Boost C++ Libraries: Ticket #4020: regex::match_results::format functor cannot use member variables https://svn.boost.org/trac10/ticket/4020 <p> regex::match_results::format makes a copy of its functor argument. This is restrictive, because it prevents the functor from managing its state using member variables. Is that intentional? </p> <p> The attached VC++ 2008 code demonstrates the problem. When it uses a member variable to maintain a count, its output is: </p> <p> (1)The (1)quick (1)brown (1)fox (1)jumped (1)over (1)the (1)lazy (1)dog </p> <p> Making the counter global instead gives the correct output: </p> <p> (1)The (2)quick (3)brown (4)fox (5)jumped (6)over (7)the (8)lazy (9)dog </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/4020 Trac 1.4.3 Keith MacDonald <keith@…> Tue, 16 Mar 2010 18:33:57 GMT attachment set https://svn.boost.org/trac10/ticket/4020 https://svn.boost.org/trac10/ticket/4020 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">RegexFunctor.zip</span> </li> </ul> Ticket Steven Watanabe Tue, 16 Mar 2010 20:27:32 GMT <link>https://svn.boost.org/trac10/ticket/4020#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4020#comment:1</guid> <description> <p> This is normal behavior for interfaces that accept function objects. Put the variables outside the function object and store a pointer or reference to them. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Wed, 17 Mar 2010 17:04:28 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4020#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4020#comment:2</guid> <description> <p> As Steven says, this is the expected behaviour. </p> <p> However, I will try and make that clearer in the docs, and I'll trivially update the code so that it works with boost::ref. </p> <p> John. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>John Maddock</dc:creator> <pubDate>Wed, 17 Mar 2010 18:20:16 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/4020#comment:3 https://svn.boost.org/trac10/ticket/4020#comment:3 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> (In <a class="changeset" href="https://svn.boost.org/trac10/changeset/60678" title="Add support for Boost.Ref in match_results::format. Update docs ...">[60678]</a>) Add support for Boost.Ref in match_results::format. Update docs accordingly. Fixes <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/4020" title="#4020: Support Requests: regex::match_results::format functor cannot use member variables (closed: fixed)">#4020</a>. </p> Ticket Keith MacDonald <keith@…> Thu, 18 Mar 2010 16:32:42 GMT <link>https://svn.boost.org/trac10/ticket/4020#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4020#comment:4</guid> <description> <p> Thanks for the clarification. Returning to C++ after a break, I had forgotten that it was a standard library convention to pass functors by value. Anyway, I've amended my example code to take account of that, and you're welcome to use it in the documentation: </p> <pre class="wiki">// Code to insert an incremented count before each word in the source text. #include &lt;stdlib.h&gt; #include &lt;iostream&gt; #include &lt;sstream&gt; #include &lt;boost/regex.hpp&gt; #include &lt;boost/shared_ptr.hpp&gt; typedef wchar_t char_t; typedef std::wstring string_t; template &lt;class M&gt; class functor { public: functor() : m_pImpl(new functor_data) {} template &lt;class O&gt; O operator()(const M&amp; m, O i) { // Generate the sequence number in brackets: char_t buf[16]; O i2(i); *i2++ = L'('; _itow(++m_pImpl-&gt;nCounter, buf, 10); i2 = std::copy(buf, buf + wcslen(buf), i2); *i2++ = L')'; // Copy the matched text; return m.format(i2, L"$0"); } private: struct functor_data { functor_data() : nCounter(0) {} int nCounter; }; boost::shared_ptr&lt;functor_data&gt; m_pImpl; }; int wmain(int argc, char_t* argv[]) { string_t sText(L"The quick brown fox jumped over the lazy dog"); string_t sRE(L"\\w+"); boost::regex_constants::match_flag_type matchFlags = boost::regex_constants::match_default; boost::basic_regex&lt;char_t&gt; e; e.assign(sRE, matchFlags); typedef string_t::const_iterator string_iterator; boost::regex_iterator&lt;string_iterator&gt; reit(sText.begin(), sText.end(), e, matchFlags); boost::regex_iterator&lt;string_iterator&gt; reEnd; boost::match_results&lt;string_iterator&gt; last_m = *reit; std::basic_ostringstream&lt;char_t&gt; stream; std::ostream_iterator&lt;char_t, char_t&gt; streamIter(stream); functor&lt;boost::match_results&lt;string_iterator&gt; &gt; func; for ( ; reit != reEnd; ++reit) { const boost::match_results&lt;string_iterator&gt;&amp; m = *reit; // copy the source up to this match: std::copy(m.prefix().first, m.prefix().second, streamIter); // replace the matched text: m.format(streamIter, func); last_m = m; } // copy the remainder of the source string: std::copy(last_m.suffix().first, last_m.suffix().second, streamIter); // output the result: std::wcout &lt;&lt; stream.str() &lt;&lt; std::endl; return 0; } </pre> </description> <category>Ticket</category> </item> </channel> </rss>