Boost logo

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