模板化右值引用与非模板化编译错误

Templated rvalue reference vs non templated compilation errors

#include <typeinfo>
#include <iostream>
using namespace std;

template<typename T> void f1(T&& a) {}

void f2(int&& a) {}

int main()
{
  int i = 0;
  f1(i);//This is fine
  f2(i);//This gives compilation error

}

为什么相同类型的调用有不同的编译规则?

模板化 f1 接受 lvalue,但非模板化函数不接受 lvalue。为什么? f1 for int 的模板实例化看起来不像 f2 吗?

我可以用 std::move 解决编译问题。不过上面一个没看懂。

test.cpp: In function 'int main()': test.cpp:13:7: error: cannot bind 'int' lvalue to 'int&&' f2(i);

test.cpp:7:6: note: initializing argument 1 of 'void f2(int&&)' void f2(int&& a) {}

在模板上下文中,T&& 不仅仅是一个右值引用,它是一个 forwarding reference

在调用f1(i)中,Tdeduced as int&, and according to reference collapsing规则,int& &&变为int&,即左值引用。

这就是它能够绑定到 int x 的原因。

f2 中的非模板上下文中,int&& 只是一个右值引用,没有额外的魔法。它只会绑定到右值。