Boost logo

Boost :

Subject: Re: [boost] [variant] Please vote for behavior (Was: Basic rvalue and C++11 features seupport)
From: Larry Evans (cppljevans_at_[hidden])
Date: 2013-01-22 09:43:50


On 01/21/13 22:02, Edward Diener wrote:
> On 1/21/2013 8:39 AM, Antony Polukhin wrote:
>> Current implementation of recursive_wrapper move constructor is not
>> optimal:
>>
>> recursive_wrapper<T>::recursive_wrapper(recursive_wrapper&& operand)
>> : p_(new T(std::move(operand.get()) ))
>> { }
>>
>> During descussion were made following proposals:
[snip]
>> II: Set operand.p_ to NULL, add BOOST_ASSERT in get operations
>> + good performance
>> + provides noexcept guarantee for move constructor
>> + optimization will be used even if varinat has no type with trivial
>> default constructor
>> + easy to implement
>> - triggers an assert when user tries to reuse moved object
>> - adds an empty state to the recursive_wrapper
>>
>> III: Make recursive_wrapper and variant cooperate, enable move for
>> varinat in the presence of recursive_wrappers only when there is at
>> least one type that is nothrow-default-constructible, regardless of
>> whether it's current. It is easyer to understand by example:
>> typedef variant<int, recursive_wrapper<foo>> V;
>> V v1( std::move(v2) );
>> This move-constructs v1 from v2 and leaves int() into v2.
>> + good performance
>> + provides noexcept guarantee for rcursive_wrapper
>> + does not adds an empty state
>> - optimization won't trigger if varinat has no type with trivial
>> default constructor
>> - hard to implement
>> - user may be obscured by the fact, that v2 from the example now
>> contains int
[snip]
> The main issue seems to be simply this: are guarantees ( invariants )
> for an object of a class meant to cover moved from objects of that class ?
>
> All of the choices which you have specified, which popularly boils down
> to II or III, involves this question. The choice of II answers No to the
> question above while the choice of III answers Yes to the question above.
>
The attached code is about the simplest recursive wrapper possible.
The output, also attached, illustrates the current behaviour.
AFAICT, the proposed changes, II and III would cause the following
changes in the output.

I think proposal II would cause the:

 113:list_1 moved which=1

line to remain unchanged; however, the next line:

114:list_1 moved print=( 1, (blank) )

would not complete because, since the recursive_wrapper pointer would
be null, the const list_bounded<T>& value needed for:

list_printer::operator()(const list_bounded<T>& lst) const

could not be retrieved because the assertion:

>> - triggers an assert when user tries to reuse moved object

would be triggered first.

In contrast, proposal III would cause the line 113 output to be:

 113:list_1 moved which=1

and the line 114 output to be:

114:list_1 moved print=(blank)

and the rest of the output the same.

Is that about right?

-regards,
Larry





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