Boost logo

Boost :

Subject: Re: [boost] Improving the assignment operators of various Boosttypes
From: Giovanni Piero Deretta (gpderetta_at_[hidden])
Date: 2008-09-10 13:36:44


On Wed, Sep 10, 2008 at 6:17 PM, Michael Marcin <mike.marcin_at_[hidden]> wrote:
> Peter Dimov wrote:
>>
>> Michael Marcin:
>> ...
>>
>>> It also allows you to support move assignment emulation rather elegantly
>>> using the move library in the sandbox.
>>
>> There is no need to use a move library. The point of the above assignment
>> is to take advantage of copy elision, which allows the compiler to construct
>> the rvalue argument directly into 'arg', without a copy. In other words, if
>> you have
>>
>
> For rvalues yes but for lvalues you need move emulation. Which can be
> implemented in the sandbox move library as follows.
>
> class foo
> {
> public:
> foo();
> foo( T t );
> foo( boost::move_from<foo> other )
> {
> swap( other.source );
> }
>
> foo& operator=( foo rhs )
> {
> swap( rhs );
> }
>
> void swap();
>
> //...
> };
>
> T bar();
>
> int main()
> {
> foo x;
> foo y( bar() );
> x = boost::move(y);
> }
>

If you do not want to deal with move emulation (which I've found very
brittle in complex expressions), a simple way to to gain the advantage
of T::operator=(T rhs) even when assigning from lvalues is something
like:

   template<class T> T destructive_copy(T& x) {
      using std::swap;
      T result;
      swap(result, x);
      return x;
   }

which relies on NRVO to eliminate expensive copies:

struct foo {
     foo();
     foo(const& foo);
     foo& operator(foo);
     friend swap(foo&, foo&);
};

foo t1;

// no expensive copies if the compiler
// does both NRVO and temporaries
// elision
foo t2 (destructive_copy(t2));

foo t3;
// again, no expensive copies
t3 = destructive_copy(t2);

The name is also something that is easily greppable for (I do not use
'move' to prevent name collisions with an eventual std::move or
boost::move).

For types which do not have an optimized swap is suboptimal, so some
sfinae trick on is_swappable might be needed. Ah, of course it
requires T to be DefaultConstructible, and most importantly
CopyConstructible so it doesn't handle move only types.

HTH,

-- 
gpd

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