Several sources given the C++ reference collapsing rules as follows:
A& & becomes A&
A& && becomes A&
A&& & becomes A&
A&& && becomes A&&
(e.g. http://thbecker.net/articles/rvalue_references/section_08.html )
I can give the following example for A&&& becomes A&
template <class T> void f1(T&& param) {
// T t = 5; // does not compile because T is T&
param++; // param collapses from int&&&& to int&&
}
void demo()
{
int x = 8;
int &y = x;
f1(y); // OK T will still be int&, param will go to int&&& -> collapses to int&
cout << y; // prints 9
}
I would like something similar for A&& && becomes A&&, however when I call with an RValue , T is deduced to int, and so this does not show what I would like to.
template <class T> void f1(T&& param) {
T t = 5; // compiles since T is int
T t2 = t; // would not compile if T was int&&
t2++;
cout << t; // prints 5 since t2 was not a reference
}
void demo()
{
f1(8); // OK T deduced to int, param will go to int&& , no collapsing
}
Can someone help me show a similar example where T is deduced to T&& and the parameter is collapsed from T&&&& to T&&?
If we are talking about actual deduction, where the template argument
Tis not given explicitly or defaulted somehow, that's impossible. The reason is that forwarding relies not only on reference collapsing.To begin with, we must note that in C++ an argument to a function (template) is always some sort of expression. And expressions never have reference type.
You can't actually produce an argument to a function that is of reference type. So
Tcannot be deduced to be a reference under normal circumstances. Forwarding works by also relying on a special case for reference function parameters in templates.As you can see, a forwarding reference is specifically designed around the value category of the expression supplied as an argument. It is only if the expression is an lvalue, that the type of the argument is taken as "lvalue reference to A". Otherwise, there is no adjustment done. And so
Tis going to be deduced as the type being referred to.The reference collapsing rules only come into play for when the type argument is explicitly given. In that case, when
int&&is supplied somehow, we get an rvalue reference by virtue of reference collapse. But it is not after template argument deduction.