Boost logo

Boost :

Subject: Re: [boost] [variant] Please vote for behavior
From: Antony Polukhin (antoshkka_at_[hidden])
Date: 2013-02-01 01:37:53


2013/1/31 Paul Smith <pl.smith.mail_at_[hidden]>:
> On Thu, Jan 31, 2013 at 9:24 AM, Antony Polukhin <antoshkka_at_[hidden]> wrote:
>> From theoretical point of view you are absolutely correct, and my
>> example is lame. Moreover, current implementation of move assignment
>> and move constructors for recursive_wrapper were implemented to model
>> that behavior.
>
> Just pointing out that move assignment is not affected by this
> discussion. Everything is already allocated so it's as efficient as a
> pointer swap.

Can not agree (variant makes some additional manipulations to
guarantee non emptyness):

void move_assign(recursive_wrapper<T>&& rhs) {
...
// heap allocation in move constructor of recursive_wrapper
// can be optimized away (see #7960)
variant temp( detail::variant::move(rhs) );

// *this stores type different from recursive_wrapper<T>,
// so it another call to move constructor of recursive_wrapper
// will be made
// Potential call to less effective move_assign implementation if
// variant does not have fallback_type (+1 heap allocation and deallocation)
variant_assign( detail::variant::move(temp) );
...
// heap deallocation in destructor of recursive_wrapper
}

With recursive_ptr this would be:

void move_assign(recursive_ptr<T>&& rhs) {
...
// swap ptrs
// can be optimized away (see #7960)
variant temp( detail::variant::move(rhs) );

// recursive_ptr move constructor does not throw, so
// variant will use a fastest possible move assignment implementation
// *this stores type different from recursive_wrapper<T>,
// so it calls to move constructor of recursive_ptr
// => swap ptrs
variant_assign( detail::variant::move(temp) );

...
// destructors of temporaries will call delete on nullptrs

// Whole function will be noexcept => variant can be move
// assigned in STL containers (containers will use copy-assignments,
// if this function can throw)
}

With recursive_ptr it is as efficient, as pointers swap! With
recursive_wrapper it is multiple times slower.

2013/2/1 Dave Abrahams <dave_at_[hidden]>:
>
> on Thu Jan 31 2013, Paul Smith <pl.smith.mail-AT-gmail.com> wrote:
>
>> On Thu, Jan 31, 2013 at 9:24 AM, Antony Polukhin <antoshkka_at_[hidden]> wrote:
>>> From theoretical point of view you are absolutely correct, and my
>>> example is lame. Moreover, current implementation of move assignment
>>> and move constructors for recursive_wrapper were implemented to model
>>> that behavior.
>>
>> Just pointing out that move assignment is not affected by this
>> discussion. Everything is already allocated so it's as efficient as a
>> pointer swap.
>
> Actually the correct semantics of move assignment is the same as "swap +
> clear" if there's an empty state. See
> http://cpp-next.com/archive/2009/09/your-next-assignment/
>
> I recommend reading the whole article.

Oops, if move assignment shall be equal to "swap + clear", then the
current implementations of recursive_wrappers move assign must be
fixed (it just swaps).

--
Best regards,
Antony Polukhin

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