当不使用带有r值的std::forward时

When not to use std::forward with r-values?

本文关键字:std 值的 forward      更新时间:2023-10-16

不需要std::forward的情况有哪些?它用于包装被模板化为右值的内部函数参数(也就是说,它可以是左值或命名为右值)。类似于:

template<class T>
void outer(T&& t) { 
    inner(std::forward<T>(t)); 
}

我猜有一种情况是内部函数参数通过值传递。还有其他情况吗?当我写std::begin(std::forward<Ct>(ct))时,我遇到了这个问题,其中Ct是模板化的。

编辑关于可能重复的

如果我没记错的话,这是一些不理解这个问题的新手第三次尝试将这个4年前的问题作为重复来结束。

"使用forward的优点?"answers"何时不使用带有r-值的std::forward?"是截然不同的问题。首先介绍了初学者的r值,其次讨论了高级C++用户的完美转发。我是元模板库和lambda库的作者,他们不需要详细的基础描述。答案中的信息和其他问题大不相同。

当模板参数类型包含值类别时,完美的转发是可能的。(如果这句话没有意义,花一分钟时间熟悉一下手头的问题。)

给定:

template <typename T>
void foo(T&& x); 

foo体内,T将采取UU&的形式。前者意味着我们被传递了一个右值,后者意味着我们得到了一个左值。我们可以转发这样的事实:

template <typename T>
void foo(T&& x)
{
    bar(std::forward<T>(x));
}

将左值传递给foobar将获得相同的左值。将右值传递给foobar获得右值。

如果不能区分一个值类别,那么转发就没有用。只有当您有一个以与上面相同的方式推导的模板参数时,它才有用。所以是的,它在这里没有用:

template <typename T>
void foo(const T& x)
{
    // if this was called as foo(1), we're none the wiser
}

我正在回答我自己的问题,因为到目前为止我还没有得到满意的答案。如果我能得到哪怕是一点小小的改进/补充,我会选择你的答案作为接受。

一般来说,如果能达到完美转发的效果,std::forward将有利于内部功能。否则就是多余的。

仅当以下任何一项为真时,才使用std::forward包装内部函数arg:

  • 内部函数参数是模板化的rvalue-ref(现在称为"转发引用")
  • 内部函数具有多个重载,这些重载根据参数r/l值进行区分
  • 内部函数具有多个重载,这些重载基于常量来区分左值参数

使用std::forward(对模板化函数的形式参数,其类型为T&&,T是模板的类型参数):

  • 当内部函数调用是外部函数中参数的最后一次使用时,以及
  • 在可能的情况下,内部函数的重载可能会也可能不会将参数作为右值引用

其原理是,当一个对象可能被右值引用作为参数传递时(这是您使用std::forward所允许的),它的信息内容可能会被破坏。所以,只有当你确信自己不再使用这些信息内容时,你才想这样做。

示例:

#include <utility>
template <class T> void f(T &&t);
template <class T> void g(const T &t);
template <class T>
void outer(bool f_first, T &&t)
  {
    if (f_first)
      {
        f(t);
        g(t);
      }
    else
      {
        g(t);
        f(std::forward<T>(t));
      }
  }
#include <string>
void foo(std::string s)
  {
    outer(true, s);
    outer(true, s + "x");
    outer(false, s);
    outer(false, std::move(s));
  }