Can anyone please explain why this compiles and why does t
end up with type int&
?
#include <utility>
void f(int& r)
{
++r;
}
template <typename Fun, typename T>
void g(Fun fun, T&& t)
{
fun(std::forward<T>(t));
}
int main()
{
int i = 0;
g(f, i);
}
I see this on GCC 4.5.0 20100604 and GDB 7.2-60.2
Because of perfect forwarding, when the argument to P&&
is an lvalue, then P
will be deduced to the argument's type plus having a &
attached. So you get int & &&
with P
being int&
. If the argument is an rvalue then P
will be deduced to only the argument's type, so you would get an int&&
argument with P
being int
if you would pass, for example 0
directly.
int& &&
will collapse to int&
(this is a semantic view - syntactically int& &&
is illegal. But saying U &&
when U
is a template parameter or a typedef refering to a type int&
, then U&&
is still the type int&
- i.e the two references "collapse" to one lvalue reference). That's why t
has type int&
.