Boost logo

Boost :

Subject: Re: [boost] [core] Breaking change to boost::ref in 1.56
From: Eric Niebler (eniebler_at_[hidden])
Date: 2014-07-14 12:04:02


On 7/14/2014 12:56 AM, Andrey Semashev wrote:
> On Sunday 13 July 2014 17:04:09 Eric Niebler wrote:
>> On 7/13/2014 2:48 AM, Peter Dimov wrote:
>>> Andrey Semashev wrote:
>>>> Perhaps Eric could provide more context on why Boost.Proto needs
>>>> recursive reference wrappers? Frankly, the requirement looks strange
>>>> to me.
>>>
>>> Generic code that does
>>>
>>> boost::reference_wrapper<T> r = boost::ref( t );
>>>
>>> is broken when t is a reference_wrapper.
>>
>> Right. That's exactly what I argued in committee. Doug Gregor was the
>> only person I was able to convince. C'est la vie. It's also why Proto broke.
>>
>> Proto doesn't *need* the old behavior, strictly speaking. But the part
>> of proto that builds expressions, proto::make_expr, was designed around
>> the old semantics. See <http://bit.ly/1oUbgZr>.
>> proto::result_of::make_expr is a metafunction for computing the result
>> of the proto::make_expr function. It interprets reference types as the
>> types of things to be held by reference, and non-reference types to be
>> held by value. When calling proto::make_expr at run-time, each argument
>> to be held by reference must be wrapped in boost::ref. It uses the
>> generic-friendly invariant of boost::ref that Peter references above.
>>
>> I've already hacked Proto and it's tests to accommodate the change, and
>> the tests are turning green again, so it's not a huge deal. But end user
>> code will have to change. Xpressive didn't break, and it looks like
>> Spirit didn't break, so the scope of the breakage might be small. Hard
>> to say.
>
> Thank you Eric.
>
> Am I right that the user's code that uses proto::result_of::make_expr (or any
> other Proto metafunction for result type computation) won't be broken?

Define "broken". proto::result_of::make_expr will now compute a
different type than for the previous release. So anybody who is
depending on the exact type will be broken. This is probably not a lot
of people.

> I'm
> omitting for now the possibility that the user's code could use the reference
> wrapper like in the Peter's code sample. From your changes to Proto tests I
> could not see what kind of changes would be required on the user's side.

These are the changes:
https://github.com/boostorg/proto/commit/d9a4fc37c2b99a08648a5245ce637e60d4b6d564

The changes in proto/test/mem_ptr.cpp are an example of where things get
weird. If you pass a reference_wrapper<int> to boost::ref, you get a
reference_wrapper<int>. But it you pass it to boost::cref, you get a
reference_wrapper<int const>. This changes the type computation in yet
another way, and yet another code invariant is broken. Previously, it
was the case that if you have a T const &, it doesn't matter if you call
boost::ref or boost::cref. Now it does, and anybody who uses boost::cref
together with proto::make_expr is in for a rude surprise. The type of
the returned object will not be the same as the type computed by
proto::result_of::make_expr. (This is what broke the test.)

-- 
Eric Niebler
Boost.org
http://www.boost.org

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk