only the general (or primary? What is the correcto word here?) template
The technical term used by the C++ Standard is "primary class template". It will also be the most general class template, compared to its partial specializations and explicit specializations. So that could also be a reasonable thing to call it, given enough context.
The "reference collapsing rule" is found in [dcl.ref]/6 and applies mainly when determining the meaning of combining a specific type name which aliases a reference type with a &
or &&
token which would normally form a reference to the type name's type. Deducing template arguments for a template parameter of the form T&
or T&&
is sort of the reverse of that. Although it's helpful to think of template argument deduction as "find the template arguments so that the resulting types match up", the technical details of template argument deduction are much more specific; [temp.deduct] is several pages of rules for exactly how this deduction proceeds, and there are additional relevant rules in other sections. The detail is needed so compilers agree on cases when there could otherwise be more than one "correct" answer, and so that compilers aren't required to deal with some of the more difficult cases.
In particular, when matching a dependent type P
with a known type A
, by the list of deducible types in [temp.deduct.type]/8, deduction can occur if both P
and A
have the form T&
or if both have the form T&&
. When attempting argument deduction for the partial specialization remove_reference<T&&>
to determine the definition of remove_reference<int&>
, P
is T&&
and A
is int&
, so they do not share one of these forms.
The template argument deduction rules do not have a general allowance for deducing arguments from a reverse of the reference collapsing rule. But they do have a limited allowance which is related for certain cases: Per [temp.deduct.call]/3, if T
is a template type parameter, but not a parameter for a class template, then the type T&&
is a forwarding reference. When comparing types for argument deduction, if P=T&&
is a forwarding reference type and A
is an lvalue reference type, then the template type parameter T
can be deduced as the lvalue reference type A
, only if A
is the type of an lvalue function argument expression ([temp.deduct.call]/3 again) or sometimes if P
and A
are being compared because they represent function parameter types within two compared function types ([temp.deduct.type]/10).
Similarly, when ["]calling["] remove_reference_t<int&&>
, can't the first specialization's T&
match int&&
if T
is substituted for T&
?
In this case, there's no possible way that the partial specialization remove_reference<T&>
can match remove_reference<int&&>
. Even if the process of template argument deduction allowed finding a potential answer for this case, there is no possible type T
such that T&
is the same as int&&
.
char&&
,std::string&
,int*&
, but notT&
/T&&
whenT
is a template parameter? There are still some bits not clear to me, especially in the 4th paragraph (the 3rd paragraph starting with The). I'll comment again this evening to be more specific about what's not clear to me. – Mason