The syntactic form of T&& in the context of type inference (including the output of a template argument, but, for example, also the type inference of a variable declared as auto ) does not indicate a rvalue reference, but rather Scott Meyers calls [universal reference]. Note that only the special syntax form T&& denotes a universal link, while other similar forms are not considered as such. For example:
template<typename T> void foo(T&& t); <-- T&& is a universal reference template<typename T> void foo(T const&& t); <-- T const&& is NOT a universal reference template<typename T> void foo(S<T>&& t); <-- S<T>&& is NOT a universal reference template<typename T> struct S { void foo(T&& t); }; <-- T&& is NOT a universal reference
Universal references can bind both lvalues ββand r. If an A type lvalue is bound, then T is inferred as A& , and the argument type resolves to A& (value reference) due to the folding of the reference rule ( A& && becomes A& ). If an rvalue of type A bound, then T is inferred as A , and the argument type is resolved to A&& (rvalue reference).
[ Note : the link collapse rule may seem complicated, but it's actually quite simple: to quote Stephan T. Lavavej, βlink links are contagious,β meaning that when forms T&& & T& & or T& && get an instance, they always allowed on T& - only form T&& && permitted on T&& ]
This is why the std::move function std::move will be created as follows when the argument lvalue ( T is output as T& ):
typename remove_reference<A&>::type&& std::move(A& && a);
while it will be created as follows if the argument is rvalue ( T is output as A )
typename remove_reference<A>::type&& std::move(A&& a);
Andy prowl
source share