简体   繁体   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?

Simple question, why doesn't the following work (implying a copy of ci )? 简单的问题,为什么不做以下工作(暗示ci的副本)?

#include <utility>

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

prog.cpp: In function 'int main()': prog.cpp:在函数'int main()'中:
prog.cpp:6:23: error: no matching function for call to 'forward(const int&)' prog.cpp:6:23:错误:没有匹配函数来调用'forward(const int&)'

The problem manifested itself while writing some template stuff, where I have a simple holder type as follows. 在编写一些模板内容时,问题就出现了,我有一个简单的持有者类型,如下所示。 To avoid unnecessary copies, I use perfect forwarding where possible, but that turns out to be the root of the problem it seems. 为了避免不必要的副本,我尽可能使用完美转发,但结果证明它似乎是问题的根源。

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));
}

If any further information is needed, please let me know. 如果需要任何进一步的信息,请告诉我。
Any idea to circumvent this problem is greatly appreciated. 我们非常感谢任何想要绕过这个问题的想法。

This: 这个:

#include <utility>

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

doesn't work because you can't implicitly cast away const . 不起作用,因为你不能隐含地抛弃const std::forward<T>(u) should be read as: std::forward<T>(u)应该被理解为:

Forward u as a T . 转发u作为T

You are attempting to say: 你试图说:

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

which throws away the const . 扔掉了const To avoid throwing away the const you could: 为了避免抛弃const你可以:

#include <utility>

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

which says: 其中说:

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

In your code: 在你的代码中:

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

the const qualifier on h impacts the data member selection expression h.value . h上的const限定符会影响数据成员选择表达式h.value h.value is a const lvalue int . h.value是一个const lvalue int You can use forward to change that into a const rvalue int , or you could use forward to pass it on unchanged (as a const lvalue int ). 您可以使用forward将其更改为const rvalue int ,或者可以使用forward将其更改为未更改(作为const lvalue int )。 You could even use forward to add volatile (though I can't think of a good reason to). 你甚至可以使用forward来添加volatile (虽然我想不出一个很好的理由)。

In your example, I'm seeing no reason to use forward at all (unless you take the const off of h ). 在你的榜样,我看到没有理由使用forward在所有的(除非你把const关闭的h )。

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

Your comment is even still correct. 你的评论甚至还是正确的。

It's a dry read, but N2951 surveys what you can and can not do with forward and why. 这是一个干燥的阅读,但N2951调查你可以做什么,不能做什么forward和为什么。 This was modified by N3143 just prior to standardization, but the use cases and rationale from are still valid and unchanged in the final N3143 formulation. 在标准化之前, N3143对此进行了修改,但在最终的N3143配方中,用例和基本原理仍然有效且未发生变化。

Things you can do with forward : 你可以用forward做的事情:

  • You can forward an lvalue as an lvalue. 您可以将左值转发为左值。
  • You can forward an lvalue as an rvalue. 您可以将左值转发为右值。
  • You can forward an rvalue as an rvalue. 您可以将右值转发为右值。
  • You can forward less cv-qualified expressions to more cv-qualified expressions. 您可以将更少cv限定的表达式转发给更多cv限定的表达式。
  • You can forward expressions of derived type to an accessible, unambiguous base type. 您可以将派生类型的表达式转发为可访问的,明确的基类型。

Things you can not do with forward : 事情你不能做与forward

  • You can not forward an rvalue as an lvalue. 您不能将右值作为左值转发。
  • You can not forward more cv-qualified expressions to less cv-qualified expressions. 您不能将更多cv限定的表达式转发给更少cv限定的表达式。
  • You can not forward arbitrary type conversions (eg forward an int as a double ). 您无法转发任意类型的转换(例如,将int转发为double )。

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

相关问题 如何修复错误&#39;std :: promise <int> :: promise(const std :: promise <int> &)&#39;:尝试引用已删除的函数 - How to fix error 'std::promise<int>::promise(const std::promise<int> &)' : attempting to reference a deleted function 为什么基于 int 的访问不适用于 std::get(std::tuple)? - Why doesn't the int-based access work for std::get(std::tuple)? 为什么std :: pair <const int, int> 不适用于某些STL容器? - Why std::pair<const int, int> does not work with some STL containers? 为什么是 std::pair<string, int> 不与 std::string 比较? - Why std::pair<string, int> doesn't compare with std::string? 为什么TBB无法将`int`转换为`const tbb :: atomic <unsigned int> &`,但std :: atomic可以吗? - Why can't TBB cast `int` to `const tbb::atomic<unsigned int>&`, but std::atomic can? 标准::设置<int * const>不会编译 - std::set<int * const> won't compile 为什么 std::tie 不适用于 const 类方法? - Why doesn't std::tie work with const class methods? 为什么const_cast不能处理std :: function的参数? - Why doesn't const_cast work on arguments to std::function? 为什么要诠释 a = std :: max(a,x)不会发出“未初始化”警告 - Why int a; a = std::max(a, x) doesn't emit “uninitialized” warnings 为什么是std :: pair <int, int> 可从const std :: pair构造 <int, float> &? - Why is std::pair<int, int> constructible from a const std::pair<int, float>&?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM