Boost logo

Boost :

Subject: Re: [boost] [Review] Formal Review: Boost.Move
From: Jeffrey Lee Hellrung, Jr. (jhellrung_at_[hidden])
Date: 2010-05-31 04:43:07


On 5/30/2010 11:46 PM, Thomas Klimpel wrote:
> Jeffrey Lee Hellrung wrote:
>> Thomas Klimpel wrote:
>>> All that is needed to to wrap its type declaration with the
>>> BOOST_MOVE_ASSIGNMENT_WRAPPER macro.
>> [snip]
>>
>> Do you find this preferable to simply explicitly defining the
>> copyassignment operator in the enclosing class?
>
> The enclosing class might simply want to use the compiler generated copy constructor and copy assignment operator, for maintenance reasons. Another point is the behavior on compilers with rvalue references, as one of the goals of boost.move is to allow to write code that works on compilers with and without rvalue references, without scarifying the performance on new compilers for the compatibility with old compilers.

Fair enough. Either way, if boost::container::vector uses "optimal"
move emulation, one won't be able to just drop it into an existing class
without some additional modifications (e.g., using this
move_assignment_wrapper, or defining an explicit copy assignment
operator). And, in fact, using move_assignment_wrapper or defining a
copy assignment operator can each happen conditionally, predicated on
BOOST_NO_RVALUE_REFERENCES *and* on whether the boost::container::vector
instance (or whatever member object we're concerned about) really does
force an auto-generated copy assignment operator with signature
operator=(T&). For example:

T& operator=(
     typename boost::mpl::if_<
         enclosing_has_normal_autogen_copy_assign< vector<T> >,
         dummy_t,
         const T&
>::type other) { ... }

I only suggested to explicitly define the copy assignment operator
because that seems like the "natural" resolution, in general, if the
compiler fails the generate the correct one...

> Apart from that, you are right in that the enclosing class could simply define
> TYPE& operator=(TYPE t)
> and be freed of all problems, without using the BOOST_MOVE_ASSIGNMENT_WRAPPER macro.
>
> But as we are discussing the question whether classes like boost::container::vector should use the optimized move emulation, the exact impact on the enclosing class is quite important.

By "exact impact", you mean the "recommended resolution" to define,
implicitly or explicitly, a standard copy assignment operator in the
enclosing class...?

>>> However, my position on breaking move-assignment
>>> from temporaries for the non-optimized mode remains
>>> that this is not a reasonable option, especially considering
>>> that it would be a serious regression with respect
>>> to the Adobe Move Library.
>>
>> Is this a position based on technical semantics, rather than practical
>> semantics? Because I believe even the non-optimized emulation should
>> effectively move-assign from temporaries via RVO...
>
> If it were not practical semantics, it wouldn't be a serious regression. The practical problem is the following: If the "move enabled" class defines "TYPE& operator=(const TYPE& t)", then the "TYPE& operator=(BOOST_RV_REF(&) t)" overload won't kick in for move assignment from temporaries on C++03 compilers, as "TYPE& operator=(const TYPE& t)" is a better match. It also cannot define a "TYPE& operator=(TYPE t)" overload in addition to "TYPE& operator=(const TYPE& t)" (this would be ambiguous), so RVO can also no longer kick in.
>
> The alternative is to just define "TYPE& operator=(TYPE t)", but Ion doesn't like this for classes like boost::container::vector, as this copy assignment operator cannot reuse existing resources. So his proposed non-optimized mode sacrificed move-assign from temporaries on C++03 compilers, to avoid non-optimal code on new compilers in C++0x mode.

Ah, okay, I was thinking of the distinction between the 2 move emulation
modes described in the proposed Boost.Move documentation, neither of
which use a copy assignment operator with signature operator=(const T&).

If I understand correctly, optimal move emulation for
boost::container::vector is the best choice if we ignore the effect on
(future) enclosing classes. Are you/we necessarily against just going
with this, documenting the fact that enclosing classes will have to deal
with the non-standard compiler-generated copy assignment operator
(either by defining it explicitly, perhaps conditionally; or wrapping
member vars in a wrapper, also perhaps conditionally)? We don't have
any backwards compatibility concerns, since boost::container::vector is
not actually released yet, right?

- Jeff


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