为什么 std::forward 需要转发引用

SU3*_*SU3 6 c++ move-semantics perfect-forwarding c++11 forwarding-reference

在这样的函数模板中

template <typename T>
void foo(T&& x) {
  bar(std::forward<T>(x));
}
Run Code Online (Sandbox Code Playgroud)

如果用右值引用调用,x内部不是右值引用吗?如果 foo 是用左值引用调用的,则无论如何都不需要强制转换,因为在. 也将被推导为左值引用类型,因此不会改变.foofooxfooTstd::forward<T>x

我使用boost::typeindex和不使用std::forward<T>.

#include <iostream>
#include <utility>

#include <boost/type_index.hpp>

using std::cout;
using std::endl;

template <typename T> struct __ { };

template <typename T> struct prt_type { };
template <typename T>
std::ostream& operator<<(std::ostream& os, prt_type<T>) {
  os << "\033[1;35m" << boost::typeindex::type_id<T>().pretty_name()
     << "\033[0m";
  return os;
}

template <typename T>
void foo(T&& x) {
  cout << prt_type<__<T>>{} << endl;
  cout << prt_type<__<decltype(x)>>{} << endl;
  cout << prt_type<__<decltype(std::forward<T>(x))>>{} << endl;
  cout << endl;
}

int main(int argc, char* argv[])
{
  foo(1);

  int i = 2;
  foo (i);

  const int j = 3;
  foo(j);

  foo(std::move(i));

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

g++ -Wall test.cc && ./a.outwithgcc 6.2.0和的输出boost 1.62.0

__<int>
__<int&&>
__<int&&>

__<int&>
__<int&>
__<int&>

__<int const&>
__<int const&>
__<int const&>

__<int>
__<int&&>
__<int&&>
Run Code Online (Sandbox Code Playgroud)

编辑:我找到了这个答案:https : //stackoverflow.com/a/27409428/2640636显然,

只要给参数一个名字,它就是一个左值。

我的问题是,为什么选择这种行为而不是将右值引用保留为右值,即使它们被赋予名称?在我看来,整个转发的考验可以通过这种方式规避。

Edit2:我不是在问什么 std::forward。我在问为什么需要它。

Bo *_*son 3

确实不希望参数自动移动到调用的函数中。考虑这个函数:

template <typename T>
void foo(T&& x) {
  bar(x);
  baz(x);
  global::y = std::forward<T>(x);
}
Run Code Online (Sandbox Code Playgroud)

现在您确实希望自动移动到bar和空参数到baz

当前要求您指定是否以及何时移动或转发参数的规则并非偶然。

  • @SU3如果某件事发生的概率非零,那么它肯定会在某个程序中的某个时间发生。这将是一个很难发现的错误。委员会可能认为(我也持同样的观点)最好制作一份副本,而不是意外移动。`std::forward` 已经有点复杂了,想象一下有一个反 std::forward...人们会发疯的:) (2认同)