C ++模板函数的行为

时间:2013-10-03 07:24:41

标签: c++ templates c++11 universal-reference

假设我有这个功能:

bool f(int&& one, int&& two) { }

如果我尝试使用此代码调用它:

int x = 4;
f(x, 5);

编译器会抱怨它无法将x从左值引用转换为右值引用,这是正确的。

现在,如果我将f转换为这样的模板函数:

template <class T, class U>
bool f(T&& one, U&& two) { }

然后我可以用左值引用来调用它:

int x = 5;
f(x, 5);

为什么会这样?为什么编译器在这种情况下不抱怨?

3 个答案:

答案 0 :(得分:10)

根据§8.3.3/ 6.这是参考折叠规则。

template <class T> void func(T&&)  // Accepts rvalue or lvalue
void func(T&&)                     // Accepts rvalue only
void func(T&)                      // Accepts lvalue only

值得标准草案的例子:

int i;
typedef int& LRI;
typedef int&& RRI;

LRI& r1 = i;           // r1 has the type int&
const LRI& r2 = i;     // r2 has the type int&
const LRI&& r3 = i;    // r3 has the type int&

RRI& r4 = i;           // r4 has the type int&
RRI&& r5 = 5;          // r5 has the type int&&

decltype(r2)& r6 = i;  // r6 has the type int&
decltype(r2)&& r7 = i; // r7 has the type int&

答案 1 :(得分:8)

因为存在模板参数推断,所以会发生参考折叠。这是Scott Meyers所说的通用引用U&&实际上会成为int &。关于它如何工作以及如何使用它有一个很好的article and video

答案 2 :(得分:6)

这是因为在c ++ 11中添加了参考折叠规则

A& & becomes A&
A& && becomes A&
A&& & becomes A&
A&& && becomes A&&

在模板中应用这些规则但不在正常函数中,通常在函数中没有引用折叠。还有一些其他特定情况会发生引用崩溃,例如出现autodecltypetypedef(包括using声明)这会解释您的结果汇编。必须在c ++ 11中添加引用折叠,因为否则使用像A&amp; A这样的引用。 &安培;因为你不能引用引用而会出错。