C ++ 11完美转发和参考折叠

时间:2014-12-10 19:35:18

标签: c++ c++11 perfect-forwarding forwarding-reference

考虑以下代码:

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&&
  3. 所以根据这个规则并考虑到通用引用为什么std :: forward签名不能如下:

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

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

1 个答案:

答案 0 :(得分:2)

  

我的问题是,如果可以推断出通用参考类型,为什么我还需要呼叫前转?

因为只要给参数param命名,它就是左值,即使用rvalue调用函数,所以除非使用{{1,否则它不会作为右值转发}}

  

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

因为forward<T>是左值。要恢复传递给param的参数的值类别,您需要将其强制转换回foostring&,这意味着您需要知道推导出的string&&类型,并使用T进行演员表。

  

那么为什么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.htmlhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2951.html

中有很多背景信息

您建议的版本存在的问题是,如果您说std::forward,则不会推断出参数forward<string>,因此不会用作转发参考,这意味着T可以' t绑定到左值,它需要能够绑定到左值以使T&&起作用,因为forward<string>(param)是左值。