C++11 完美的转发和引用折叠

C++11 perfect forwarding and reference collapsing

本文关键字:引用 折叠 转发 完美 C++11      更新时间:2023-10-16

请考虑以下代码:

template<typename T>
void foo(T&& param){ //In this case && is called universal reference
    std:string tmp = std::forward<string>(param);
}

我的问题是,如果可以推断出通用引用类型,为什么我仍然需要调用前置?
为什么不转发 tmp 的正确 c'tor 即使推导出 T 的类型也不会被调用。

我的第二个问题是关于引用折叠规则:

  1. A& &&变得A&
  2. A&& &&变得A&&

因此,根据此规则并考虑到通用参考,为什么std::转发签名不能如下所示:

template<class T> 
T&& forward(T&& arg){
    return static_cast<T&&>(arg);
}

根据上面的规则,如果T的类型是右值引用,它将折叠为右值引用,如果T的类型是左值引用,它将折叠为右值引用。
那么为什么std::forward有两个不同的签名,一个用于左值引用,一个用于右值引用,我错过了什么?

我的问题是,如果可以推断出通用引用类型,为什么我仍然需要调用前置?

因为只要你为参数param命名,它就是一个左值,即使该函数是用右值调用的,所以除非你使用右值,否则它不会作为右值转发forward<T>

为什么不转发 tmp 的正确 c'tor 即使推导出 T 的类型也不会被调用。

因为param是一个左值。要恢复传递给foo的参数的值类别,您需要将其强制转换为string&string&&这意味着您需要知道T被推导为的类型,并使用forward进行强制转换。

那么为什么std::forward有两个不同的签名,一个用于左值引用,一个用于右值引用,我错过了什么?

它被 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3143.html 更改

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3143.html 和 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2951.html 中有很多背景信息

你建议的版本的问题在于,如果你说forward<string>那么参数T不会被推导,所以不能作为转发引用,这意味着T&&不能绑定到左值,它需要能够绑定到左值才能forward<string>(param)工作, 因为那里param是一个左值。