Boost logo

Boost :

Subject: Re: [boost] New libraries implementing C++11 features in C++03
From: Joel de Guzman (joel_at_[hidden])
Date: 2011-11-23 20:11:19


On 11/24/2011 8:06 AM, Brent Spillner wrote:
> On 23 Nov 2011 10:21:50 Joel de Guzman wrote:
>> a good approximation of lambda is already existing in Boost. Namely: bind,
>> lambda and phoenix. I posted a Spirit example of lambda in action using
>> Phoenix:
>>
>> http://tinyurl.com/7w2h2r9
>>
>> Try as hard as you can, but you cannot ever come close to the clarity of
>> he syntax presented there. Proponents of locals have cited error-messages
>> generated by the compiler as a justification for Locals. Locals is probably
>> a good workaround. But hear me out...
>
> First of all, this "trivial" example didn't even compile on the first
> machine I tried it on, which had Boost 1.45 (which doesn't expose
> qi:_val_type or qi:_1_type). This is a pretty good reminder of the

Man! Of course you should use the examples in 1.45. Those examples
are for 1.48 and uses new features implemented in 1.48! Sheesh!

> On a machine with 1.48, the example compiles just fine. If you were
> to pass std::string::iterators instead of const_iterators to
> phrase_parse(), though ( a pretty common class of mistake in the real
> world), you get this error message (GCC 4.4.4):
>

Double Sheesh! If you've spent even a few seconds looking into the
error (beyond fault-finding), you will see that a simple textual
search of "error" will reveal this:

> ------------------- Horrific error messages follow ---------------------

calc3.cpp:90: instantiated from here
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:176: error: no
matching function for call to
'assertion_failed(mpl_::failed************
(boost::spirit::qi::rule<Iterator, T1, T2, T3,
T4>::define(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, const
Expr&, mpl_::false_)

[snip ... some complex types]

::error_invalid_expression::************)

And double clicking on it using your editor will lead you here:

        static void define(rule& lhs, Expr const& expr, mpl::false_)
        {
            // Report invalid expression error as early as possible.
            // If you got an error_invalid_expression error message here,
            // then the expression (expr) is not a valid spirit qi expression.
            BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
        }

If you've read the Spirit docs, you will know what that means.

Now having said that, and before I leave this thread, let me remind
everyone that **you can also have statement syntax in Phoenix** if you
have a complex statement and you fear writing complex phoenix lambda
expressions. It's called phoenix::functions.

In fact here's what I advocate:

1) For simple 1-2-3 liners, use a phoenix lambda expression. It's hard
   to get them wrong. For example, you'll have to be absurdly dumb to
   get this wrong:

     auto plus = _1 + _2;

2) For more complex expressions, especially those involving statements,
   use a phoenix function plus a simple lambda expression that forwards
   to the phoenix function. Example:

     for_each(f, l, call_complex_function(_1));

Regards,

-- 
Joel de Guzman
http://www.boostpro.com
http://boost-spirit.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk