| Home | Libraries | People | FAQ | More

## Struct template callable_context

boost::proto::context::callable_context — An evaluation context adaptor that makes authoring a context a simple matter of writing function overloads, rather then writing template specializations.

## Synopsis

    template<typename Context,
             typename DefaultCtx = proto::context::default_context>
    struct callable_context {
      template<typename Expr, typename ThisContext = Context>
      struct eval :  see-below {
      };
    };

## Description

`proto::callable_context<>` is a base class that implements the context protocol by passing fanned-out expression nodes to the derived context, making it easy to customize the handling of expression types by writing function overloads. Only those expression types needing special handling require explicit handling. All others are dispatched to a user-specified default context, `DefaultCtx`.

`proto::callable_context<>` is defined simply as:

    template<typename Context, typename DefaultCtx = default_context>
    struct callable_context {
      template<typename Expr, typename ThisContext = Context>
      struct eval :
        mpl::if_<
          is_expr_handled_<Expr, Context>, // For exposition
          proto::context::callable_eval<Expr, ThisContext>,
          typename DefaultCtx::template eval<Expr, Context>
        >::type
      {};
    };

The Boolean metafunction `is_expr_handled_<>` uses metaprogramming tricks to determine whether `Context` has an overloaded function call operator that accepts the fanned-out constituents of an expression of type `Expr`. If so, the handling of the expression is dispatched to `proto::context::callable_eval<>`. If not, it is dispatched to the user-specified `DefaultCtx`.

Example:

    // An evaluation context that increments all
    // integer terminals in-place.
    struct increment_ints :
      proto::context::callable_context<
        increment_ints const                // derived context
        proto::context::null_context const  // fall-back context
      >
    {
        typedef void result_type;

        // Handle int terminals here:
        void operator()(proto::tag::terminal, int &i) const
        {
           ++i;
        }
    };

With `increment_ints`, we can do the following:

    proto::literal<int> i = 0, j = 10;
    proto::eval( i - j * 3.14, increment_ints() );

    assert( i.get() == 1 && j.get() == 11 );