繁体   English   中英

为什么不`const int ci = 2; std :: forward <int>(ci);`工作以及如何修复/解决它?

[英]Why doesn't `const int ci = 2; std::forward<int>(ci);` work and how to fix / workaround it?

简单的问题,为什么不做以下工作(暗示ci的副本)?

#include <utility>

int main(){
  const int ci = 2;
  std::forward<int>(ci);
}

prog.cpp:在函数'int main()'中:
prog.cpp:6:23:错误:没有匹配函数来调用'forward(const int&)'

在编写一些模板内容时,问题就出现了,我有一个简单的持有者类型,如下所示。 为了避免不必要的副本,我尽可能使用完美转发,但结果证明它似乎是问题的根源。

template<class T>
struct holder{
    T value;

    holder(T&& val)
        : value(std::forward<T>(val))
    {}
};

template<class T>
holder<T> hold(T&& val){
    // T will be deduced as int, because literal `5` is a prvalue
    // which can be bound to `int&&`
    return holder<T>(std::forward<T>(val));
}

template<class T>
void foo(holder<T> const& h)
{
    std::tuple<T> t;  // contrived, actual function takes more parameters
    std::get<0>(t) = std::forward<T>(h.value); // h.value is `const T`
}

int main(){
    foo(hold(5));
}

如果需要任何进一步的信息,请告诉我。
我们非常感谢任何想要绕过这个问题的想法。

这个:

#include <utility>

int main(){
  const int ci = 2;
  std::forward<int>(ci);
}

不起作用,因为你不能隐含地抛弃const std::forward<T>(u)应该被理解为:

转发u作为T

你试图说:

Forward an lvalue `const int` as an rvalue `int`.

扔掉了const 为了避免抛弃const你可以:

#include <utility>

int main(){
  const int ci = 2;
  std::forward<const int>(ci);
}

其中说:

Forward an lvalue `const int` as an rvalue `const int`.

在你的代码中:

template<class T>
void foo(holder<T> const& h)
{
    std::tuple<T> t;  // contrived, actual function takes more parameters
    std::get<0>(t) = std::forward<T>(h.value); // h.value is `const T`
}

h上的const限定符会影响数据成员选择表达式h.value h.value是一个const lvalue int 您可以使用forward将其更改为const rvalue int ,或者可以使用forward将其更改为未更改(作为const lvalue int )。 你甚至可以使用forward来添加volatile (虽然我想不出一个很好的理由)。

在你的榜样,我看到没有理由使用forward在所有的(除非你把const关闭的h )。

    std::get<0>(t) = h.value; // h.value is `const T`

你的评论甚至还是正确的。

这是一个干燥的阅读,但N2951调查你可以做什么,不能做什么forward和为什么。 在标准化之前, N3143对此进行了修改,但在最终的N3143配方中,用例和基本原理仍然有效且未发生变化。

你可以用forward做的事情:

  • 您可以将左值转发为左值。
  • 您可以将左值转发为右值。
  • 您可以将右值转发为右值。
  • 您可以将更少cv限定的表达式转发给更多cv限定的表达式。
  • 您可以将派生类型的表达式转发为可访问的,明确的基类型。

事情你不能做与forward

  • 您不能将右值作为左值转发。
  • 您不能将更多cv限定的表达式转发给更少cv限定的表达式。
  • 您无法转发任意类型的转换(例如,将int转发为double )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM