Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext
5.2.2. Evaluating the expression using boost::mpl::fold
[Note] Note

Note that you can find everything that has been included and defined so far here.

Let's use sum_items with boost::mpl::fold to build the parser that summarises the values coming from the + <number> elements. We can extend the parser we were using in exp_parser7 by wrapping the repeated<...> part with transform, which transforms the result of repeated<...> with the folding expression we have just created:

> using exp_parser8 = \
...> build_parser< \
...>   sequence< \
...>     int_token, /* parse the first <number> */ \
...>     transform< \
...>       repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */ \
...> \
...>       /* lambda expression summarising the "+ <number>" elements using fold */ \
...>       boost::mpl::lambda< \
...>         /* The folding expression we have just created */ \
...>         boost::mpl::fold< \
...>           boost::mpl::_1, /* the argument of the lambda expression, the result */ \
...>                           /* of the repeated<...> parser */ \
...>           boost::mpl::int_<0>, \
...>           boost::mpl::quote2<sum_items> \
...>         > \
...>       >::type \
...>     > \
...>   > \
...> >;

copy-paste friendly version

It uses transform to turn the result of the previous version of our parser into one that summarises the + <number> elements. Let's try it out:

> exp_parser8::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type
boost_::mpl::vector<mpl_::integral_c<int, 1>, mpl_::integral_c<int, 9> >

This returns a pair of numbers as the result of parsing: the first number and the sum of the rest. To get the value of the entire expression we need to add these two numbers together. We can extend our parser to do this final addition as well:

> using exp_parser9 = \
...> build_parser< \
...>   transform< \
...>     /* What we had so far */ \
...>     sequence< \
...>       int_token, \
...>       transform< \
...>         repeated<sequence<plus_token, int_token>>, \
...>         boost::mpl::lambda< \
...>           boost::mpl::fold< \
...>             boost::mpl::_1, \
...>             boost::mpl::int_<0>, \
...>             boost::mpl::quote2<sum_items> \
...>           > \
...>         >::type \
...>       > \
...>     >, \
...>     boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */ \
...>   > \
...> >;

copy-paste friendly version

exp_parser9 wraps the parser we had so far (which gives us the two element vector as the result) with transform to add the elements of that two element vector together. Since that two element vector is a vector of numbers, we can (re)use the sum_vector metafunction for this. Let's try it out:

> exp_parser9::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type
mpl_::integral_c<int, 10>

It gives us the correct result, but it is very inefficient. Let's see why:

There are two loops in this process:

[Note] Note

Note that we have been talking about loops while there is no such thing as a loop in template metaprogramming. Loops can be implemented using recursion: every recursive call is one iteration of the loop. The loop is stopped at the bottom of the recursive chain.


PrevUpHomeNext