Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext
Evaluating an Expression with proto::eval()

Synopsis:

namespace proto
{
    namespace result_of
    {
        // A metafunction for calculating the return
        // type of proto::eval() given certain Expr
        // and Context types.
        template<typename Expr, typename Context>
        struct eval
        {
            typedef
                typename Context::template eval<Expr>::result_type
            type;
        };
    }

    namespace functional
    {
        // A callable function object type for evaluating
        // a Proto expression with a certain context.
        struct eval : callable
        {
            template<typename Sig>
            struct result;

            template<typename Expr, typename Context>
            typename proto::result_of::eval<Expr, Context>::type
            operator ()(Expr &expr, Context &context) const;

            template<typename Expr, typename Context>
            typename proto::result_of::eval<Expr, Context>::type
            operator ()(Expr &expr, Context const &context) const;
        };
    }

    template<typename Expr, typename Context>
    typename proto::result_of::eval<Expr, Context>::type
    eval(Expr &expr, Context &context);

    template<typename Expr, typename Context>
    typename proto::result_of::eval<Expr, Context>::type
    eval(Expr &expr, Context const &context);
}

Given an expression and an evaluation context, using proto::eval() is quite simple. Simply pass the expression and the context to proto::eval() and it does the rest and returns the result. You can use the eval<> metafunction in the proto::result_of namespace to compute the return type of proto::eval(). The following demonstrates a use of proto::eval():

template<typename Expr>
typename proto::result_of::eval<Expr const, MyContext>::type
MyEvaluate(Expr const &expr)
{
    // Some user-defined context type
    MyContext ctx;

    // Evaluate an expression with the context
    return proto::eval(expr, ctx);
}

What proto::eval() does is also very simple. It defers most of the work to the context itself. Here essentially is the implementation of proto::eval():

// eval() dispatches to a nested "eval<>" function
// object within the Context:
template<typename Expr, typename Context>
typename Context::template eval<Expr>::result_type
eval(Expr &expr, Context &ctx)
{
    typename Context::template eval<Expr> eval_fun;
    return eval_fun(expr, ctx);
}

Really, proto::eval() is nothing more than a thin wrapper that dispatches to the appropriate handler within the context class. In the next section, we'll see how to implement a context class from scratch.


PrevUpHomeNext