Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems with the two parameter format function in boost::regex_replace

I am having problems with the format function in boost::regex_replace. I can call the one parameter version of it, but not the two parameter:

e = "(^|>)([^<>]+)";
h_str = regex_replace(h_str, e, repl_quot, boost::match_default);

Where repl_quot is defined as

std::string const &repl_quot(boost::smatch const &what) {
    boost::regex e("\"");
    std::string  repl("&#34;");
    static std::string;
    str = regex_replace(what[0].str(), e, repl, boost::match_default);
    return str;
}

The above works, but I don't really want to use that static variable, so I tried what I thought was an acceptable two parameter alternate version:

std::string const &repl_quot2(boost::smatch const &what, std::string &out) {
    boost::regex e("\"");
    std::string  repl("&#34;");
    out = regex_replace(what[0].str(), e, repl, boost::match_default);
    return out;
}

But regex_replace won't accept this (a convoluted compiler error). I am trying to use the two parameter version based on the following from the Boost::Regex documentation:

template basic_string regex_replace(const basic_string& s, const basic_regex& e, Formatter fmt, match_flag_type flags = match_default);

Requires The type Formatter must be either ... a unary, binary or ternary functor that computes the replacement string from a function call: either fmt(what) which must return a container of char_type's to be used as the replacement text, or either fmt(what, out) or fmt(what, out, flags), both of which write the replacement text to *out, and then return the new OutputIterator position. In each case what is the match_results object that represents the match found.

There have been repeated requests for the compiler error message, so here it is (be careful what you ask for):

c:\boost\boost\regex\v4\regex_format.hpp In member function `OutputIter boost::re_detail::format_functor_container::operator()(const Match&, OutputIter, boost::regex_constants::match_flag_type, const Traits&) [with OutputIter = boost::re_detail::string_out_iterator, std::allocator > >, Container = const std::string&(*)(const boost::smatch&, std::string&), Match = boost::match_results<__gnu_cxx::__normal_iterator, std::allocator > >, std::allocator, std::allocator > > > > >, Traits = boost::regex_traits_wrapper > >]':

356 c:\boost\boost\regex\v4\match_results.hpp instantiated from `OutputIterator boost::match_results::format(OutputIterator, Functor, boost::regex_constants::match_flag_type, const RegexT&) const [with OutputIterator = boost::re_detail::string_out_iterator, std::allocator > >, Functor = const std::string&(*)(const boost::smatch&, std::string&), RegexT = boost::basic_regex > >, BidiIterator = __gnu_cxx::__normal_iterator, std::allocator > >, Allocator = std::allocator, std::allocator > > > >]'

60 c:\boost\boost\regex\v4\regex_replace.hpp instantiated from `OutputIterator boost::regex_replace(OutputIterator, BidirectionalIterator, BidirectionalIterator, const boost::basic_regex&, Formatter, boost::regex_constants::match_flag_type) [with OutputIterator = boost::re_detail::string_out_iterator, std::allocator > >, BidirectionalIterator = __gnu_cxx::__normal_iterator, std::allocator > >, traits = boost::regex_traits >, charT = char, Formatter = const std::string&(*)(const boost::smatch&, std::string&)]'

80 c:\boost\boost\regex\v4\regex_replace.hpp instantiated from `std::basic_string, std::allocator<_T2> > boost::regex_replace(const std::basic_string, std::allocator<_T2> >&, const boost::basic_regex&, Formatter, boost::regex_constants::match_flag_type) [with traits = boost::regex_traits >, charT = char, Formatter = const std::string&(*)(const boost::smatch&, std::string&)]'

327 C:\Dev-Cpp\Examples\wordrad\xhtml_open.cpp instantiated from here

1064 c:\boost\boost\regex\v4\regex_format.hpp request for member begin' in((boost::re_detail::format_functor_container, std::allocator > >, std::allocator, std::allocator > > > > >, boost::regex_traits_wrapper > > >*)this)->boost::re_detail::format_functor_container, std::allocator > >, std::allocator, std::allocator > > > > >, boost::regex_traits_wrapper > > >::func', which is of non-class type `const std::string&(* const)(const boost::smatch&, std::string&)'

1064 c:\boost\boost\regex\v4\regex_format.hpp request for member end' in((boost::re_detail::format_functor_container, std::allocator > >, std::allocator, std::allocator > > > > >, boost::regex_traits_wrapper > > >*)this)->boost::re_detail::format_functor_container, std::allocator > >, std::allocator, std::allocator > > > > >, boost::regex_traits_wrapper > > >::func', which is of non-class type `const std::string&(* const)(const boost::smatch&, std::string&)'

like image 441
Mark Avatar asked Jan 30 '11 03:01

Mark


1 Answers

OK here's how I had to write repl_quot2:

struct formatter
{       
  template<typename Out>
  Out operator()(boost::smatch const &what, Out out) const {
    boost::regex e("\"");    
    std::string  repl("&#34;");
    std::string str
      = regex_replace(what[0].str(), e, repl, boost::match_default);
    out = std::copy(str.begin(), str.end(), out);
    return out;
  }

};

And then when invoking it from regex_replace:

  e = "(^|>)[^<>]+";
  formatter repl_quot2;
  h_str = regex_replace(h_str, e, repl_quot2, boost::match_default);

This corresponds to the documentation at http://boost-sandbox.sourceforge.net/libs/xpressive/doc/html/boost_xpressive/user_s_guide/string_substitutions.html.

What puzzles me at the moment is that it requires a functor (a class with the () operator) as opposed to a function if the two parameter version is called, but did not require a functor for the one parameter versions (repl_quot in the OP). Anyway, haven't gotten the new two parm version to work as a straight function. But the main problem was out which I had to pass and return as a template parameter as shown, as opposed to making it std::string as in the OP. Its supposed to be an OutputIterator -still don't know what that is actually.

Incidentally, all this regex does is replace double quotes with the html entity version, \&#34; in any text in html not part of a tag.

Also, the reason I wanted to replace my original function repl_quot is that I had to store the return value in a static local variable in repl_quot. It doesn't work to just return a normal local variable, because it can be deallocated before it can even be used (and caused crashes). repl_quot was working - my problem with the static is that it isn't thread safe, and didn't know if Boost::RegEx was multithreading. I think I compiled it as multithreading, but the static var didn't seem to cause problems. But with repl_quot2 I write the return value to an output parameter.

like image 52
Mark Avatar answered Oct 13 '22 00:10

Mark