Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference collapsing?

Tags:

c++

By trying to solve this problem, something made me wonder. Consider the following code:

template <typename T>
struct foo 
{
    foo(T const& x) : data(x) {}
    T data;
};

It seems that I can construct an object of type foo<T const&> without error, the hypothetical T const& const& being understood as T const&.

It seems also that this is called reference collapsing, but I never heard this term before (see comments in the linked question).

Is this widespread? Is this standard?

like image 213
Alexandre C. Avatar asked Sep 22 '10 16:09

Alexandre C.


People also ask

What is reference collapsing?

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.

What is forwarding reference in C++?

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.

What is a reference declaration?

A reference variable declaration is any simple declaration whose declarator has the form. & attr(optional) declarator. (1) && attr(optional) declarator.

What is a reference type in C++?

There are two kinds of references: lvalue references which refer to a named variable and rvalue references which refer to a temporary object.


2 Answers

In C++03, it was not legal to do the following

typedef int &ref;
ref &r = ...; // reference to reference!

This frequently causes problems for people compiling with really strict or older C++03 compilers (GCC4.1 as well as Comeau 8/4/03 do not like the above) because the Standard function object binders do not take care of the "reference to reference" situation, and occasionally create such illegal types.

In C++0x this is called "reference collapsing", yes. Most current C++03 compilers do that (i.e a T& where T denotes a reference type is T again), by retroactively applying the rule. The boost.call_traits library makes it easy to declare such function parameters though, so that the "reference to reference" situation does not occur.

Please note that the const there does not have any effect. A const applied on a reference type is silently ignored. So even if the compiler supports reference collapsing, the following is not legal

int const x = 0;

// illegal: trying to bind "int&" to "int const"!
ref const& r = x; 
like image 119
Johannes Schaub - litb Avatar answered Sep 18 '22 12:09

Johannes Schaub - litb


According to this, in C++98 there was only limited support for reference collapsing:

In C++98, there is only one reference collapsing rule: T& & or a reference to a reference, collapses to T&:

void g(int & ri) {++ri;} // int& & -> int& 
void f(int & ri) {g(ri);}

Even there, it's illegal to try to declare a variable that is a reference to a reference:

int ben;
int& bill(ben);     // OK
int & & bob(bill);  // error C2529: 'bob' : reference to reference is illegal
like image 38
Steve Townsend Avatar answered Sep 21 '22 12:09

Steve Townsend