首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >P0960,有没有什么机制可以检测在c++20中使用()s初始化的新聚集体中是否存在缩小?

P0960,有没有什么机制可以检测在c++20中使用()s初始化的新聚集体中是否存在缩小?
EN

Stack Overflow用户
提问于 2019-04-08 19:10:38
回答 2查看 132关注 0票数 4

使用P0960“允许从带括号的值列表中初始化聚合”,您也可以使用()初始化聚合。

然而,这个初始化允许缩小范围,而{}s不允许。

代码语言:javascript
复制
#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
}

是否可以使用带括号的C++20聚合初始化来检测缩小转换范围?

EN

回答 2

Stack Overflow用户

发布于 2019-04-08 20:17:48

Paren-初始化聚合允许缩小转换范围。

构造函数和聚合初始化的行为不同,该功能看起来像构造函数调用,因此它被故意设计为尽可能像构造函数调用。聚合初始化的所有值得注意的特性(缩小转换范围、延长引用的生命周期等)在参数初始化的情况下是故意不存在的。

唯一的区别是,paren初始化聚合确实从左到右计算表达式(而对于构造函数调用,我们对参数的计算是不确定的)。

具体地说:

代码语言:javascript
复制
 auto q = new Foo(INT_MAX, UINT_MAX); 

将主要表现为您实际编写了此构造函数:

代码语言:javascript
复制
struct Foo
{
  Foo(int x, int y) : x(x), y(y) { } // ~ish
  int x, y;
};

它本身不会对我今天尝试的任何编译器发出警告。

票数 7
EN

Stack Overflow用户

发布于 2019-04-11 01:21:55

在使用()初始化时,您不应该想要“限制范围”。

此功能的要点是允许在转发场景中使用聚合,例如container::emplace、就地构造函数等。它们目前不起作用,因为std::allocator_traits<>::construct不会也不能使用列表初始化语法,因为在很多情况下,它会隐藏您可能想要调用的构造函数。

在转发场景中,在处理聚合时,准确剔除缩小转换的能力是有限的。为什么?请考虑以下内容:

代码语言:javascript
复制
struct Agg { int i; };

Agg a{5.0f};

这不是缩小转换,因为特定的浮点文字值可以转换为int而不会损失精度。但是,当您通过emplace等转发构造时,编译器无法看到参数的实际值。它只看到类型。因此,如果您要这样做:

代码语言:javascript
复制
vector<Agg> v;
v.emplace_back(5.0f);

编译器所看到的就是emplace_back将尝试将一个float传递给Agg的聚合初始化。这始终是缩小转换,因此始终是非法的。

列表初始化的缩小预防是有意义的,因为带括号的init列表最好在本地使用。被初始化的类型是已知的,并且在使用{}的地方将直接提供任何文字值。因此,有足够的信息来以合理的方式处理缩小范围的问题。

一旦你进入转发阶段,这就不能正常工作了。缩小预防将剔除其值在本地应该是好的参数。

所以问题是这样的:对于所有有效的X、Y和Z,您希望emplace(X, Y, Z)Agg{X, Y, Z}一样工作吗?如果答案是肯定的,则()聚合初始化无法阻止范围缩小。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55572101

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档