Агрегированная инициализация std::массива подобъектов с вложенными списками инициализаторов

#c #initialization #initializer-list #initializer #stdarray

#c #инициализация #инициализатор-список #инициализатор #stdarray

Вопрос:

Каков правильный способ инициализации агрегированного типа (например, std::array ) и его подобъектов с вложенными списками инициализаторов? Я не хочу напрямую вызывать конструкторы подтипа (ов).

Это повторяющаяся проблема, и я всегда удивляюсь, что приведенный ниже код не работает, поскольку указан тип элементов, поэтому компилятор может вывести правильный конструктор.

Обратите внимание, что тип example A не обязательно должен быть агрегированным (но, конечно, он должен поддерживать привязанные списки инициализаторов).

 #include <array>    

struct A
{
    int values[4];
};

int main()
{
    std::array<A, 2> arr{{ 0, 1, 2, 3 }, { 4, 5, 6, 7 }};

    // Works only if A is an aggregate, also looks confusing, I don't want to do this
    //std::array<A, 2> arr{ 0, 1, 2, 3, 4, 5, 6, 7 };

    // I don't want to do this neither
    //std::array<A, 2> arr{A{ 0, 1, 2, 3 }, A{ 4, 5, 6, 7 }};

    return 0;
}
  

Но все, что я получаю, это ошибка

 error: too many initializers for 'std::array<A, 2ul>'
  

Ответ №1:

Вы могли бы добавить фигурные скобки вокруг инициализации подобъекта, например

 std::array<A, 2> arr{{{ 0, 1, 2, 3 }, { 4, 5, 6, 7 }}};
  

std::array<A, 2> arr{{ 0, 1, 2, 3 }, { 4, 5, 6, 7 }}; не работает, потому что для исключения фигурных скобок,

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

Обратите внимание, что 1-е предложение инициализатора { 0, 1, 2, 3 } может использоваться для инициализации всего внутреннего массива std::array (остальные элементы будут инициализированы нулем). Затем { 4, 5, 6, 7} становится избыточным предложением.

Комментарии:

1. Можете ли вы пояснить, почему это требуется? Я думал, что при удалении фигурных скобок дополнительная фигурная скобка не нужна.

2. @plasmacel std::array<A, 2> arr{{ 0, 1, 2, 3 }, { 4, 5, 6, 7 }}; нарушает правило исключения скобок, инициализатор имеет 2 предложения, что не соответствует количеству элементов соответствующего подгруппы,