Boost C++ Libraries: Ticket #8564: Variable hiding errors within nested let blocks in Phoenix https://svn.boost.org/trac10/ticket/8564 <p> I encounter errors when using nested let blocks in Phoenix whenever an "inner" local variable hides an "outer" local variable. The "Visibility" example from the documentation at <a href="http://www.boost.org/doc/libs/1_53_0/libs/phoenix/doc/html/phoenix/modules/scope/let.html">http://www.boost.org/doc/libs/1_53_0/libs/phoenix/doc/html/phoenix/modules/scope/let.html</a> also fails. Here is that "Visibility" example as a standalone module which fails: </p> <pre class="wiki">#include &lt;iostream&gt; #include &lt;boost/phoenix.hpp&gt; namespace phoenix = boost::phoenix; using namespace phoenix::local_names; int main(int argc, char *argv[]) { phoenix::let(_x = 1, _y = ", World") [ phoenix::let(_x = "Hello") // hides the outer _x [ std::cout &lt;&lt; _x &lt;&lt; _y // prints "Hello, World" ] ](); return 0; } </pre><p> The errors I receive from GCC 4.7.2, GCC 4.8 snapshot, and Clang 3.2, with any of Boost 1.49, 1.53, or trunk, begin as follows: </p> <blockquote> <p> GCC: "error: function returning an array" </p> </blockquote> <blockquote> <p> Clang: "error: function cannot return array type 'result_type' (aka 'char <a class="changeset" href="https://svn.boost.org/trac10/changeset/6" title="New repository initialized by cvs2svn.">[6]</a>')" </p> </blockquote> <p> Another failing example provided in Eric Niebler's Stack Overflow answer <a class="ext-link" href="http://stackoverflow.com/questions/16408770/variable-hiding-within-nested-let-blocks-in-boost-phoenix"><span class="icon">​</span>here</a> is: </p> <pre class="wiki">int y = 0; int x = (phoenix::let(_a = 1, _b = 2)[phoenix::let(_b = 3)[ _a ]])(y); </pre><p> ...which contrasts with the following example; which does compile: </p> <pre class="wiki">int y = 0; int x = (phoenix::let(_a = 1, _b = 2)[phoenix::let(_b = _1)[ _a ]])(y); </pre> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/8564 Trac 1.4.3 John Fletcher <J.P.Fletcher@…> Sat, 08 Feb 2014 19:59:32 GMT <link>https://svn.boost.org/trac10/ticket/8564#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/8564#comment:1</guid> <description> <p> This is indeed a bug and the examples given do not work. The solution is to use either an argument e.g _1 or a local variable e.g. _a to assign value to the local variable in the inner let. </p> <p> These examples both work with the definitions </p> <pre class="wiki">namespace phoenix = boost::phoenix; using namespace phoenix::local_names; using boost::phoenix::arg_names::_1; using boost::phoenix::arg_names::_2; using boost::phoenix::arg_names::_3; using std::cout; </pre><pre class="wiki"> phoenix::let(_x = _1, _y = _2) [ let(_x = _3) // hides the outer _x [ cout &lt;&lt; _x &lt;&lt; _y // prints "Hello, World" ] ](1," World","Hello,"); cout &lt;&lt; std::endl; </pre><pre class="wiki"> phoenix::let(_x = _1, _y = _2, _z = _3) [ let(_x = _z) // hides the outer _x [ cout &lt;&lt; _x &lt;&lt; _y // prints "Hello, World" ] ](1," World","Hello,"); cout &lt;&lt; std::endl; </pre><p> I will investigate further and also change the documentation. John </p> </description> <category>Ticket</category> </item> <item> <author>John Fletcher <J.P.Fletcher@…></author> <pubDate>Sun, 09 Feb 2014 12:20:33 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/8564#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/8564#comment:2</guid> <description> <p> Further work has shown that these cases work as expected: </p> <pre class="wiki"> { int z = 3; int y = 0; int x = (phoenix::let(_a = 1, _b = 2)[phoenix::let(_b = _a)[ _a ]])(y); } </pre><pre class="wiki"> { int y = 0; int x = (phoenix::let(_a = 1, _b = 2)[phoenix::let(_b = _1)[ _a ]])(y); } </pre><pre class="wiki"> { int y = 0; int x = (phoenix::let(_a = 1, _b = 2)[phoenix::let(_b = 1)[_b]])(); } // This works.... </pre><p> but this case fails: </p> <pre class="wiki"> { int y = 0; int x = (phoenix::let(_a = 1, _b = 2)[phoenix::let(_b = 1)[_a]])(); } </pre><p> Reference to _a in the inner loop is the problem, but only when _b is set to a constant!! </p> <p> Further investigation is in progress. </p> </description> <category>Ticket</category> </item> <item> <author>John Fletcher <J.P.Fletcher@…></author> <pubDate>Sun, 09 Feb 2014 18:32:30 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/8564#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/8564#comment:3</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/8564#comment:2" title="Comment 2">John Fletcher &lt;J.P.Fletcher@…&gt;</a>: </p> <blockquote class="citation"> <p> Further work has shown that these cases work as expected </p> <pre class="wiki"> { int z = 3; int y = 0; int x = (phoenix::let(_a = 1, _b = 2)[phoenix::let(_b = _a)[ _a ]])(y); } </pre><pre class="wiki"> { int y = 0; int x = (phoenix::let(_a = 1, _b = 2)[phoenix::let(_b = _1)[ _a ]])(y); } </pre><pre class="wiki"> { int y = 0; int x = (phoenix::let(_a = 1, _b = 2)[phoenix::let(_b = 1)[_b]])(); } // This works.... </pre><p> but this case fails: </p> <pre class="wiki"> { int y = 0; int x = (phoenix::let(_a = 1, _b = 2)[phoenix::let(_b = 1)[_a]])(); } </pre><p> Reference to _a in the inner loop is the problem, but only when _b is set to a constant!! </p> <p> Further investigation is in progress. </p> </blockquote> <p> Unfortunately it is not as easy as that. The 'working' cases above fail for some compilers e.g. clang 3.4 in C++03 but not C++11. gcc 4.8.2 works for C++03 and C++11. Work is in progress. </p> </description> <category>Ticket</category> </item> <item> <author>John Fletcher <J.P.Fletcher@…></author> <pubDate>Sun, 01 Feb 2015 21:50:40 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/8564#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/8564#comment:4</guid> <description> <p> Apologies for the delay in giving further information. There is certainly a problem in Boost Phoenix V3 in the implementation of let and lambda. This shows up in various ways. In some cases code works when not optimised but fails when optimised - gcc 4.9.0 on -O1 and clang 3.5 on -O2. I know this is serious and I am working on it. The documentation is being revised and will be much more up to date with the next release of Boost. </p> </description> <category>Ticket</category> </item> </channel> </rss>