I know that if a variable or parameter is declared to have type T&&
for some deduced type T
, that variable or parameter is widely called a universal reference.
The term universal reference was introduced by Scott Meyers in his original talk “Universal References in C++11”. However, I wonder what's the official/standard term for universal references.
Universal reference was a term Scott Meyers coined to describe the concept of taking an rvalue reference to a cv-unqualified template parameter, which can then be deduced as either a value or an lvalue reference.
Rvalue references is a small technical extension to the C++ language. Rvalue references allow programmers to avoid logically unnecessary copying and to provide perfect forwarding functions. They are primarily meant to aid in the design of higer performance and more robust libraries.
When t is a forwarding reference (a function argument that is declared as an rvalue reference to a cv-unqualified function template parameter), this overload forwards the argument to another function with the value category it had when passed to the calling function.
Reference collapsing is the mechanism that leads to universal references (which are really just rvalue references in situations where reference-collapsing takes place) sometimes resolving to lvalue references and sometimes to rvalue references.
It is known that since C++11, a parameter of type T&&
is called an rvalue reference [ISO/IEC 14882:2011 §8.3.2/p2 References [dcl.ref] ]. That is, unless T
is a template parameter type or auto
or a typedef
for some lvalue reference type.
examples:
template<typename T> void foo(T&& p) { // -> T is a template parameter ... } auto &&p = expression;
Although technically T&&
in the examples above is still an rvalue reference, its behaviour differs significantly from a regular one.
Naturally, you would ask "why this special case doesn't have a special syntax". The answer is that the &&
syntax was intentionally overloaded for this special construct by the C++ committee. However, they missed to name this special case.
In the absence of a distinct name for this particular construct, Scott Meyers coined the widely known term/name universal references.
The committee however, decided that this name is not proper for a number of reasons. As such, the proposal N4164 made by Herb Sutter, Bjarne Stroustrup and Gabriel Dos Reis proposed to change the name to Forwarding References.
The name Forwarding References had the most support in informal discussions among committee members, including the authors of the proposal mentioned earlier. Interestingly enough, it was Scott Meyers himself that introduced that term in his original “Universal References” talk. However, later he decided to go along with the name universal references. For this decision played role the fact that at the time he didn't think that the term forwarding references included also the auto&&
case.
According to the proposal the term Universal references although is a reasonable name with an obvious meaning, it happens to be wrong in several aspects.
A universal reference must mean the following:
Obviously this is not the case nor is the appropriate use of this construct. Furthermore, this name would encourage many people to consider that something having such a name is meant to be used "universally". Something that the committee considered it a bad thing.
Moreover, "universal references" aren’t even really references per se, but rather a set of rules for using references in a particular way in a particular context with some language support for that use, and that use is forwarding.
auto&&
is Also Considered a Forwarding caseauto&&
is also considered a forward case since it follows the reference collapsing rules. For example in:
[](auto&& x){ … }
for
-ranged loop of the form, for(auto &&i : v) { ... }
auto&&
local variables are for forwarding.The term forwarding references is mentioned in the draft standard N4527 in the following places:
§14.8.2.1/ Deducing template arguments from a function call [temp.deduct.call] (Emphasis Mine):
If P is a cv-qualified type, the top level cv-qualifiers of P’s type are ignored for type deduction. If P is a reference type, the type referred to by P is used for type deduction. A forwarding reference is an rvalue reference to a cv-unqualified template parameter. If P is a forwarding reference and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction. [ Example:
template <class T> int f(T&& heisenreference); 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 ]
§14.8.2.5/p10 Deducing template arguments from a type [temp.deduct.type]:
Similarly, if P has a form that contains (T), then each parameter type Pi of the respective parameter-typelist of P is compared with the corresponding parameter type Ai of the corresponding parameter-type-list of A. If P and A are function types that originated from deduction when taking the address of a function template (14.8.2.2) or when deducing template arguments from a function declaration (14.8.2.6) and Pi and Ai are parameters of the top-level parameter-type-list of P and A, respectively, Pi is adjusted if it is a forwarding reference (14.8.2.1) and Ai is an lvalue reference, in which case the type of Pi is changed to be the template parameter type (i.e., T&& is changed to simply T). [ Note: As a result, when Pi is
T&&
and Ai isX&
, the adjusted Pi will be T, causing T to be deduced asX&
. — end note ] [Example:template <class T> void f(T&&); template <> void f(int&) { } // #1 template <> void f(int&&) { } // #2 void g(int i) { f(i); // calls f<int&>(int&), i.e., #1 f(0); // calls f<int>(int&&), i.e., #2 }
— end example ] If the parameter-declaration corresponding to Pi is a function parameter pack, then the type of its declaratorid is compared with each remaining parameter type in the parameter-type-list of A. Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack. During partial ordering (14.8.2.4), if Ai was originally a function parameter pack:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With