Safe, simultaneous string replacement I've written a function which takes as an input:


a string to be modified
a vector of regular expressions on which to match
a vector of replacements
option to ignore case in the match statements


The function will then, from the users perspective, simultaneously perform all replacements in a 'safe' fashion. By 'safe' I mean sub-string matches are ignored in favor of longer matches (if 'the' and 'they' are patterns to match, ignore the sub-string 'the' in 'they') and also allow users to have cross-replacement (swap 'hey' for 'ho' and 'ho' for 'hey').

Examples:

rcpp_mgsub("hey ho",{"hey","ho"},{"ho","hey"},true)
// Expect "ho hey"
rcpp_mgsub("Hey, how are you?",{"hey","how","are","you"},{"how","are","you","hey"},true)
// Expect "how, are you hey?"


I've written a function in the R programming language that accomplishes this, but R isn't a fast language. R libraries can include pre-compiled C++11 code which can result in vastly faster functions.  To this end, I've written a C++11 function but the performance is actually significantly slower than R (3-7x slower in various comparisons I've done) so I realize there must be some significant inefficiencies in my function.

So, I'm curious what inefficiencies are present in the rcpp_mgsub function that I should focus on improving.

#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;regex&gt;

std::string rcpp_mgsub(std::string string, std::vector&lt;std::string&gt; const&amp; match, std::vector&lt;std::string&gt; const&amp; replace, bool const&amp; ic) {
  std::string newString = "";
  std::smatch matches;
  std::string prefix = string;
  std::string detected;
  std::string suffix;

  std::regex::flag_type flags;
  flags |= std::regex_constants::optimize;
  if(ic) flags |= std::regex_constants::icase;

  std::vector&lt;std::regex&gt; r(match.size());
  std::transform(match.begin(), match.end(), r.begin(),
                 [&amp;flags](std::string m) {return std::regex (m, flags);});

  int j=0;
  while(string.size() &gt; 0){
    prefix = string;
    detected = "";
    suffix = "";
    j = 0;
    for(int i=0;i &lt; match.size();i++){
      if (std::regex_search(string,matches, r[i])) {
        std::string pr = matches.prefix();
        std::string m = matches[0];
        if(pr.size() &lt; prefix.size() || (pr.size() == prefix.size() &amp;&amp; m.size() &gt; detected.size())){
          prefix = pr;
          detected = m;
          suffix = matches.suffix();
          j=i;
        }
      }
    }
    if(prefix == string){
      newString = newString+string;
      string = "";
    } else {
      newString = newString+prefix+std::regex_replace(detected,r[j],replace[j],std::regex_constants::format_sed);
      string = suffix;
    }
  }
  return newString;
}


int main()
{
   std::cout &lt;&lt; rcpp_mgsub("hey ho hey",{"hey","ho"},{"ho","hey"},true) &lt;&lt; "\n";
   std::cout &lt;&lt; rcpp_mgsub("Hey, how are you?",{"hey","how","are","you"},{"how","are","you","hey"},true) &lt;&lt; "\n";
   std::cout &lt;&lt; rcpp_mgsub("Dopazamine is not the same as Dopachloride and is still fake.",{"[Dd]opa(.*?mine)","fake"},{"Meta\\1","real"},false);
   return(0);
}
What compiler are you using? Some implementations of the C++ standard library are better than others for supporting Regex.

Do you really need backreferences? That usually makes regex much slower.

It's very unusual to use a variable with the same name as the variable's type.

You don't need to initialize prefix=string before the loop, it's done first thing inside the loop.

Have you done any profiling of your code to see which lines are slowing it down? It'd be very good to know if the slowness is due to the regex or due to the string concatenation.