转发参考是否仍然是右值参考?

时间:2019-07-01 21:17:11

标签: c++ c++11 rvalue-reference lvalue forwarding-reference

我仍然对为支持移动和转发而发明的规则感到困惑。我仍然不确定的一件事是:

是转发参考,只是右值参考(带有    参考折叠规则适用?)

如果它是右值引用,那么为什么要执行该功能:

template<typename T>
void func(T&&);

不仅接受右值,还接受左值吗?

2 个答案:

答案 0 :(得分:1)

在替换T之前,T &&是右值引用(很明显)。

T被替换之后(并且引用被折叠之后),T &&仍然是右值引用(如果T不是引用),或者成为左值引用(如果{ {1}}是左值引用。

答案 1 :(得分:1)

我不确定这个答案是否会让您满意,但是我可以指出标准的相关部分。简而言之,引用T&&在语法上始终是右值引用,但有时最终声明的类型是左值引用类型。

如果这是模板自变量推导的结果,则整个构造称为“转发参考”,是一种方便的简写。 (这种情况需要引用折叠,但是模板参数推导并不是引用折叠的唯一时间。)

现在,继续使用标准措辞。首先,我们有[dcl.ref](例如p2p6):

  

使用&声明的引用类型称为左值引用,使用&&声明的引用类型称为右值引用< / em>。 [...]

     

如果 typedef-name (9.1.3,13.1)或 decltype-specifier (9.1.7.2)表示类型TR为引用类型T,创建类型“对 cv TR的左值引用”的尝试会创建类型“对T的左值引用”,而   尝试创建类型“对 cv TR的右值引用”会创建类型TR。 [注意:此规则称为参考折叠。 — 尾注]

最后,模板参数推导的情况在[temp.deduct.call] p3中处理:

  

转发参考是对cv不合格模板参数[...]

的右值参考

换句话说,转发引用一个右值引用,但它也是一个接受左值的引用。 (请注意,标准的“转发参考”定义实际上不需要推导模板参数,尽管这通常是触发参考折叠行为的主要方式。)