C ++ 20 инициализирует агрегаты из списка значений в скобках, не поддерживает внутренний массив - PullRequest
1 голос
/ 27 мая 2020

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 не применил более простой подход, сделав () - инициализация больше похоже на {} ?

Например, что-то вроде:

если ни один конструктор не является жизнеспособным, тип назначения агрегатный класс, а инициализатор представляет собой список выражений в скобках, объект будет инициализирован, как если бы значения были отправлены с инициализацией скобками.

1 Ответ

3 голосов
/ 27 мая 2020

p0960 изменен между r1 и r2:

r2: Эта версия изменяет ментальную модель с исходной «буквальной перезаписи на список в фигурных скобках» на «, как если бы синтезированный явный конструктор с соответствующими инициализаторами памяти был вызван 1 . Это позволяет сужать преобразования в списке, заключенном в скобки, даже если сужающие преобразования были бы запрещены в соответствующем синтаксисе списка в фигурных скобках. Это также разъясняет непродление временных сроков жизни временных конструкций, привязанных к ссылкам, отсутствие исключения скобок и отсутствие четко определенного порядка оценки аргументов.

Причина, по которой это внесенное изменение можно найти в измененных принципах проектирования для p0960:

r1: Инициализация в скобках и инициализация в скобках должны быть как можно более похожими.

r2: Инициализация в скобках и в скобках -инициализация должна быть как можно более похожей, но настолько отличной, насколько это необходимо , чтобы соответствовать существующим ментальным моделям списков в скобках и списков в скобках. ( выделено мной )

" Почему p0960 не применил более простой подход, сделав () -инициализацию более похожей на {}? ":

Когда было принято решение go для соответствия существующим ментальным моделям 1 , запрет на снятие скобок кажется подходом только .

...