9

简单的问题,为什么以下工作不起作用(暗示 的副本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));
}

如果需要任何进一步的信息,请告诉我。
非常感谢任何解决此问题的想法。

4

1 回答 1

21

这个:

#include <utility>

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

不起作用,因为您不能隐式丢弃conststd::forward<T>(u)应该读作:

转发uT.

你试图说:

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`
}

const限定符 on影响h数据成员选择表达式h.valueh.value是一个const左值int。您可以使用forward将其更改为constrvalue int,或者您可以使用forward将其不变地传递(作为constlvalue 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 限定表达式。
  • 您不能转发任意类型转换(例如转发 an intas a double)。
于 2011-11-27T18:26:17.520 回答