模板化右值引用与非模板化编译错误
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)
中,T
是deduced as int&
, and according to reference collapsing规则,int& &&
变为int&
,即左值引用。
这就是它能够绑定到 int x
的原因。
在 f2
中的非模板上下文中,int&&
只是一个右值引用,没有额外的魔法。它只会绑定到右值。
#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)
中,T
是deduced as int&
, and according to reference collapsing规则,int& &&
变为int&
,即左值引用。
这就是它能够绑定到 int x
的原因。
在 f2
中的非模板上下文中,int&&
只是一个右值引用,没有额外的魔法。它只会绑定到右值。