C ++ 20从带括号的值列表初始化聚合,不支持内部数组 [英] C++20 initializing aggregates from a parenthesized list of values, not supporting inner array

查看:160
本文介绍了C ++ 20从带括号的值列表初始化聚合,不支持内部数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C ++ 20采用了 p0960 -允许从带括号的值列表中初始化聚合。

C++20 adopted p0960 - allowing initialization of aggregates from a parenthesized list of values.

确切的用词( [dcl.init] 17.6.2.2 )说:

The exact wording ([dcl.init] 17.6.2.2) says:


[...]构造函数是可行的,目标类型是聚合的
类,初始化程序是带括号的表达式列表,
对象的初始化如下。

[...] if no constructor is viable, the destination type is an aggregate class, and the initializer is a parenthesized expression-list, the object is initialized as follows.

让e 1 ,...,e n 成为合计([dcl.init.aggr])中的元素

Let e1 , …, en be the elements of the aggregate ([dcl.init.aggr]).

让x 1 ,…,x k 成为表达式列表的元素。

Let x1, …, xk be the elements of the expression-list.

如果k大于n,则程序格式错误。

If k is greater than n, the program is ill-formed.

元素e i 使用以下命令进行复制初始化: x i 等于1
≤i≤k。其余元素使用其默认的
成员初始化程序进行初始化[...]

The element ei is copy-initialized with xi for 1 ≤ i ≤ k . The remaining elements are initialized with their default member initializers [...]

这不允许内部变量的初始化带有括号的值列表的数组:

This doesn't allow initialization of inner array with parenthesized list of values:

struct Foo {
    int i, j;
};

struct Moo {
    int arr[2];
};

int main() {
    // before C++20:
    Foo foo1{1, 2};
    // with C++20:
    Foo foo2(1, 2); // p0960! we are good

    // before C++20:
    Moo moo1{1, 2};
    // C++20 - oops p0960 doesn't help here:
    Moo moo2(1, 2); // error: too many initializers

    // before C++20:
    std::array<int, 2> arr1{1, 2};   // OK
    std::array<int, 2> arr2({1, 2}); // OK
    std::array<int, 2> arr3{{1, 2}}; // OK
    // C++20 - oops p0960 doesn't help here:
    std::array<int, 2> arr4(1, 2); // error: too many initializers
}

std :: array 不能用圆括号初始化,从而阻止其参与从以下列表中创建未知类型 T 的对象的通用代码中值(例如,使用 make_shared make_unique make_from_tuple 等。)

The fact that std::array cannot be initialized with rounded brackets prevents it from participating in a generic code that creates an object of unknown type T from a list of values (e.g. an algorithm that uses make_shared, make_unique, make_from_tuple etc.).

例如,像这样:


如果没有构造函数是可行的,则目标类型是聚合的
类,并且使用初始化程序如果是带括号的表达式列表,则
对象将被初始化,就好像值是通过括号初始化发送的。

if no constructor is viable, the destination type is an aggregate class, and the initializer is a parenthesized expression-list, the object would be initialized as if the values were sent with brace-initialization.


推荐答案

p0960在r1和r2之间更改:

p0960 changed between r1 and r2:

r2:此修订将心理模型从原始的将文字重写为括号列表更改为 ,就像调用了带有适当的mem-initializers的综合显式构造函数一样。 1 。即使在相应的括号列表语法中禁止缩小转换的情况下,也具有允许在括号列表中缩小转换的效果。它还阐明了不延长引用临时对象的临时寿命,不存在大括号省略和不存在对参数进行明确定义的求值顺序。

r2: This revision changes the mental model from the original "literal rewrite to a braced list" to "as if a synthesized, explicit constructor with appropriate mem-initializers was called" 1. This has the effect of allowing narrowing conversions in the parenthesized list, even when narrowing conversions would be forbidden in the corresponding braced list syntax. It also clarifies the non-extension of temporary lifetimes of temporaries bound to references, the absence of brace elision, and the absence of a well-defined order of evaluation of the arguments.

进行此更改的原因可以在已更改的p0960设计原理中找到:

The reason why this change was made can be found in the changed design principles for p0960:


r1:括号内的初始化和括号内的初始化

r1: Parenthesized initialization and braced-initialization should be as similar as possible.

r2:
括号化的初始化和支撑初始化应尽可能相似,但必须与众不同,以与现有的一致括号列表和括号列表的心理模型。
强调我的

为什么p0960没有采用更简单的方法()初始化,更像{}?

当决定与现有心理模型保持一致时 1 已被采用,不允许括号删除似乎是 only 方法。

When the decision to go for conformance with the existing mental models 1 had been taken, not allowing brace elision seems like the only approach.

这篇关于C ++ 20从带括号的值列表初始化聚合,不支持内部数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆