Home | Libraries | People | FAQ | More |
Note | |
---|---|
Note that you can find everything that has been included and defined so far here. |
The final result here is a pair of the first number and the vector
of the rest of the values. To
calculate the result we need to process that data structure. Let's give
the example output we have just parsed a name. This will make it easier
to test the code calculating the final result from this structure:
> using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
Now we can write a template metafunction turning this structure into the result of the calculation this structure represents.
Note | |
---|---|
Note that you can find everything that has been included and defined so far here. |
We have a vector
containing
another vector
. Therefore,
we will need to be able to summarise the elements of different vector
s. We can use the boost::mpl::fold
metafunction
to do this:
> #include <boost/mpl/fold.hpp>
With this metafunction, we can iterate
over a vector
of parsed
numbers and summarise them. We can provide it a metafunction
taking two arguments: the sum we have so far and the next element of
the vector
. This metafunction will be called for every element
of the vector
.
Note | |
---|---|
Note that this is very similar to the |
Let's start with a simple case: a vector
of numbers. For example let's summarise the elements of the following
vector
:
> using vector_of_numbers = \ ...> boost::mpl::vector< \ ...> boost::mpl::int_<2>, \ ...> boost::mpl::int_<5>, \ ...> boost::mpl::int_<6> \ ...> >;
We will write a template metafunction,
sum_vector
for summarising
the elements of a vector
of numbers:
> template <class Vector> \ ...> struct sum_vector : \ ...> boost::mpl::fold< \ ...> Vector, \ ...> boost::mpl::int_<0>, \ ...> boost::mpl::lambda< \ ...> boost::mpl::plus<boost::mpl::_1, boost::mpl::_2> \ ...> >::type \ ...> > \ ...> {};
This metafunction takes the vector
to summarise the elements of
as its argument and uses boost::mpl::fold
to calculate the sum. boost::mpl::fold
takes three arguments:
Vector
.
0
means that we
want to start the sum from 0
.
boost::mpl::lambda
. This expression adds its
two arguments together using boost::mpl::plus
.
The lambda expression refers to its arguments by boost::mpl::_1
and boost::mpl::_2
.
Let's try this metafunction out:
> sum_vector<vector_of_numbers>::type mpl_::integral_c<int, 13>
It works as expected. Here is a diagram showing how it works:
As the diagram shows, boost::mpl::fold
evaluates the lambda expression for each element of the vector
and passes the result of the
previous evaluation to the next lambda expression invocation.
We have a metafunction that can summarise
a vector
of numbers.
The result of parsing the + <number>
elements is a vector
of vector
s. As a recap,
here is temp_result
:
boost_::mpl::vector< // The result of int_token mpl_::integral_c<int, 1>, // The result of repeated< sequence<plus_token, int_token> > boost_::mpl::vector< boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 2> >, boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 3> >, boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 4> > > >
First let's summarise the result of repeated
<...>
using boost::mpl::fold
. This is a vector
of vector
s, but that's
fine. boost::mpl::fold
doesn't care about what the elements
of the vector
are. They
can be numbers, vector
s
or something else as well. The function we use to add two numbers together
(which was a lambda expression in our previous example) gets these elements
as its argument and has to deal with them. So to summarise the elements
of the vector
s we get
as the result of parsing with repeated
<...>
,
we need to write a metafunction that
can deal with these elements. One such element is boost_::mpl::vector<mpl_::char<'+'>,
mpl_::integral_c<int, 2>>
.
Here is a metafunction that can be
used in a boost::mpl::fold
:
> template <class Sum, class Item> \ ...> struct sum_items : \ ...> boost::mpl::plus< \ ...> Sum, \ ...> typename boost::mpl::at_c<Item, 1>::type \ ...> > \ ...> {};
This function takes two arguments:
Sum
, which is a number.
This is the summary of the already processed elements.
Item
, the next item
of the vector
. These
items are vector
s
of size two: the result of parsing the +
symbol and the number.
The metafunction adds the sum we
have so far and the next number together using the boost::mpl::plus
metafunction. To get the next number
out of Item
, it uses
boost::mpl::at_c
. Let's try sum_items
out:
> sum_items< \ ...> mpl_::integral_c<int, 1>, \ ...> boost::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 2>> \ ...> >::type mpl_::integral_c<int, 3>
We have called sum_items
with values from temp_result
and saw that it works as expected: it added the partial sum (mpl_::integral_c<int, 1>
)
to the next number (mpl_::integral_c<int, 2>
).
boost::mpl::fold
can summarise the list we get
as the result of parsing the +
<number>
elements of the input, so we need
to extract this list from temp_result
first:
> boost::mpl::at_c<temp_result, 1>::type
Here is the formatted version of the result:
boost_::mpl::vector< boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 2>>, boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 3>>, boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 4>> >
This is the second element of the temp_result
vector (the first one is the value of the first <number>
element). Let's try fold out for this:
> \ ...> boost::mpl::fold< \ ...> boost::mpl::at_c<temp_result, 1>::type, /* The vector to summarise */ \ ...> boost::mpl::int_<0>, /* The value to start the sum from */ \ ...> boost::mpl::quote2<sum_items> /* The function to call in each iteration */ \ ...> >::type mpl_::integral_c<int, 9>
Note | |
---|---|
We are using |
As we have seen, the result of this is the sum of the elements, which
was 9
in our case. Here is
a diagram showing how boost::mpl::fold
works:
It starts with the value boost::mpl::int_<0>
and adds the elements of the boost_::mpl::vector
containing the parsing results one by one. The diagram shows how the
subresults are calculated and then used for further calculations.