[c++0x] std::move vs. std::forward

CoffeeBuzz chris.fairles@gmail.com
Thu Aug 23 01:33:00 GMT 2007


This discussion originally spawned in the thread titled "[c++0x]
unique_ptr.hpp implementation" but since it has little to do with unique_ptr
I've moved it here. The discussion started with the following question and I
included Howard's response below.

On Aug 17, 2007, at 9:18 PM, Chris Fairles wrote:
> 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


-- 
View this message in context: http://www.nabble.com/-c%2B%2B0x--std%3A%3Amove-vs.-std%3A%3Aforward-tf4314952.html#a12286022
Sent from the gcc - libstdc++ mailing list archive at Nabble.com.



More information about the Libstdc++ mailing list