Boost C++ Libraries: Ticket #9580: [spirit.lex] self("state") += calls a wrong operator += https://svn.boost.org/trac10/ticket/9580 <p> This construct </p> <div class="wiki-code"><div class="code"><pre> <span class="k">this</span><span class="o">-&gt;</span><span class="n">self</span><span class="p">(</span><span class="s">&quot;SOME_STATE&quot;</span><span class="p">)</span> <span class="o">+=</span> <span class="n">someTokenDef</span><span class="p">;</span> </pre></div></div><p> doesn't call </p> <div class="wiki-code"><div class="code"><pre> <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">LexerDef</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Expr</span><span class="o">&gt;</span> <span class="kr">inline</span> <span class="n">lexer_def_</span><span class="o">&lt;</span><span class="n">LexerDef</span><span class="o">&gt;&amp;</span> <span class="n">boost</span><span class="o">::</span><span class="n">spirit</span><span class="o">::</span><span class="n">lex</span><span class="o">::</span><span class="n">detail</span><span class="o">::</span><span class="k">operator</span><span class="o">+=</span> <span class="p">(</span><span class="n">lexer_def_</span><span class="o">&lt;</span><span class="n">LexerDef</span><span class="o">&gt;&amp;</span> <span class="n">lexdef</span><span class="p">,</span> <span class="n">Expr</span><span class="o">&amp;&amp;</span> <span class="n">xpr</span><span class="p">)</span> </pre></div></div><p> as it should in order for the definition get added to the lexer. Instead this operator </p> <div class="wiki-code"><div class="code"><pre> <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Left</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Right</span><span class="o">&gt;</span> <span class="k">typename</span> <span class="n">boost</span><span class="o">::</span><span class="n">proto</span><span class="o">::</span><span class="n">detail</span><span class="o">::</span><span class="n">enable_binary</span><span class="o">&lt;</span> <span class="n">deduce_domain</span> <span class="p">,</span> <span class="n">deduce_domain</span><span class="o">::</span><span class="n">proto_grammar</span> <span class="p">,</span> <span class="n">boost</span><span class="o">::</span><span class="n">mpl</span><span class="o">::</span><span class="n">or_</span><span class="o">&lt;</span><span class="n">is_extension</span><span class="o">&lt;</span><span class="n">Left</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">is_extension</span><span class="o">&lt;</span><span class="n">Right</span><span class="o">&gt;</span> <span class="o">&gt;</span> <span class="p">,</span> <span class="n">boost</span><span class="o">::</span><span class="n">proto</span><span class="o">::</span><span class="n">tag</span><span class="o">::</span><span class="n">plus_assign</span> <span class="p">,</span> <span class="n">Left</span> <span class="k">const</span> <span class="o">&amp;</span> <span class="p">,</span> <span class="n">Right</span> <span class="k">const</span> <span class="o">&amp;</span> <span class="o">&gt;::</span><span class="n">type</span> <span class="k">const</span> <span class="k">operator</span> <span class="o">+=</span><span class="p">(</span><span class="n">Left</span> <span class="o">&amp;&amp;</span><span class="n">left</span><span class="p">,</span> <span class="n">Right</span> <span class="o">&amp;&amp;</span><span class="n">right</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">boost</span><span class="o">::</span><span class="n">proto</span><span class="o">::</span><span class="n">detail</span><span class="o">::</span><span class="n">make_expr_</span><span class="o">&lt;</span> <span class="n">boost</span><span class="o">::</span><span class="n">proto</span><span class="o">::</span><span class="n">tag</span><span class="o">::</span><span class="n">plus_assign</span> <span class="p">,</span> <span class="n">deduce_domain</span> <span class="p">,</span> <span class="n">Left</span> <span class="k">const</span> <span class="o">&amp;</span> <span class="p">,</span> <span class="n">Right</span> <span class="k">const</span> <span class="o">&amp;</span> <span class="o">&gt;</span><span class="p">()(</span><span class="n">left</span><span class="p">,</span> <span class="n">right</span><span class="p">);</span> <span class="p">}</span> </pre></div></div><p> is called from boost::proto::exprns_ namespace. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/9580 Trac 1.4.3 Joel de Guzman Thu, 16 Jan 2014 00:39:13 GMT owner changed https://svn.boost.org/trac10/ticket/9580#comment:1 https://svn.boost.org/trac10/ticket/9580#comment:1 <ul> <li><strong>owner</strong> changed from <span class="trac-author">Joel de Guzman</span> to <span class="trac-author">Hartmut Kaiser</span> </li> </ul> Ticket Vyacheslav Andrejev Thu, 16 Jan 2014 07:58:09 GMT <link>https://svn.boost.org/trac10/ticket/9580#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9580#comment:2</guid> <description> <p> An example that demonstrates the problem: </p> <div class="wiki-code"><div class="code"><pre><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf">&lt;boost/spirit/include/lex_lexertl.hpp&gt;</span><span class="cp"></span> <span class="k">using</span> <span class="k">namespace</span> <span class="n">boost</span><span class="o">::</span><span class="n">spirit</span><span class="p">;</span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Lexer</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="nl">tokens</span> <span class="p">:</span> <span class="k">public</span> <span class="n">lex</span><span class="o">::</span><span class="n">lexer</span><span class="o">&lt;</span><span class="n">Lexer</span><span class="o">&gt;</span> <span class="p">{</span> <span class="n">tokens</span><span class="p">()</span> <span class="p">{</span> <span class="n">someTokenDef</span> <span class="o">=</span> <span class="sc">&#39;&quot;&#39;</span><span class="p">;</span> <span class="k">auto</span> <span class="n">expr</span> <span class="o">=</span> <span class="p">(</span><span class="k">this</span><span class="o">-&gt;</span><span class="n">self</span><span class="p">(</span><span class="s">&quot;SOME_STATE&quot;</span><span class="p">)</span> <span class="o">+=</span> <span class="n">someTokenDef</span><span class="p">);</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;Arity = &quot;</span> <span class="o">&lt;&lt;</span> <span class="n">expr</span><span class="p">.</span><span class="n">proto_arity_c</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;, should be 0&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;token_id_ = &quot;</span> <span class="o">&lt;&lt;</span> <span class="n">someTokenDef</span><span class="p">.</span><span class="n">id</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;, should be 65536&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;unique_id_ = &quot;</span> <span class="o">&lt;&lt;</span> <span class="n">someTokenDef</span><span class="p">.</span><span class="n">unique_id</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;, should be 0&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;token_state_ = &quot;</span> <span class="o">&lt;&lt;</span> <span class="n">someTokenDef</span><span class="p">.</span><span class="n">state</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;, should be 1&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> <span class="p">}</span> <span class="n">lex</span><span class="o">::</span><span class="n">token_def</span><span class="o">&lt;&gt;</span> <span class="n">someTokenDef</span><span class="p">;</span> <span class="p">};</span> <span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span><span class="o">*</span> <span class="n">argv</span><span class="p">[])</span> <span class="p">{</span> <span class="k">typedef</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">iterator</span> <span class="n">base_iterator_type</span><span class="p">;</span> <span class="k">typedef</span> <span class="n">lex</span><span class="o">::</span><span class="n">lexertl</span><span class="o">::</span><span class="n">token</span><span class="o">&lt;</span> <span class="n">base_iterator_type</span> <span class="p">,</span> <span class="n">boost</span><span class="o">::</span><span class="n">mpl</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;&gt;</span> <span class="o">&gt;</span> <span class="n">token_type</span><span class="p">;</span> <span class="k">typedef</span> <span class="n">lex</span><span class="o">::</span><span class="n">lexertl</span><span class="o">::</span><span class="n">lexer</span><span class="o">&lt;</span><span class="n">token_type</span><span class="o">&gt;</span> <span class="n">lexer_type</span><span class="p">;</span> <span class="k">typedef</span> <span class="n">tokens</span><span class="o">&lt;</span><span class="n">lexer_type</span><span class="o">&gt;</span> <span class="n">a_lexer</span><span class="p">;</span> <span class="n">a_lexer</span> <span class="n">lexer</span><span class="p">;</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span> </pre></div></div><p> The program above outputs: </p> <pre class="wiki">Arity = 2, should be 0 token_id_ = 0, should be 65536 unique_id_ = 18446744073709551615, should be 0 token_state_ = 18446744073709551615, should be 1 </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>Vyacheslav Andrejev</dc:creator> <pubDate>Wed, 29 Jan 2014 08:20:13 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9580#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9580#comment:3</guid> <description> <p> I found a workaround: </p> <div class="wiki-code"><div class="code"><pre> <span class="k">auto</span> <span class="n">lex_def</span> <span class="o">=</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">self</span><span class="p">(</span><span class="s">&quot;SOME_STATE&quot;</span><span class="p">);</span> <span class="k">auto</span> <span class="n">expr</span> <span class="o">=</span> <span class="p">(</span><span class="n">lex_def</span> <span class="o">+=</span> <span class="n">someTokenDef</span><span class="p">);</span> </pre></div></div><p> With this change the output is </p> <pre class="wiki">Arity = 0, should be 0 token_id_ = 65536, should be 65536 unique_id_ = 0, should be 0 token_state_ = 1, should be 1 </pre><p> I checked the WAR with GCC 4.8 and MSVC 12.0. </p> <p> Any clue what is going on? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Vyacheslav Andrejev</dc:creator> <pubDate>Thu, 30 Jan 2014 15:52:29 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9580#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9580#comment:4</guid> <description> <p> I found out what is going on. An rvalue cannot be bound to a non-const reference. <code>boost::spirit::lex::detail::operator+=</code> has a non-const reference as the first parameter and <code>this-&gt;self("SOME_STATE")</code> returns an rvalue. Therefore the compiler doesn't call <code>boost::spirit::lex::detail::operator+=</code>, but uses <code>template &lt;typename Left, typename Right&gt; operator +=(Left &amp;&amp;left, Right &amp;&amp;right)</code> from <code>boost::proto::expns_</code> instead. A solution could be adding another definition of <code>boost::spirit::lex::detail::operator+=</code>: </p> <div class="wiki-code"><div class="code"><pre> <span class="c1">// allow to assign a token definition expression</span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">LexerDef</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Expr</span><span class="o">&gt;</span> <span class="kr">inline</span> <span class="n">lexer_def_</span><span class="o">&lt;</span><span class="n">LexerDef</span><span class="o">&gt;&amp;</span> <span class="k">operator</span><span class="o">+=</span> <span class="p">(</span><span class="n">lexer_def_</span><span class="o">&lt;</span><span class="n">LexerDef</span><span class="o">&gt;&amp;&amp;</span> <span class="n">lexdef</span><span class="p">,</span> <span class="n">Expr</span><span class="o">&amp;&amp;</span> <span class="n">xpr</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// Report invalid expression error as early as possible.</span> <span class="c1">// If you got an error_invalid_expression error message here,</span> <span class="c1">// then the expression (expr) is not a valid spirit lex </span> <span class="c1">// expression.</span> <span class="n">BOOST_SPIRIT_ASSERT_MATCH</span><span class="p">(</span><span class="n">lex</span><span class="o">::</span><span class="n">domain</span><span class="p">,</span> <span class="n">Expr</span><span class="p">);</span> <span class="n">lexdef</span><span class="p">.</span><span class="n">define</span><span class="p">(</span><span class="n">xpr</span><span class="p">);</span> <span class="k">return</span> <span class="n">lexdef</span><span class="p">;</span> <span class="p">}</span> </pre></div></div><p> Do we have some kind of virtual regression system I could test my changes in before forming a pull request? </p> </description> <category>Ticket</category> </item> </channel> </rss>