
On 3/1/2010 2:21 PM, Manjunath Kudlur wrote:
Yeah, got it. I realise now that the passing a domain to make_expr wraps all the components of the expression also with the corresponding expression class. What I am unable to figure out it how to wrap only the final expression I want with program_expr. In this case I want to wrap expr<tag::function, vararg<terminal<Var> > > with program_expr. Is there an example I can look at that does something similar? Or is this the wrong way to look at the problem? Basically, I want to add the function call operator to my expressions, but only to expressions of certain forms. My thinking is, if I only wrap expressions of that certain form with my expression class, I should be OK, no?
Ah, you want a different expression interface based on the structure of the expression being wrapped. There's a straightforward way to do that, but it's not obvious. See the program below. #include <boost/utility/result_of.hpp> #include <boost/utility/enable_if.hpp> #include <boost/proto/proto.hpp> namespace proto = boost::proto; using proto::_; // This wrapper is for function expressions template<typename Expr> struct function_expr; // This wrapper is for all other expressions template<typename Expr> struct program_expr; struct function_call : proto::function< proto::vararg< proto::terminal<_> > > {}; struct program_generator : proto::or_< // Wrap function expressions in function_expr proto::when< function_call // pod_generator is a function object and // so can be used to make this callable // transform , proto::pod_generator<function_expr>(_) > // Wrap all other expressions in program_expr , proto::otherwise< proto::pod_generator<program_expr>(_) > > {}; // A program_generator satisfies the requirement for // a proto generator because it is a unary function // object, albeit a rather complicated one. struct program_domain : proto::domain< program_generator > {}; template<typename Expr> struct function_expr { BOOST_PROTO_BASIC_EXTENDS(Expr, function_expr<Expr>, program_domain) BOOST_PROTO_EXTENDS_FUNCTION() void I_am_a_function() const {} }; template<typename Expr> struct program_expr { BOOST_PROTO_BASIC_EXTENDS(Expr, program_expr<Expr>, program_domain) BOOST_PROTO_EXTENDS_FUNCTION() void I_am_not_a_function() const {} }; program_expr<proto::terminal<int>::type> i = {{1}}; program_expr<proto::terminal<int>::type> j = {{2}}; int main() { i.I_am_not_a_function(); (i + j).I_am_not_a_function(); i(j).I_am_a_function(); (i(j) + j(i)).I_am_not_a_function(); } -- Eric Niebler BoostPro Computing http://www.boostpro.com