Home | Libraries | People | FAQ | More |
Note | |
---|---|
Note that you can find everything that has been included and defined so far here. |
To fix the evaluation of expressions containing subtractions, we need to fix the function we use for summarising. We need to write a version that takes the operator being used into account.
First of all we will need the boost::mpl::minus
metafunction for implementing subtraction:
> #include <boost/mpl/minus.hpp>
Let's write a helper metafunction that takes three arguments: the left operand, the operator and the right operand:
> template <class L, char Op, class R> struct eval_binary_op; > template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {}; > template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
The first command declares the eval_binary_op
metafunction. The first and third arguments are the left and right operands
and the second argument is the operator.
Note | |
---|---|
Note that it does not satisfy the expectations of a template
metafunction since it takes the operator as a |
The second and third commands define the operation for the cases when the
operator is +
and -
. When the eval_binary_op
metafunction is called, the C++ compiler chooses one of the definitions
based on the operator. If you have functional programming experience this
approach (pattern matching) might be familiar to you. Let's try eval_binary_op
out:
> eval_binary_op<boost::mpl::int_<11>, '+', boost::mpl::int_<2>>::type mpl_::integral_c<int, 13> > eval_binary_op<boost::mpl::int_<13>, '-', boost::mpl::int_<2>>::type mpl_::integral_c<int, 11>
You might also try to use it with an operator it does not expect (yet).
For example '*'
. You will see
the C++ compiler complaining about that the requested version of the eval_binary_op
template has not been
defined. This solution can be extended and support for the '*'
operator can always be added later.
Let's write the metafunction we can
use from the folding parser to evaluate the expressions using +
and -
operators. This takes two arguments:
(+|-)
<number>
. This a vector
containing two elements: a character representing the operator (+
or -
)
and the value of the <number>
.
The number is the right operand.
Let's write the metafunction binary_op
that takes these arguments
and calls eval_binary_op
:
> template <class S, class Item> \ ...> struct binary_op : \ ...> eval_binary_op< \ ...> S, \ ...> boost::mpl::at_c<Item, 0>::type::value, \ ...> typename boost::mpl::at_c<Item, 1>::type \ ...> > \ ...> {};
This metafunction takes the operator
(the first element) and the right operand (the second element) from Item
. The operator is a class representing
a character, such as mpl_::char_<'+'>
.
To get the character value out of it, one has to access its ::value
.
For example mpl_::char<'+'>::value
is '+'
. Since eval_binary_op
takes this character value as its second argument, we had to pass boost::mpl::at_c<Item, 0>::type::value
to it. Let's try it out:
> binary_op<boost::mpl::int_<11>, boost::mpl::vector<boost::mpl::char_<'+'>, boost::mpl::int_<2>>>::type mpl_::integral_c<int, 13>
We passed it a number (11
)
and a vector
of a character
(+
) and another number (2
). It added the two numbers as expected.
Let's use this function as the third argument of foldl_start_with_parser
:
> using exp_parser13 = \ ...> build_parser< \ ...> foldl_start_with_parser< \ ...> sequence<one_of<plus_token, minus_token>, int_token>, \ ...> int_token, \ ...> boost::mpl::quote2<binary_op> \ ...> > \ ...> >;
It uses binary_op
instead
of sum_items
. Let's try
it out:
> exp_parser13::apply<BOOST_METAPARSE_STRING("1 + 2 - 3")>::type mpl_::integral_c<int, 0>
It returns the correct result.