Subject: Re: [boost] [interprocess] Compile problem with 1.39 and trunk
From: Thomas Klimpel (Thomas.Klimpel_at_[hidden])
Date: 2009-08-26 06:37:50
Mathias Gaunard wrote:
> Ion Gaztañaga wrote:
> > That was a change in the forwarding code. Since perfect forwarding can't
> > be achieved in C++03
> Can't you just overload all the possible const/non-const combinations?
> That would surely do forwarding of constness just fine.
> Of course, this is only feasible if you have few arguments.
Until recently, I thought that the "perfect forwarding" problem was a technical defect of C++03, but then I read through the following:
Robert Jones wrote:
> There's a terrific article about RVO and copy elision by Dave A at
somewhere down, we have the following
Dave Abrahams wrote:
> One place you can apply this guideline immediately is in assignment operators.
> The canonical, easy-to-write, always-correct, strong-guarantee, copy-and-swap
> assignment operator is often seen written this way:
> T& T::operator=(T const& x) // x is a reference to the source
> T tmp(x); // copy construction of tmp does the hard work
> swap(*this, tmp); // trade our resources for tmp's
> return *this; // our (old) resources get destroyed with tmp
> but in light of copy elision, that formulation is glaringly inefficient! It's now "obvious" that the correct way to write a copy-and-swap assignment is:
> T& operator=(T x) // x is a copy of the source; hard work already done
> swap(*this, x); // trade our resources for x's
> return *this; // our (old) resources get destroyed with x
> Reality Bites
So operator= takes "T x" as an argument, but if the function that want to forward its arguments also takes "T x" as argument and passes "x" as argument to operator=, neither RVO nor "copy elision" can help. So something called "rvalues" could be introduced in an attempt to help, let's write it as "T&& x". But at which point in time should the destructor of x now be called? The implementation of operator= probably wants to rely on the fact that the destructor of x gets called upon exit from operator=. But if the destructor of x should also be called upon exist of the function that forwarded x, we must create at least one additional x object so that we have room for two destructor calls. The other alternative is that operator= takes its argument as "T&& x", but now it can no longer rely on the fact that the destructor of x gets called upon exit from operator=. So operator= must now worry about the resources owned by x upon exit, and possibly try to free them. So it is unclear to me whether the "perfect forwarding" problem is solvable at all.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk