|
Proto : |
Subject: [proto] problem with constness of operator return types
From: Thomas Heller (thom.heller_at_[hidden])
Date: 2010-12-02 06:51:55
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
Proto list run by eric at boostpro.com