sup*_*uan 18 c++ templates c++11 universal-reference
假设我有这个功能:
bool f(int&& one, int&& two) { }
Run Code Online (Sandbox Code Playgroud)
如果我尝试使用此代码调用它:
int x = 4;
f(x, 5);
Run Code Online (Sandbox Code Playgroud)
编译器会抱怨它不能将x从左值引用转换为右值引用,这是正确的.
现在,如果我将f转换为模板函数,如下所示:
template <class T, class U>
bool f(T&& one, U&& two) { }
Run Code Online (Sandbox Code Playgroud)
然后我可以用左值引用来调用它:
int x = 5;
f(x, 5);
Run Code Online (Sandbox Code Playgroud)
为什么会这样?为什么编译器在这种情况下不抱怨?
mas*_*oud 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
Run Code Online (Sandbox Code Playgroud)
值得标准草案的例子:
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&
Run Code Online (Sandbox Code Playgroud)
这是因为在c ++ 11中添加了引用折叠规则
A& & becomes A&
A& && becomes A&
A&& & becomes A&
A&& && becomes A&&
Run Code Online (Sandbox Code Playgroud)
在模板中应用这些规则但不在正常函数中,通常在函数中没有引用折叠.还有一些其他特定情况,其中引用折叠将发生,如存在auto,decltype或typedef(包括using声明)解释编译的结果.必须在c ++ 11中添加引用折叠,因为否则使用像A&&这样的引用会变成错误,因为您无法引用引用.