Инициализировать std::array, используя тип элемента из объявления неявно

В следующем коде я пытаюсь инициализировать массивы (необработанные C-classic и std::array), сводя к минимуму использование типа элемента, т.е. S:

#include <array>

struct S { unsigned u; int i; };

auto std_array = std::array<S, 3>{
    S{0U, 0},
    S{1U, 1},
    S{2U, 2}
};

S raw_array[] = {
    {0U, 0},
    {1U, 1},
    {2U, 2}
}; 

/*  // compile error: excess elements in struct initializer
std::array<S,3> std_array_no_type = {
    {0U, 0},
    {1U, 1},
    {2U, 2}
}; 
*/

std::array<S,3> std_array_one_type_only = {
    S{0U, 0},
    {1U, 1},
    {2U, 2}
}; 

int main() {}

Используя raw_array, я могу указать S только один раз. Но попытка сделать то же самое с std::array не работает (см. комментарий std_array_no_type). Я должен указать тип S для каждого или (это тоже интересная часть вопроса) только для первого элемента в списке инициализаторов (см. std_array_one_type_only).

Итак, есть ли способ определить инициализированный объект std::array, используя тип S только один раз? Если нет, то в соответствии с каким пунктом стандарта? И почему один явный тип S позволяет компилировать std_array_one_type_only?


person αλεχολυτ    schedule 07.08.2019    source источник
comment
Добавьте еще одну пару фигурных скобок. Поиск дубликата...   -  person Max Langhof    schedule 07.08.2019
comment
Примечание: дубликат охватывает только основной вопрос (ну, название вопроса). Вы задали больше вопросов, чем это - если вы все еще хотите получить конкретные ответы на них, я рекомендую задавать их по отдельности.   -  person Max Langhof    schedule 07.08.2019


Ответы (1)


По 1-му вопросу,

Итак, есть ли способ определить инициализированный объект std::array, используя тип S только один раз?

Вы можете добавить еще одну пару {}, потому что std::array фактически содержит базовый массив.

std::array<S,3> std_array_one_type_only = {{{0U, 0}, {1U, 1}, {2U, 2}}}; 
//                                        ^                           ^ for std::array
//                                         ^                         ^  for underlying array
//                                          ^     ^                     for the 1st element of underlying array
//                                                   ^     ^            for the 2nd element of underlying array
//                                                            ^     ^   for the 3rd element of underlying array

По 2-му вопросу,

И почему один явный тип S позволяет компилировать std_array_one_type_only?

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

Если при инициализации агрегата используется синтаксис copy- (until C++14)list-initialization (T a = {args..} or T a {args..} (since C++14)), фигурные скобки вокруг вложенных списков инициализаторов могут быть опущены (опущены), и в этом случае для инициализации каждого члена или элемента соответствующего подагрегата используется столько предложений инициализатора, сколько необходимо. и последующие предложения инициализатора используются для инициализации следующих членов объекта.

Дано

std::array<S,3> std_array_no_type = {{0U, 0}, {1U, 1}, {2U, 2}}; 
//                                  ^                         ^  for std::array
//                                   ^     ^                     for underlying array

Первый {0U, 0} будет использоваться для инициализации всего базового массива, что приведет к ошибке типа лишние элементы в инициализаторе, потому что std::array не содержит дополнительных подобъектов.

Дано

std::array<S,3> std_array_no_type = {S{0U, 0}, {1U, 1}, {2U, 2}}; 
//                                  ^                          ^ for std::array
//                                    ^     ^                    for the 1st element of underlying array
//                                             ^     ^           for the 2nd element of underlying array
//                                                      ^     ^  for the 3rd element of underlying array

S{0U, 0} нельзя использовать для инициализации базового массива (который не соответствует стилю агрегатной инициализации), тогда он будет использоваться для инициализации 1-го элемента базового массива, т.е. применяется указанное выше правило исключения фигурных скобок, затем следующие {1U, 1} и {2U, 2} используются для инициализации следующих элементов базового массива.

person songyuanyao    schedule 07.08.2019