Reference collapsing (C++0x)

Note: C++0x is a new version of the C++ programming language standard. IBM continues to develop and implement the features of the new standard. The implementation of the language level is based on IBM's interpretation of the standard. Until IBM's implementation of all the features of the C++0x standard is complete, including the support of a new C++ standard library, the implementation may change from release to release. IBM makes no attempt to maintain compatibility, in source, binary, or listings and other compiler interfaces, with earlier releases of IBM's implementation of the new features of the C++0x standard and therefore they should not be relied on as a stable programming interface.
Before C++0x, references to references are ill-formed in the C++ language. In C++0x, the rules of reference collapsing apply when you use references to references through one of the following contexts:
  • A decltype specifier
  • A typedef name
  • A template type parameter
You can define a variable var whose declared type TR is a reference to the type T, where T is also a reference type. For example,
// T denotes the int& type
typedef int& T;
 
// TR is an lvalue reference to T
typedef T& TR;

// The declared type of var is TR
TR var; 
The actual type of var is listed in the following table for different cases, where neither TR nor T is qualified by cv-qualifiers.
Table 1. Reference collapsing without cv-qualifiers
T TR Type of var
A T A1
A T& A&1
A T&& A&&1
A& T A&1
A& T& A&
A& T&& A&
A&& T A&&1
A&& T& A&
A&& T&& A&&
Note:
  1. Reference collapsing does not apply in this case, because T and TR are not both reference types.
The general rule in this table is that when T and TR are both reference types, but are not both rvalue reference types, var is of an lvalue reference type.

Example 1

typedef int& T;

// a has the type int&
T&& a; 
In this example, T is of the int& type, and the declared type of a is T&&. After reference collapsing, the type of a is int&.

Example 2

template <typename T> void func(T&& a);
auto fp = func<int&&>;
In this example, the actual parameter of T is of the int&& type, and the declared type of a is T&&. An rvalue reference to an rvalue reference is formed. After reference collapsing, the type of a is int&&.

Example 3

auto func(int& a) -> const decltype(a)&;
In this example, decltype(a), which is a trailing return type, refers to the parameter a, whose type is int&. After reference collapsing, the return type of func is int&.
You can define a variable var whose declared type TR is a reference to the type T, where T is also a reference type. If either TR or T is qualified by cv-qualifiers, then the actual type of var is listed in the following table for different cases.
Table 2. Reference collapsing with cv-qualifiers
T TR Type of var
A const T const A1
const A volatile T& const volatile A&1
A const T&& const A&&1
A& const T A&1
const A& volatile T& const A&
const A& T&& const A&
A&& const T A&&1
const A&& volatile T& const A&
const A&& T&& const A&&
Note:
  1. Reference collapsing does not apply in this case, because T and TR are not both reference types.
The general rule of this table is that when T is a reference type, the type of var inherits only the cv-qualifiers from T.