...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
boost::proto::pass_through — A PrimitiveTransform that transforms the child expressions of an expression node according to the corresponding children of a Grammar.
// In header: <boost/proto/transform/pass_through.hpp> template<typename Grammar> struct pass_through : proto::transform< pass_through<Grammar> > { // member classes/structs/unions template<typename Expr, typename State, typename Data> struct impl : proto::transform_impl<Expr, State, Data> { // types typedef typename proto::result_of::child_c<Grammar, N>::type GN; // For each N in [0,Expr arity), for exposition only typedef typename proto::result_of::child_c<Expr, N>::type EN; // For each N in [0,Expr arity), for exposition only typedef typename boost::result_of<GN(EN,State,Data)>::type RN; // For each N in [0,Expr arity), for exposition only typedef typename Expr::proto_tag T; // For exposition only typedef typename Expr::proto_domain D; // For exposition only typedef typename D::proto_generator G; // For exposition only typedef proto::listN<R0,...RN> A; // For exposition only typedef proto::expr<T, A> E; // For exposition only typedef proto::basic_expr<T, A> BE; // For exposition only typedef typename mpl::if_<proto::wants_basic_expr<G>, BE, E>::type expr_type; // For exposition only typedef typename boost::result_of<D(expr_type)>::type result_type; // public member functions result_type operator()(typename impl::expr_param, typename impl::state_param, typename impl::data_param) const; }; };
Given a Grammar such as proto::plus<T0, T1>
,
an expression type that matches the grammar such as
proto::plus<E0, E1>::type
, a state
S
and a data D
, the result of applying
the proto::pass_through<proto::plus<T0, T1> >
transform is:
proto::plus< boost::result_of<T0(E0, S, D)>::type, boost::result_of<T1(E1, S, D)>::type >::type
The above demonstrates how child transforms and child expressions are applied pairwise, and how the results are reassembled into a new expression node with the same tag type as the original.
The explicit use of proto::pass_through<>
is not usually
needed, since the expression generator metafunctions such as
proto::plus<>
have
proto::pass_through<>
as their default transform. So,
for instance, these are equivalent:
proto::when< proto::plus<X, Y>, proto::pass_through< proto::plus<X, Y> > >
proto::when< proto::plus<X, Y>, proto::plus<X, Y> >
proto::when< proto::plus<X, Y> > // because of proto::when<class X, class Y=X>
proto::plus<X, Y> // because plus<> is both a grammar and a transform
For example, consider the following transform that promotes all
float
terminals in an expression to
double
.
// This transform finds all float terminals in an expression and promotes // them to doubles. struct Promote : proto::or_< proto::when<proto::terminal<float>, proto::terminal<double>::type(proto::_value) >, // terminal<>'s default transform is a no-op: proto::terminal<proto::_>, // nary_expr<> has a pass_through<> transform: proto::nary_expr<proto::_, proto::vararg<Promote> > > {};