Что вам не хватает, так это то, что matches
заполняется одной записью для каждой группы захвата (включая всю согласованную подстроку как 0-й захват).
Если вы пишете
std::regex needle("a(b)c");
] , то вы получите matches.size()==2
, с matches[0]=="abc"
и matches[1]=="b"
.