2

例如

template <typename T>
void function(T&& arg)

有人可以详细解释一下函数签名是如何结束左值的 T& 和传入的右值的 T&& 的吗?我知道以某种方式(需要标准行) T -> T& 在左值的情况下和 T -> T 在重值的情况下,然后通过组合 & 和 && 它产生左值/右值引用。

4

2 回答 2

5

该规则可在第 8.3.2p6 节中找到。

如果 typedef 、 type template-parameterdecltype-specifier表示的类型TR 是对 type 的引用T,则尝试创建类型“lvalue reference to cv TR ”会创建类型“lvalue reference to T”,而尝试创建类型“lvalue reference to cv”时创建类型“对cv TR的右值引用”创建类型TR

或以表格形式:

TR   R

T&   &  -> T&  // lvalue reference to cv TR -> lvalue reference to T
T&   && -> T&  // rvalue reference to cv TR -> TR (lvalue reference to T)
T&&  &  -> T&  // lvalue reference to cv TR -> lvalue reference to T
T&&  && -> T&& // rvalue reference to cv TR -> TR (rvalue reference to T)
于 2012-10-23T14:29:21.457 回答
4

这要归功于参考折叠规则。假设这U是一个非引用类型;然后:

    T = U             T & = U &       T && = U &&
If  T = U &  ,  then  T & = U &  and  T && = U &    .
    T = U &&          T & = U &       T && = U &&

因此,如果您的函数参数可以绑定到类型的左值引用U,则T必须推导出为U &才能T &&成为U &,这是唯一的选择,因为左值不能绑定到右值引用。另一方面,如果您的参数是 type 的右值U,则推导T出为U,并且您的参数可以绑定。T &&U &&

关键是匹配的引用类型是T &&(而不是T!)。但是,由于arg它本身是一个命名变量,因此是一个左值,因此您必须使用它std::forward<T>(arg)来创建一个与调用您的函数的表达式相同的表达式。

于 2012-10-23T14:36:31.797 回答