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

Xeo*_*Xeo 9 c++ perfect-forwarding c++11

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

#include <utility>

int main(){
  const int ci = 2;
  std::forward<int>(ci);
}
Run Code Online (Sandbox Code Playgroud)

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));
}
Run Code Online (Sandbox Code Playgroud)

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

How*_*ant 19

这个:

#include <utility>

int main(){
  const int ci = 2;
  std::forward<int>(ci);
}
Run Code Online (Sandbox Code Playgroud)

不起作用,因为你不能暗中抛弃const. std::forward<T>(u)应该理解为:

转发uT.

你试图说:

Forward an lvalue `const int` as an rvalue `int`.
Run Code Online (Sandbox Code Playgroud)

扔掉了const.为了避免丢弃,const你可以:

#include <utility>

int main(){
  const int ci = 2;
  std::forward<const int>(ci);
}
Run Code Online (Sandbox Code Playgroud)

其中说:

Forward an lvalue `const int` as an rvalue `const int`.
Run Code Online (Sandbox Code Playgroud)

在你的代码中:

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`
}
Run Code Online (Sandbox Code Playgroud)

const上限定符h影响数据成员选择表达h.value. h.value是一个const左值int.您可以使用forward它将其更改为const右值int,或者您可以使用forward它来保持不变(作为const左值int).你可以甚至使用forwardvolatile(虽然我不能想到一个很好的理由).

在你的例子中,我看不出任何理由forward(除非你const取消h).

    std::get<0>(t) = h.value; // h.value is `const T`
Run Code Online (Sandbox Code Playgroud)

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

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

你可以做的事情forward:

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

不能做的事情forward:

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