I don't think such a callback would be useful to the OP. If the callback merely accepts the matched string, it would need to reparse the string to find the sub-matches. In addition, accepting and returning strings imposes unnecessary dynamic allocations.
Xpressive's regex_replace() algorithm can accept a formatter function or function object with one of three different signatures. It can either:
a) Accept the match_results object, and return a std::string, or b) Accept the match_results object and an output iterator, and return the output iterator, or b) Accept the match_results object, an output iterator and the match flags, and return the output iterator.
You can read about it here: http://tinyurl.com/bd6c3f. I like this interface because it gives the formatter object lots of context and makes formatting potentially very efficient.
It would be great if Boost.Regex and Boost.Xpressive settled on a common callback interface for regex_replace().
I think the interface you have there is very good - I'd always assumed that the callback would accept a match_results not a string - as you say the performance would be just so much better... John.