[英]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 aT
.转发
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
做的事情:
Things you can not do with forward
: 事情你不能做与
forward
:
int
as a double
). int
转发为double
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.