
I am trying to define operator()(...) for my expressions. I want to be able to form expression of the form Program_(a,b) and call Program_(a, b)(10,20). Here, 'a' and 'b' are terminals and I have a mechanism shown in the code below that somehow gets the type suitable for the parameter position. Suppose 'a' is terminal<Var<int> >, I want the first parameter position in Program_(a,b) (pos1, pos2) to be of the type 'int'. typename boost::result_of<call_param_type<M>(const Expr &)>::type gives me that type for the Mth argument in the expression of the form Program_(a1,a2,...). Now, I am trying to use this to define operator()(...) in my program_expr class. That doesn't seem to work. However, if I define a separate function callfunc, that takes the expression and the arguments, that seems to work. In the following code, enabling the if 0'ed out code results in compilation errors. How do I go about defining operator()(...) in my program_expr class with the above property? Thanks, Manjunath #include <boost/proto/proto.hpp> #include <boost/proto/proto_typeof.hpp> #include <boost/mpl/bool.hpp> #include <boost/mpl/assert.hpp> #include <iostream> #include <sstream> #include <string> namespace proto=boost::proto; namespace mpl=boost::mpl; unsigned int ids; template<typename VT> struct Var { unsigned int id; Var() { id = ++ids; } }; typedef proto::terminal<Var<int> >::type int32_; typedef proto::terminal<Var<float> >::type float_; struct program_ {}; template<class E> struct program_expr; struct program_domain : proto::domain<proto::pod_generator<program_expr> > { }; struct _var_type : proto::callable { template<typename Sig> struct result; template<typename This, typename T> struct result<This(const Var<T> &)> { typedef T type; }; }; struct var_type : proto::or_< proto::when<proto::terminal<Var<proto::_> >, _var_type(proto::_value)>
{};
template<int N> struct call_param_type : proto::or_< proto::when< proto::function< proto::terminal<program_>, proto::vararg<proto::terminal<Var<proto::_> > > >, var_type(proto::_child_c<N+1>)>
{};
template <typename Expr> struct program_expr { BOOST_PROTO_BASIC_EXTENDS(Expr, program_expr<Expr>, program_domain); BOOST_PROTO_EXTENDS_SUBSCRIPT(); typedef void result_type; #if 0 result_type operator()(typename boost::result_of<call_param_type<0>(const Expr &)>::type x) { std::cout << "program with one arg\n"; } result_type operator()(typename boost::result_of<call_param_type<0>(const Expr &)>::type x, typename boost::result_of<call_param_type<1>(const Expr &)>::type y) { std::cout << "program with two args\n"; } #endif }; template<typename Expr> void callfunc(const Expr &e, typename boost::result_of<call_param_type<0>(const Expr &)>::type x) { std::cout << "program with one arg\n"; } template<typename Expr> void callfunc(const Expr &e, typename boost::result_of<call_param_type<0>(const Expr &)>::type x, typename boost::result_of<call_param_type<1>(const Expr &)>::type y) { std::cout << "program with two args\n"; } template<typename A0> typename proto::result_of::make_expr<proto::tag::function , program_domain , program_ , A0 const &>::type const Program_(A0 const &a0) { return proto::make_expr<proto::tag::function, program_domain>( program_(), boost::ref(a0)); } template<typename A0, typename A1> typename proto::result_of::make_expr<proto::tag::function , program_domain , program_ , A0 const & , A1 const &>::type const Program_(A0 const &a0, A1 const &a1) { return proto::make_expr<proto::tag::function, program_domain>( program_(), boost::ref(a0), boost::ref(a1)); } int main() { int32_ a,b,c; callfunc(Program_(a, b), 10, 20); #if 0 Program_(a, b)(10, 20); #endif }