Definintion of proto::context::callable_context<>,
an evaluation context for proto::eval()
that fans out each node and calls the derived context type with the expressions constituents. If the derived context
doesn't have an overload that handles this node, fall back to some other context.
A BinaryFunction that accepts a Proto expression and a callable context and calls
the context with the expression tag and children as arguments, effectively fanning the
expression out.
proto::context::callable_eval<> requires that
Context is a PolymorphicFunctionObject
that can be invoked with Expr's tag and children as
expressions, as follows:
context(typename Expr::proto_tag(), proto::child_c<0>(expr), ... proto::child_c<N>(expr))
typename boost::result_of<
Context(
typename Expr::proto_tag,
typename proto::result_of::child_c<0>::type,
...
typename proto::result_of::child_c<N>::type,
)>::type
result_type
Expr &
The current expression
Context &
The callable evaluation context
context(typename Expr::proto_tag(),
proto::child_c<0>(expr),...
proto::child_c<N>(expr))
proto::context::default_context
An evaluation context adaptor that makes authoring a context a simple matter of
writing function overloads, rather then writing template specializations.
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 );
Context
A BinaryFunction that accepts an Expr and a
Context, and either fans out the expression and passes
it to the context, or else hands off the expression to DefaultCtx.
If Context is a PolymorphicFunctionObject
such that it can be invoked with the tag and children of Expr, as
ctx(typename Expr::proto_tag(), child_c<0>(expr),... child_c<N>(expr)),
then eval<Expr, ThisContext> inherits from
proto::context::callable_eval<Expr, ThisContext>.
Otherwise, eval<Expr, ThisContext> inherits from
DefaultCtx::eval<Expr, Context>.
see-below