【问题标题】:Perfect Fowarding and the Use of std::forward<T>完美转发和 std::forward<T> 的使用
【发布时间】:2017-02-22 11:29:57
【问题描述】:

我目前正试图弄清楚完美转发的工作原理。我已经编写了一段示例代码,据我所知,它可以完美地转发:

void whatIsIt(std::vector<int>&& variable)
{
  std::cout << "rvalue" << std::endl;
}

void whatIsIt(std::vector<int>& variable)
{
  std::cout << "lvalue" << std::endl;
}

template <class T>
void performPerfectForwarding(T&& variable)
{
  whatIsIt(std::forward<T>(variable));
}

int main(int argc, char** argv)
{
  std::vector<int> lvalue;
  performPerfectForwarding(lvalue);
  performPerfectForwarding(std::move(lvalue));

  return 0;
}

使用左值调用函数performPerfectForwarding 使其调用whatIsIt 的相应重载,同样适用于使用右值调用它。因此,此代码生成的输出为:

lvalue
rvalue

但是,我问自己以下版本的函数 performPerfectForwarding 会做什么:

1.

template <class T>
void performPerfectForwarding(T& variable)
{
  whatIsIt(std::forward<T>(variable));
}

2.

template <class T>
void performPerfectForwarding(T variable)
{
  whatIsIt(std::forward<T>(variable));
}

他们都输出:

rvalue
rvalue

现在,我的问题是:这两个替代版本会做什么?它们在任何可能的情况下都有意义吗?与在上述“正确”版本中的应用相比,参考折叠规则在这些情况下如何应用?

【问题讨论】:

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


    【解决方案1】:
    template <class T>
    void performPerfectForwarding(T& variable)
    {
        whatIsIt(std::forward<T>(variable));
    }
    

    variable 不是转发引用 时,T 被推导出为T,即使对于 左值 (与被推导为T&amp;)。因此,这会将variable 转换为右值引用,因为:

    forward<T> -> T&&
    forward<T&> -> T&
    forward<T&&> -> T&&
    

    template <class T>
    void performPerfectForwarding(T variable)
    {
        whatIsIt(std::forward<T>(variable));
    }
    

    同样的考虑也适用于此。 T 在这里永远不能是左值引用,所以forward 将始终转换为右值引用


    这两个替代版本会做什么?它们在任何可能的情况下都有意义吗?

    我不这么认为,因为您的forward 基本上是move


    与在上述“正确”版本中的应用相比,参考折叠规则在这些情况下的应用如何?

    这里的规则照常应用。记住:

    &  &  -> &
    &  && -> &
    && &  -> &
    && && -> &&
    

    在这两种情况下,都没有办法让variable 变成&amp;&amp;

    【讨论】:

    • 感谢您的简洁回答。不过,我仍然在问自己一件事。如果我用左值调用我的函数perfectForwarding(T&amp;&amp;),为什么 T 被推断为引用类型(T&amp;)。折叠规则只会给我`&&`(来自函数签名),折叠时会导致&amp;&amp;。或者它实际上会导致&amp; &amp;&amp;?抱歉,如果我对引用如何与模板结合使用感到有些困惑。如果我有一个函数doSth(int&amp; parameter),那么参数仍然是int 类型,而不是int&amp; 类型。
    • 或者换句话说:如果我有 performPerfectForwarding(T&amp;) 并用左值调用它,T 将在函数内部计算为 T 而不是 T&amp;。那么这是一些只适用于这些“通用引用”(T&amp;&amp;)的疯狂特殊规则吗?
    • '那么这是一些只适用于这些“通用引用”的疯狂的特殊规则吗?' - 几乎是的。见cppreference/template argument deduction/deduction from a function call/4
    • 好的,谢谢,现在很清楚了。因此,假设我想在我的完美转发函数中声明我的类型的变量,因此我必须写std::remove_reference&lt;T&gt;::type localVariable;,而不是只写std::remove_reference&lt;T&gt;::type localVariable;,因为否则我将声明一个未初始化的引用以防左值被传递给函数。
    • 或者在这种情况下使用std::decay 而不是std::remove_reference 会更正确吗?
    猜你喜欢
    • 2020-10-23
    • 2014-01-04
    • 2015-09-07
    • 2015-04-11
    • 1970-01-01
    • 2014-06-12
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多