Search code examples
c++templatesc++11forwardingrvalue-reference

Why is T&& instantiated as int&?


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


Solution

  • 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&.