8
votes

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&)'

1
You should post the error you're getting.Eric Fortin
Its absurdly long. I predict you wouldn't make heads or tails of it. Its template related or something. The problem is with what regex-replace is expecting as a signature for the fmt parameter, petaining to templates or whatever. THe error message is indecipherable.Mark
1064 c:\boost\boost\regex\v4\regex_format.hpp request for member end' in ((boost::re_detail::format_functor_container<const std::string&()(const boost::smatch&, std::string&), boost::match_results<__gnu_cxx::__normal_iterator<const char, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<boost::sub_match<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >, boost::regex_traits_wrapper<boost::regex_traits<char, boost::cpp_regex_traits<char> > > >*)this)->boost::re_detail::format_fu...Mark
I think there is something missing in the line static std::string;, or the semicolon must be removed there. And I don't think str needs to be static in that example. Can you post the whole error message in the question, as these comments are not long enough for the complete error message.wimh
Wimmel - the version with static std::string in it is the one that's working. Even the other version repl_quot2 actually compiles. The compiler error occurs if I pass repl_quot2 as a parameter to regex_replace (insead of repl_quot) because the parameters and return value of regex_quot2 don't conform to what regex_replace is expecting, and I don't know what it wants. You can see from the documentation excerpt that a function of one two or three parameters is acceptable. It also says that with two parameters, you write the replacement text to *out and return the new "OutputIterator" pos...Mark

1 Answers

1
votes

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.