§8.3.2 [dcl.ref]/p6:
If a typedef-name (7.1.3, 14.1)* or a decltype-specifier (7.1.6.2)
denotes a type TR that is a reference to a type T, an attempt to
create the type “lvalue reference to cv TR” creates the type “lvalue
reference to T”, while an attempt to create the type “rvalue reference
to cv TR” creates the type TR.
This is known as reference collapsing and is introduced in C++11. In C++03, your code would be ill-formed, but some compilers supported it as an extension.
Note that in const T &
, the const
applies to the type T
, so when T
is int &
, the const
would apply to the reference type itself (which is meaningless as references are immutable anyway), not the type referred to. This is why the reference collapsing specification ignores any cv-qualifiers on TR
.
*A template type parameter is a typedef-name, per §14.1 [temp.param]/p3:
A type-parameter whose identifier does not follow an ellipsis
defines its identifier to be a typedef-name (if declared with
class
or typename
) or template-name (if declared with
template
) in the scope of the template declaration.