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
[email protected]
http://lists.boost.org/mailman/listinfo.cgi/proto