On Wed, Mar 3, 2010 at 4:20 PM, Manjunath Kudlur <keveman@gmail.com> wrote:
On Wed, Mar 3, 2010 at 4:12 PM, Eric Niebler <eric@boostpro.com> wrote:
On 3/4/2010 6:51 AM, Manjunath Kudlur wrote: <snip>
I can merrily call assign()(a=10) and I get the expected behaviour. But when I call assign()(a(20)), I get a compilation error saying that there is no match for operator()(const Var<int> &, const int&). Why is that when I call proto::_value(proto::_left) on a proto::function expression, a *const* reference gets passed to the transform?
This is a bug. Thanks for reporting it. It's now fixed on trunk.
Similar problem seems to exists for expression of the form Program_(a)(10). Here, Program_ is a function that returns proto::function<proto::terminal<program_>, proto::terminal<Var<proto::_> > >. I wrap it in program_expr, and I define operator()(int) in that expression wrapper class. I try to set the value of the argument passed in, but I run into the same const-ness mismatch compiler error. Please let me know if I am missing something. Here is the complete program: (Look for the line with // COMPILER ERROR comment). #include <boost/proto/proto.hpp> #include <boost/proto/proto_typeof.hpp> #include <iostream> #include <sstream> #include <string> namespace proto=boost::proto; namespace mpl=boost::mpl; template<typename VT> struct Var { VT value; void assign(const VT v) { value = v; } }; struct program_ {}; struct _assign : proto::callable { typedef void result_type; template<typename VT> result_type operator()(Var<VT> &var) const { var.assign(20); } template<typename VT> result_type operator()(Var<VT> &var, const VT val) const { var.assign(val); } }; struct assign : proto::or_< proto::when<proto::terminal<Var<proto::_> >, _assign(proto::_value)>, proto::when<proto::assign<proto::terminal<Var<proto::_> >, proto::literal<proto::_> >, _assign(proto::_value(proto::_left), proto::_value(proto::_right))>, proto::when<proto::function<proto::terminal<Var<proto::_> >, proto::literal<proto::_> >, _assign(proto::_value(proto::_left), proto::_value(proto::_right))>
{};
template<class E> struct program_expr; struct program_generator : proto::or_< proto::when<proto::function<proto::terminal<program_>, proto::terminal<Var<proto::_> > >, proto::pod_generator<program_expr>(proto::_expr)>
{};
struct program_domain : proto::domain<program_generator> {}; 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 Expr> struct program_expr { BOOST_PROTO_BASIC_EXTENDS(Expr, program_expr<Expr>, program_domain); BOOST_PROTO_EXTENDS_SUBSCRIPT(); typedef void result_type; result_type operator()(int a) const { std::cout << "program with one arg\n"; // COMPILER ERROR on this line (proto::value(proto::child_c<1>(*this))).assign(a); } }; typedef proto::terminal<Var<int> >::type int32_; int main() { int32_ a,b,c; assign()(a=20); assign()(a(30)); Program_(a)(10); std::cout << proto::value(a).value << std::endl; }