| Home | Libraries | People | FAQ | More

###### `null_context`

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.