#include namespace proto = boost::proto; namespace mpl = boost::mpl; struct frac {}; struct simplifyfct { typedef frac result_type; frac const & operator()(frac const & f) const { return f;} }; template struct frac_calculator; struct frac_domain : proto::domain > {}; template struct simexpr { BOOST_PROTO_BASIC_EXTENDS(EXPR, simexpr, frac_domain) BOOST_PROTO_EXTENDS_FUNCTION() }; simexpr::type> const sim = {{}}; struct frac_context : proto::callable_context {}; template struct frac_calculator : proto::extends, frac_domain> { typedef proto::extends, frac_domain> base_type; frac_calculator(Expr const &expr = Expr()) : base_type(expr) {} }; /* The following grammar works */ struct RemoveAllSim : proto::or_< proto::when< proto::function, RemoveAllSim> , RemoveAllSim(proto::_right) > , proto::terminal > {}; /* The following grammar does not work */ struct RemoveSim : proto::or_< proto::when< proto::function, proto::function, proto::_> > , RemoveSim(proto::_right) > , proto::function, proto::_> , proto::terminal > {}; int main () { frac a, b; frac_context C; #define TESTEXPR (sim(sim(sim(sim(a))))) frac c = proto::eval(TESTEXPR, C); // THIS WORKS! c = proto::eval( RemoveAllSim()( TESTEXPR ) , C); // THIS WORKS! c = proto::eval( RemoveSim()( TESTEXPR ) , C); // THIS DOES NOT WORK! return 0; }