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

Reply via email to