This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: [c++0x] unique_ptr.hpp implementation
On Aug 17, 2007, at 9:18 PM, Chris Fairles wrote:
First issue is that I'm not 100% certain when forward is required (vs
move). I wouldn't mind some clarification on the matter.
They almost do the same thing, which can be confusing at times.
Use move when you *always* want to "cast" the argument to an rvalue.
But be careful with the "always". For example consider (simplified
example):
template <class A1>
class tuple
{
A1 a1_;
public:
template <class U>
tuple(U&& u) : a1_(std::move(u)) {}
};
The above is incorrect. The argument passed may have been an rvalue
or lvalue. If u bound to an lvalue, you want to construct a1_ with an
lvalue, and same for rvalues. The "move" would always construct a1_
with an rvalue.
So this is correct:
template <class A1>
class tuple
{
A1 a1_;
public:
template <class U>
tuple(U&& u) : a1_(std::forward<U>(u)) {}
};
Now if u is bound to an lvalue (say of type A2), then U will be
deduced as A2&, and the return type of std::forward<A2&> will be A2&.
Thus a1_ will be constructed with an lvalue A2.
If u is bound to an rvalue (say of type A2), then U will be deduced as
A2, and the return type of std::forward<A2> will be A2&&. Thus a1_
will be constructed with an rvalue A2.
For each use case you need to consider whether the signature is being
bound to lvalues and/or rvalues (and then what you want to do in each
case). This takes some practice as it is an issue that most C++
programmers have previously not cared about.
Also, note that *all* uses of move and forward need to be qualified:
std::move, std::forward. Neglecting the qualification opens up the
possibility that ADL will find a "move" or "forward" in the client's
namespace with different meaning. std::move and std::forward are not
customization points (like swap).
Hope this helps. Please feel free to follow this up with specific use
cases.
-Howard