C++20 从带括号的值列表初始化聚合,不支持内部数组

C++20 initializing aggregates from a parenthesized list of values, not supporting inner array

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

准确的措辞 ([dcl.init] 17.6.2.2) 表示:

[...] 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.

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

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

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

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

这不允许使用带括号的值列表初始化内部数组:

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_sharedmake_uniquemake_from_tuple 等)。


为什么 p0960 没有采用更简单的方法使 ()-initialization更像是 {}?

例如:

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 之间改变:

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 的更改设计原则中找到:

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

r2: Parenthesized initialization and braced-initialization should be as similar as possible, but as distinct as necessary to conform with the existing mental models of braced lists and parenthesized lists. (emphasis mine)

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

当决定与现有心智模型保持一致 1 时,不允许大括号省略似乎是 只有方法。