Почему 2D std :: array не может быть инициализирован двумя слоями инициализаторов списка? - PullRequest
0 голосов
/ 08 сентября 2018

Может кто-нибудь помочь мне понять, почему мой компилятор не может / не выводит это?(с использованием g ++ 7.3)

Не работает:

#include <array>
std::array<std::array<double,2>,2> f() {
 return {{0,0},{0,0}};
}

Работает нормально:

#include <array>
std::array<std::array<double,2>,2> f() {
 return {std::array<double,2>{0,0},{0,0}};
}

Также странно, что это тоже не получается:

#include <array>
std::array<std::array<double,2>,2> f() {
 return std::array<std::array<double,2>,2>{{0,0},{0,0}};
}

@ 1201ProgramAlarm указал, что добавление еще одного набора фигурных скобок работает:

#include <array>
std::array<std::array<double,2>,2> f() {
 return {{{0,0},{0,0}}};
}

Используется агрегатная инициализация, потому что std::array не имеет конструктора для brace-init-list.Это нормально, но тогда почему / как это работает?

std::array<double,2> x{1,2};

почему он обрабатывает этот случай, но не вложенный случай?

1 Ответ

0 голосов
/ 08 сентября 2018

Контейнер std::array эквивалентно является структурой, содержащей C-массив (реализация не может реализовать std::array таким образом, но он должен гарантировать, что семантика одинакова), поэтому он должен быть инициализирован двумя уровнямифигурные скобки, т. е.

#include <array>
std::array<std::array<double,2>,2> f() {
   return {{{{0,0}},{{0,0}}}};
} 

Конечно, фигурные скобки в списке инициализаторов могут быть исключены, как это обычно делается для двумерного массива:

int arr[2][2] = {0,1,2,3};

... но инициализатор-Список, который начинается с исключенных фигурных скобок до исключения, не должен начинаться с левой фигурной скобки после исключения.Другими словами, если список инициализатора начинается с левой фигурной скобки, компилятор не будет учитывать возможность того, что этот список инициализатора имеет исключенные внешние фигурные скобки.

В вашем инициализаторе {{0,0},{0,0}} субинициализатор {0,0},{0,0} начинается с левой фигурной скобки, поэтому он используется для инициализации самого массива C.Тем не менее, в списке есть два предложения, в то время как имеется только один массив C, возникает ошибка.

В вашем инициализаторе {std::array<double,2>{0,0},{0,0}} субинициализатор std::array<double,2>{0,0},{0,0} не начинается с левой фигурной скобки,поэтому его можно использовать для инициализации элементов массива C, что в порядке (рекурсивно, {0,0} в порядке для инициализации std::array<double,2>, поскольку субинициализатор 0,0 не начинается с левой фигурной скобки).


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

#include <array>
std::array<std::array<double,2>,2> f() {
   return {0,0,0,0};
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...