寻求关于std :: forward的澄清

时间:2018-03-11 00:41:23

标签: c++ c++11 std forward

参考std::forward

对于所有重载,返回类型已指定为T&&(忽略constexpr)。

但是在以下示例附带的说明中:

template<class T>
void wrapper(T&& arg) 
{
    // arg is always lvalue
    foo(std::forward<T>(arg)); // Forward as lvalue or as rvalue, depending on T
}
  • 如果对wrapper()的调用传递了一个rvalue std :: string,那么T就是 推导为std :: string(不是std :: string&amp;,const std :: string&amp;,或 std :: string&amp;&amp;)和std :: forward确保rvalue引用 传给了foo。

  • 如果对wrapper()的调用传递了一个const值 std :: string,然后将T推导为const std :: string&amp;,和 std :: forward确保将const左值引用传递给foo。

  • 如果对wrapper()的调用传递非const左值std :: string,则为T. 推导出std :: string&amp;和std :: forward确保非const 左值引用传递给foo。

在第一个之后的两个实例中,左值引用而不是右值引用(如T&&暗示的那样,这种理解是正确的吗?)已被记录为传递给foo。

如果上述理解是正确的,那么为什么将返回值指定为T&&

1 个答案:

答案 0 :(得分:0)

之间有区别
void f1(int&& a) {}

template<class T>
void f2(T&& a) {}

第一个版本是定义f1来处理rvalues。另一方面,第二个版本是一个模板函数,它接受一个通用(或某些引用,转发)引用作为其参数。

要了解std::forward的机制,您应该使用不同的参数调用f2,如:

#include <iostream>

template <class T> void f2(T &&a) { std::cout << __PRETTY_FUNCTION__ << '\n'; }

int main() {
  int a{5};

  f2(5);
  f2(a);

  return 0;
}

编译代码时,例如g++,您可以从程序中获得以下输出:

./a.out
void f2(T &&) [T = int]
void f2(T &&) [T = int &]

正如您所看到的,在第一个电话中T被推断为int,而在第二个电话中,推断为int &。由于参考折叠规则已经在您的问题的评论中提到,T &&将为您提供T,而T& &&将为您提供T&。简而言之,您观察T&&作为返回类型并不意味着函数返回右值引用。实际上,在模板函数中,&&就像一个身份运算符。与T&合并后,它会为您提供T&;否则,它会给你T

在这个主题上,Arthur O&#39; Dwyer在CppCon2016上有一个really nice talk。也许您可以查看它以了解模板类型扣除规则,这将有助于您澄清std::forward行为。