C++ P0960,是否有任何类型的机制来检测新聚合init中是否有收缩,c+中的()s+;20?
使用“允许从带括号的值列表初始化聚合”,还可以使用C++ P0960,是否有任何类型的机制来检测新聚合init中是否有收缩,c+中的()s+;20?,c++,c++-standard-library,c++20,narrowing,C++,C++ Standard Library,C++20,Narrowing,使用“允许从带括号的值列表初始化聚合”,还可以使用()s执行聚合初始化 但是,此初始化允许缩小,而{}s不允许缩小 #include <vector> #include <climits> struct Foo { int x, y; }; int main() { // auto p = new Foo{INT_MAX, UINT_MAX}; // still won't compile auto q = new Foo(INT_MAX, UINT_MA
()
s执行聚合初始化
但是,此初始化允许缩小,而{}
s不允许缩小
#include <vector>
#include <climits>
struct Foo
{
int x, y;
};
int main()
{
// auto p = new Foo{INT_MAX, UINT_MAX}; // still won't compile
auto q = new Foo(INT_MAX, UINT_MAX); // c++20 allows narrowing aggregates init
std::vector<Foo> v;
// v.emplace_back(Foo{INT_MAX, UINT_MAX}); // still won't compile
v.emplace_back(INT_MAX, UINT_MAX); // c++20 allows narrowing aggregates init
// in furtherly perfect forwardings
}
#包括
#包括
结构Foo
{
int x,y;
};
int main()
{
//auto p=new Foo{INT\u MAX,UINT\u MAX};//仍然不会编译
auto q=new Foo(INT_MAX,UINT_MAX);//c++20允许缩小聚合初始化
std::向量v;
//v.emplace_back(Foo{INT_MAX,UINT_MAX});//仍然不会编译
v、 emplace_back(INT_MAX,UINT_MAX);/c++20允许缩小聚合初始值
//进一步完善货运代理
}
是否可以使用带括号的C++20聚合初始化来检测缩小转换?聚合初始化允许缩小转换 构造函数和聚合初始化的行为不同,并且该功能看起来像构造函数调用,因此有意将其设计为尽可能像构造函数调用。聚合初始化的所有显著特征(缩小凸度、引用的生存期延长等)在paren初始化情况下并不存在 唯一的区别是paren初始化聚合时会从左到右计算表达式(而使用构造函数调用时,我们会对参数进行不确定的计算)
具体而言:
auto q = new Foo(INT_MAX, UINT_MAX);
将主要表现为您实际编写了此构造函数:
struct Foo
{
Foo(int x, int y) : x(x), y(y) { } // ~ish
int x, y;
};
它本身不会对我今天尝试的任何编译器发出警告 在使用()初始化时,不应该希望“限制狭窄” 此功能的要点是允许在转发场景中使用聚合,例如
container::emplace
、就地构造函数等。它们目前不起作用,因为std::allocator\u traits::construct
不会也不能使用列表初始化语法,因为在很多情况下它会隐藏您可能想要调用的构造函数
在转发场景中,在处理聚合时,准确剔除缩小转换的能力受到限制。为什么?考虑这一点:
struct Agg { int i; };
Agg a{5.0f};
这不是缩小转换范围,因为特定的浮点文字值可以转换为int
,而不会损失精度。但是,当您通过emplace
等转发构造时,编译器无法看到参数的实际值。它只看到类型。因此,如果你要这样做:
vector<Agg> v;
v.emplace_back(5.0f);
向量v;
v、 后置炮台(5.0f);
编译器看到的只是emplace\u back
将尝试向Agg
的聚合初始化传递一个float
。这始终是一个缩小的转换,因此始终是非法的
列表初始化的缩小预防有一定的意义,因为带括号的init列表最好在本地使用。正在初始化的类型是已知的,在使用{}
的地方将直接提供任何文本值。因此,有足够的信息以合理的方式处理缩小范围的问题
一旦你进入转发,这就不起作用了。缩小预防范围将剔除局部值良好的参数
所以问题是:对于所有有效的X,Y和Z,你是否希望
emplace(X,Y,Z)
像Agg{X,Y,Z}
一样工作?如果答案是肯定的,那么聚合初始化无法阻止缩小。您正在寻找编译器特定的答案吗?@p.W“Anything”我担心这个标准操作可能会由于不知道缩小而导致许多微妙的错误。更重要的是,完美的转发实际上是“无处不在”。如果一个人能在他或她感到不舒服的地方“限制”狭窄,那一定是一种解脱。这个例子真是致命!但是,我们如何限制“外部”上“Foo”初始化的狭窄性呢?@sandthorn与您今天所做的一样-使用{}
我感觉像是有了-frestrict-showing-paren-aggregates init
这样的东西。所以我不会错过我想念自己的地方。