C ++ 20 принят p0960 - разрешает инициализацию агрегатов из списка значений в скобках.
Точная формулировка ( [dcl.init] 17.6.2.2 ) говорит:
[...] если конструктор не является жизнеспособным, целевой тип является агрегатным классом, а инициализатор - заключенным в скобки списком выражений, объектом инициализируется следующим образом.
Пусть e 1 ,…, e n - элементы агрегата ([dcl.init.aggr]).
Пусть x 1 ,…, x k будет элементами списка выражений.
Если k больше n, программа не работает
Элемент e i инициализируется копией с x i для 1 ≤ i ≤ k. Остальные элементы инициализируются их инициализаторами членов по умолчанию [...]
Это не позволяет инициализировать внутренний массив списком значений в скобках:
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
не может быть инициализировано с помощью закругленных скобок, предотвращает его участие в общем коде c, который создает объект неизвестного типа T
из списка значений (например, алгоритм, который использует make_shared
, make_unique
, make_from_tuple
et c.).
Почему p0960 не применил более простой подход, сделав () - инициализация больше похоже на {} ?
Например, что-то вроде:
если ни один конструктор не является жизнеспособным, тип назначения агрегатный класс, а инициализатор представляет собой список выражений в скобках, объект будет инициализирован, как если бы значения были отправлены с инициализацией скобками.