[Proto] callable_context

Dear all, I am trying to use callable_contexts to evaluate expressions like: x >> f >> g >> h; where this would be equivalent to h(g(f(x))). I have derived my context from callable_context, and thought I have overloaded for relevant tags (terminal and shift_right). GCC 4.5.1 (MinGW32, WinXP, SP3) stops with an error message which is cryptic to my current level of knowledge about Proto. I guess that's because I haven't done the job correctely. For your reference, I have included a copy of my program as well as the error GCC gives me in the P.S. section of this posting. Any ideas please? TIA, --Hossein P.S. <code> #include <iostream> #include <boost/proto/proto.hpp> namespace mpl = boost::mpl; namespace proto = boost::proto; using proto::_; using namespace std; struct EWGrandDad { int evaluate() const; }; typedef proto::terminal<double (*) (double)> FunctionType; template<typename> struct EmtExpr; struct EmtGrammar: proto::or_ < proto::terminal<EWGrandDad>, proto::shift_right<EmtGrammar, FunctionType>
{}; struct EmtDomain: proto::domain<proto::generator<EmtExpr>, EmtGrammar> {}; template<typename Expr> struct EmtExpr : proto::extends<Expr, EmtExpr<Expr>, EmtDomain> { typedef proto::extends<Expr, EmtExpr<Expr>, EmtDomain> base_type; EmtExpr(const Expr& e = Expr()): base_type(e) {} }; struct EWBase : EmtExpr<typename proto::terminal<EWGrandDad>::type> { typedef typename proto::terminal<EWGrandDad>::type expr_type; EWBase(): EmtExpr<expr_type>(expr_type::make(EWGrandDad())) {} }; struct EW1: EWBase { EW1(int n1, int n2): n1_(n1), n2_(n2) {} int evaluate() const {return n1_ * n2_;} int n1_, n2_; }; double times2(double d) {return d * 2;} double minus1(double d) {return d - 1;} struct EmtContext: proto::callable_context<const EmtContext> { typedef double result_type; result_type operator() (proto::tag::terminal, const EWGrandDad& ew) const { return ew.evaluate(); } template<typename Expr> result_type operator() (proto::tag::shift_right, const Expr& e, FunctionType f) const { return f(proto::eval(e, *this)); } }; int main() { EmtContext emtCtx; cout << "result = " << emtCtx(EW1(4, 5) >> ×2 >> &minus1); return 0; } </code> <error message> main.cpp: In function 'int main()': main.cpp:82:63: error: no match for call to '(EmtContext) (const boost::lazy_enable_if_c<true, boost::proto::generatorns_::generator<EmtExpr>::result<EmtDomain(boost::proto::exprns_::expr<boost::proto::tag::shift_right, boost::proto::argsns_::list2<const EmtExpr<boost::proto::exprns_::expr<boost::proto::tag::shift_right, boost::proto::argsns_::list2<const EW1&, EmtExpr<boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<double (* const&)(double)>, 0l> > >, 2l> >&, EmtExpr<boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<double (* const&)(double)>, 0l> > >, 2l>)> >::type)' main.cpp:67:14: note: candidate is: EmtContext::result_type EmtContext::operator()(boost::proto::tag::terminal, const EWGrandDad&) const </error message>

Joel,
Better use transform than context, far more easy and flexible.
OK, but my insight into Proto is not enough for that yet. Furthermore, my current application seems to be much less complex than transforms. Now, is there anything you can spot in my code which can fix the problem mentioned? TIA, --Hossein

On 12/10/2010 11:57 AM, Hossein Haeri wrote:
Dear all,
I am trying to use callable_contexts to evaluate expressions like:
x >> f >> g >> h;
where this would be equivalent to h(g(f(x))). I have derived my context from callable_context, and thought I have overloaded for relevant tags (terminal and shift_right). GCC 4.5.1 (MinGW32, WinXP, SP3) stops with an error message which is cryptic to my current level of knowledge about Proto. I guess that's because I haven't done the job correctely. For your reference, I have included a copy of my program as well as the error GCC gives me in the P.S. section of this posting. Any ideas please?
Contexts make life harder, and I hope to deprecate them in the future. Here's what the solution looks like using transforms: #include <boost/proto/proto.hpp> #include <iostream> namespace proto = boost::proto; using proto::_; struct add_one_ { typedef int result_type; int operator()(int i) const { return i + 1; } }; proto::terminal<add_one_>::type const add_one = {}; struct GetFun : proto::call<proto::_value(proto::_right)> {}; struct EvalStream : proto::or_< proto::when< proto::terminal<_> , proto::_value > , proto::when< proto::shift_right<EvalStream, proto::terminal<_> > , proto::lazy< GetFun(EvalStream(proto::_left)) > > > {}; int main() { // This prints "3" std::cout << EvalStream()( 1 >> add_one >> add_one ) << std::endl; } HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com

Hi Erik,
struct add_one_ { typedef int result_type; int operator()(int i) const { return i + 1; } };
proto::terminal<add_one_>::type const add_one = {};
This needs me to wrap every function into a function object and then instantiate that function object using an aggregate syntax. This is awkward. I need something automatic for functions.
1 >> add_one >> add_one
I need something which can work with expressions like 1 >> &f >> &g >> &h where f, g, and h are ordinary functions. Is that also doable in Proto? TIA, --Hossein

On 1/4/2011 8:10 AM, Hossein Haeri wrote:
Hi Erik,
struct add_one_ { typedef int result_type; int operator()(int i) const { return i + 1; } };
proto::terminal<add_one_>::type const add_one = {};
This needs me to wrap every function into a function object and then instantiate that function object using an aggregate syntax. This is awkward. I need something automatic for functions.
1 >> add_one >> add_one
I need something which can work with expressions like
1 >> &f >> &g >> &h
where f, g, and h are ordinary functions. Is that also doable in Proto?
No. It's not doable in C++, period. There are no UDTs in the above expression, so no operator overloads are considered. And there are no built-in operators that make that well-formed. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric,
1 >> &f >> &g >> &h
where f, g, and h are ordinary functions. Is that also doable in Proto?
No. It's not doable in C++, period. There are no UDTs in the above expression, so no operator overloads are considered.
Oops! OK, I meant something like this: lit(1) >> &f >> &g >> &h So, what about this new one in Proto? TIA, --Hossein

On 1/4/2011 10:43 AM, Hossein Haeri wrote:
Eric,
1 >> &f >> &g >> &h
where f, g, and h are ordinary functions. Is that also doable in Proto?
No. It's not doable in C++, period. There are no UDTs in the above expression, so no operator overloads are considered.
Oops! OK, I meant something like this:
lit(1) >> &f >> &g >> &h
So, what about this new one in Proto?
Yes, that should be doable. -- Eric Niebler BoostPro Computing http://www.boostpro.com
participants (3)
-
Eric Niebler
-
Hossein Haeri
-
joel falcou