为什么 '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: In function 'int main()':
Prog.cpp:6:23:错误:没有匹配的函数调用'forward(const int&)'
这个问题在写一些模板的时候出现了,我有一个简单的holder类型,如下所示。为了避免不必要的复制,我尽可能使用完美转发,但这似乎是问题的根源。
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));
}
如果需要进一步的信息,请告诉我。
This:
#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
的左值int
。您可以使用forward
将其更改为const
右值int
,或者您可以使用forward
将其原样传递(作为const
左值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
)。
相关文章:
- 为什么在全局范围内使用"extern int a"似乎不行?
- int(c) 和 c-'0' 之间的区别。C++
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 为什么野牛仍在使用"int yylex(void)",却找不到"int yylex(YYS
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 是否可以从int转换为enum类类型
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- 'short int'持有的值溢出,但"自动"不会溢出?
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- 调用'begin(int [n])'没有匹配函数
- 没有显式声明的int[]中的foreach
- 在c++中访问int到类对象的映射时出错
- 为什么我无法更改"set<set>"循环中的值<int>
- 长 长 int 不要 长 int 好
- C++程序在循环后给出奇怪的int值
- 如何计算数据类型的范围,例如int
- C++ MFC Libraries in Travis CI
- 为什么 'const int ci = 2;std::forward<int>(ci);' 工作以及如何修复/解决它?