On 3/4/2010 11:43 AM, Manjunath Kudlur wrote:
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::_> > >.
Not quite. See below. <snip>
template<typename VT> struct Var { VT value; void assign(const VT v) { value = v; } };
Var is a value-type. It holds a datum by-value.
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) ); }
Program_ takes its argument by const ref. It's argument is therefore immutable. <snip>
typedef proto::terminal<Var<int> >::type int32_;
int main() { int32_ a,b,c;
assign()(a=20); assign()(a(30));
Program_(a)(10);
Here, we're passing "a" to Program_, which takes its argument as const ref. Later, you extract "a" from the Proto tree and try to mutate it. But it's const; obviously that's not going to work. So the first thing you need to do is change Program_ to take its argument by non-const ref. However, when you do that, you'll find that it still doesn't work. And that has to do with how proto::make_expr works. proto::make_expr tries to enforce uniformity in the trees it returns. In particular, it wants all the child nodes to be in the same domain as the parent node it returns. When the domains don't match (as they don't in this case because int32_ is in the default_domain), it passes the child through the domain's generator. The result gets stored by value instead of by reference as you're requesting. The fix is quite simple. Define int32_ as follows: typedef proto::literal<Var<int>, program_domain> int32_; That puts it in the program_domain. Also, you should note that your generator is broken. It only handles the function<terminal,terminal> case. Passing any other expression to it violates its preconditions. You need an otherwise<_> in there. (BTW, I just added a default constructor to literal to make your code compile.) -- Eric Niebler BoostPro Computing http://www.boostpro.com