During template argument deduction for a function call, the special rules for "universal references" only apply if the parameter type is a cv-unqualified template parameter [temp.deduct.call]/3
[P
is the parameter type of the function template, and A
is the type of the argument]
If
P
is an rvalue reference to a cv-unqualified template parameter and the argument is an lvalue, the type “lvalue reference toA
” is used in place ofA
for type deduction. [Example:template <class T> int f(T&&); template <class T> int g(const T&&); int i; int n1 = f(i); // calls f<int&>(int&) int n2 = f(0); // calls f<int>(int&&) int n3 = g(i); // error: would call g<int>(const int&&), which // would bind an rvalue reference to an lvalue
— end example ]
Similarly, these rules do not apply to the parameter type A<T>&&
. It is not a "universal reference" but purely an rvalue-reference type.
If you want to have a ranking between two constructors, where the A<T>
-version shall be more specialized (a better match), you can:
- provide
twothree overloadsA<T> const&
,A<T>&
(thanks, Eric Niebler) andA<T>&&
in addition to theT&&
generic version - use SFINAE; provide two overloads with a parameter
T&&
and check ifT
is a specialization ofA<T>