C++, rvalue references in function parameters

Some formal explanation in addition to @songyuanyao's answer:

N4296::14.8.2.1 [temp.deduct.call]:

Template argument deduction is done by comparing each function template parameter type (call it P) with the type of the corresponding argument of the call (call it A) as described below.

N4296::14.8.2.1/3 [temp.deduct.call]:

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.

The Standard also provides the following 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&&)

That's exactly your case.


Like @Peter said, the type of T is deduced as string&, and C++’s reference-collapsing rule says:

T& & ⇒ T& // from C++98
T&& & ⇒ T& // new for C++0x
T& && ⇒ T& // new for C++0x
T&& && ⇒ T&& // new for C++0x

So func’s instantiation is actually:

void func(string& str)

And it works.