![]() |
Home | Libraries | People | FAQ | More |
The proto::null_context<>
is a simple context that recursively evaluates children but does not
combine the results in any way and returns void. It is useful in conjunction
with callable_context<>
, or when defining your own
contexts which mutate an expression tree in-place rather than accumulate
a result, as we'll see below.
proto::null_context<>
is trivially implemented in terms of null_eval<>
as follows:
// Definition of null_context struct null_context { template<typename Expr> struct eval : null_eval<Expr, null_context const, Expr::proto_arity::value> {}; };
And null_eval<>
is also trivially implemented. Here, for instance is a binary null_eval<>
:
// Binary null_eval<> template<typename Expr, typename Context> struct null_eval<Expr, Context, 2> { typedef void result_type; void operator()(Expr &expr, Context &ctx) const { proto::eval(proto::child_c<0>(expr), ctx); proto::eval(proto::child_c<1>(expr), ctx); } };
When would such classes be useful? Imagine you have an expression tree with integer terminals, and you would like to increment each integer in-place. You might define an evaluation context as follows:
struct increment_ints { // By default, just evaluate all children by delegating // to the null_eval<> template<typename Expr, typename Arg = proto::result_of::child<Expr>::type> struct eval : null_eval<Expr, increment_ints const> {}; // Increment integer terminals template<typename Expr> struct eval<Expr, int> { typedef void result_type; void operator()(Expr &expr, increment_ints const &) const { ++proto::child(expr); } }; };
In the next section on proto::callable_context<>
,
we'll see an even simpler way to achieve the same thing.