Hi, I just encountered a somehow stupid problem. Possibility is high that i missed something.
The problem is, that proto's default transform cannot handle op_assign correctly. This is due to the fact that operator OP returns a const proto expression, which turns every value type in proto terminals into a const value. Meaning, that codes like the following don't compile: // following lines copy the literal 9 into the terminal expression: boost::proto::terminal<int>::type t1 = {9}; boost::proto::terminal<int>::type t2 = {9}; // try to plus assign t2 to t1: boost::proto::default_context ctx; boost::proto::eval(t1 += t2, ctx); This fails due to the following code: (out of proto/operators.hpp) template<typename Left, typename Right> typename boost::proto::detail::enable_binary< DOMAIN , DOMAIN::proto_grammar , BOOST_PROTO_APPLY_BINARY_(TRAIT, Left, Right) , TAG , Left , Right const >::type const // The const is the problem here. operator OP(Left &left, Right const &right) { return boost::proto::detail::make_expr_<TAG, DOMAIN, Left &, Right const &>()(left, right); } With that type of expression creation, proto's default evaluation fails with this error message: ./boost/proto/context/default.hpp:142:13: error: read-only variable is not assignable So far so good ... or not good. This should work! The problem is that expressions const qualified above, return a const terminal value as well. Changing the code above to the following fixes the problem: template<typename Left, typename Right> typename boost::proto::detail::enable_binary< DOMAIN , DOMAIN::proto_grammar , BOOST_PROTO_APPLY_BINARY_(TRAIT, Left, Right) , TAG , Left , Right const >::type operator OP(Left &left, Right const &right) { return boost::proto::detail::make_expr_<TAG, DOMAIN, Left &, Right const &>()(left, right); } By changing this, the OP assignment can still be lead to hard errors by having this: boost::proto::terminal<int const>::type t1 = {9}; boost::proto::terminal<int>::type t2 = {9}; // try to plus assign t2 to t1: boost::proto::default_context ctx; boost::proto::eval(t1 += t2, ctx); This leads to exact same error, and is, imho the expected behaviour. Attached is a patch (against current trunk) which fixes these return types. Maybe there is another solution to that problem ... Regards, Thomas
Index: boost/proto/operators.hpp =================================================================== --- boost/proto/operators.hpp (revision 66967) +++ boost/proto/operators.hpp (working copy) @@ -62,6 +62,10 @@ template<typename Domain, typename Grammar, typename Trait, typename Tag, typename Left, typename Right> struct enable_binary : boost::lazy_enable_if_c< + //Trait::value + //lazy_matches<result_of::as_child<Left>, Grammar>::value + //lazy_matches<result_of::as_child<Right>, Grammar>::value + //lazy_matches<result_of::make_expr<Tag, Domain, Left &, Right &>, Grammar>::value boost::mpl::and_< Trait , lazy_matches<result_of::as_child<Left>, Grammar> @@ -105,7 +109,7 @@ , BOOST_PROTO_APPLY_UNARY_(TRAIT, Arg) \ , TAG \ , Arg \ - >::type const \ + >::type \ operator OP(Arg &arg BOOST_PROTO_UNARY_OP_IS_POSTFIX_ ## POST) \ { \ return boost::proto::detail::make_expr_<TAG, DOMAIN, Arg &>()(arg); \ @@ -118,7 +122,7 @@ , BOOST_PROTO_APPLY_UNARY_(TRAIT, Arg) \ , TAG \ , Arg const \ - >::type const \ + >::type \ operator OP(Arg const &arg BOOST_PROTO_UNARY_OP_IS_POSTFIX_ ## POST) \ { \ return boost::proto::detail::make_expr_<TAG, DOMAIN, Arg const &>()(arg); \ @@ -134,7 +138,7 @@ , TAG \ , Left \ , Right \ - >::type const \ + >::type \ operator OP(Left &left, Right &right) \ { \ return boost::proto::detail::make_expr_<TAG, DOMAIN, Left &, Right &>()(left, right); \ @@ -148,7 +152,7 @@ , TAG \ , Left \ , Right const \ - >::type const \ + >::type \ operator OP(Left &left, Right const &right) \ { \ return boost::proto::detail::make_expr_<TAG, DOMAIN, Left &, Right const &>()(left, right); \ @@ -162,7 +166,7 @@ , TAG \ , Left const \ , Right \ - >::type const \ + >::type \ operator OP(Left const &left, Right &right) \ { \ return boost::proto::detail::make_expr_<TAG, DOMAIN, Left const &, Right &>()(left, right); \ @@ -176,7 +180,7 @@ , TAG \ , Left const \ , Right const \ - >::type const \ + >::type \ operator OP(Left const &left, Right const &right) \ { \ return boost::proto::detail::make_expr_<TAG, DOMAIN, Left const &, Right const &>()(left, right);\
_______________________________________________ proto mailing list proto@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/proto