Boost logo

Boost :

Subject: Re: [boost] [move][container] Review Request (new versions of Boost.Move and Boost.Container in sandbox and vault)
From: David Abrahams (dave_at_[hidden])
Date: 2009-10-16 21:26:35


on Thu Oct 15 2009, Thomas Klimpel <Thomas.Klimpel-AT-synopsys.com> wrote:

> I know that this discussion is old, and that a review manager for the
> review is still missing.

I'll manage the review if nobody else is stepping up.

> However, since the article series at "http://cpp-next.com" has now
> covered quite some ground, I somehow guess that a review manager will
> be found sooner or later. (More precisely, I guess that the article
> series on value semantics, moving and all that will soon be finished,
> and that then a review manager will appear somehow...)

Not sure what C++Next has to do with it, but...

>> It's OK if transforming "x" into "move(x)" changes
>> semantics with respect to x. It isn't OK if it changes semantics with
>> respect to objects other than x. In particular,
>>
>> y = x; ===> y = move(x);
>>
>> should not change anything about what happens with y. That's just too
>> capricious.
>
> I'm not sure about this. An alternative would be to transform "x" into
> "X(move(x))" (move constructor call). At least this solution would be
> more general than the suggestion to call "v2.clear();".

As http://cpp-next.com/archive/2009/09/your-next-assignment/ points out,
generality isn't the point of move---optimization is--- and if you want
generality, you can go with
    
  X& operator=(X&& rhs)
  {
      X(std::move(rhs))
        .swap(*this);
      return *this;
  }

>> Here's another example:
>>
>> // C++03
>> template <class Pair, class T>
>> T& replace2nd(Pair& c, T const& x)
>> {
>> return c.second = x;
>> }
>>
>> pair<thread,thread> threads;
>> ...
>>
>> long_running_operation(replace2nd(threads, new_thread())); // (**)
>>
>>
>> OK, let's move-enable replace2nd:
>>
>> // addtional overload
>> template <class Pair, class T>
>> T& replace2nd(Pair& c, T&& x)
>> {
>> return c.second = move(x);
>> }
>>
>> can't clear there; we don't know that T has a clear().
>>
>> Now we've just changed the semantics of the line marked (**), since the
>> old thread won't be canceled until the long-running operation is
>> complete.
>
> Interesting. I have to admit that I assumed the temporary objects for
> the arguments to replace2nd would be destroyed before the return value
> of replace2nd gets used, but this assumption was probably wrong. I
> guess the C++ standard just says that they get destroyed after the
> entire expression is evaluated.

Yes

> Just a simple question for my education: Does the C++ standard
> explicitly guarantees that the temporary objects don't get destroyed
> before the entire expression is evaluated,

Yes

> or is the exact moment of the destructor calls simply unspecified?

No

<snip>

> So I'm left with the impression that there might be quite some good reasons not to
> implement move-assignment as swap, but no really conclusive counter examples against
> it. On the other hand, as long as the absence of conclusive counter examples can't be
> "proved", ruling that move-assignment may generally be implemented as swap will be
> risky or worse.

I guess we're in agreement, then :-)

-- 
Dave Abrahams           Meet me at BoostCon: http://www.boostcon.com
BoostPro Computing
http://www.boostpro.com

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