Ответ 1
Необходимы дополнительные фигурные скобки, поскольку std::array
- это совокупность и POD, в отличие от других контейнеров в стандартной библиотеке. std::array
не имеет определяемого пользователем конструктора. Его первым элементом данных является массив размером N
(который вы передаете как аргумент шаблона), и этот элемент инициализируется инициализатором. Дополнительные привязки необходимы для внутреннего массива, который непосредственно инициализируется.
Ситуация такая же, как:
//define this aggregate - no user-defined constructor
struct Aarray
{
A data[2]; //data is an internal array
};
Как бы вы инициализировали это? Если вы это сделаете:
Aarray a1 =
{
{0, 0.1},
{2, 3.4}
};
он дает ошибку компиляции:
ошибка: слишком много инициализаторов для "Aarray"
Это та же ошибка, которую вы получаете в случае std::array
(если вы используете GCC).
Итак, правильная вещь - использовать фигурные скобки следующим образом:
Aarray a1 =
{
{ //<--this tells the compiler that initialization of `data` starts
{ //<-- initialization of `data[0]` starts
0, 0.1
}, //<-- initialization of `data[0]` ends
{2, 3.4} //initialization of data[1] starts and ends, as above
} //<--this tells the compiler that initialization of `data` ends
};
который компилируется отлично. Еще раз, дополнительные скобки необходимы, потому что вы инициализируете внутренний массив.
-
Теперь возникает вопрос, почему дополнительные привязки не нужны в случае double
?
Это потому, что double
не является агрегатом, а A
-. Другими словами, std::array<double, 2>
представляет собой совокупность агрегата, а std::array<A, 2>
- совокупность совокупности агрегата 1.
1. Я думаю, что дополнительные привязки по-прежнему необходимы и в случае двойного (например, this), чтобы полностью соответствовать стандарту, но код работает без них. Кажется, мне нужно снова проскочить в спецификации!. Забастовкa >
Подробнее о фигурных скобках и дополнительных фигурных скобках
Я вырыл спецификацию. Этот раздел (§8.5.1/11 из С++ 11) интересен и применим к этому случаю:
В объявлении формы
T x = { a };
скобки можно удалить в списке инициализаторов следующим образом. Если список инициализаторов начинается с левой фигурной скобки, то последующий разделенный запятыми список инициализатор-предложений инициализирует элементы субагрегата; ошибочно, чтобы было больше предложений инициализатора, чем членов. Если, однако, список инициализаторов для суммирования не начинается с левой скобки, тогда для инициализации членов субагрегата принимаются только достаточные инициализационные предложения из списка; любые оставшиеся условия инициализации оставляются для инициализации следующего члена агрегата, членом которого является текущий субагрегат. [Пример:
float y[4][3] = {
{ 1, 3, 5 },
{ 2, 4, 6 },
{ 3, 5, 7 },
};
является полностью фиксированной инициализацией: 1, 3 и 5 инициализируют первую строку массива
y[0]
, а именноy[0][0]
,y[0][1]
иy[0][2]
. Аналогично, следующие две строки инициализируютy[1]
иy[2]
. Инициализатор заканчивается раньше, и поэтому элементыy[3]s
инициализируются так, как если бы они были явно инициализированы выражением формы float(), то есть инициализированы с помощью 0.0. В следующем примере скобки в списке инициализаторов устранены; однако список инициализаторов имеет тот же эффект, что и полностью скопированный список инициализаторов вышеприведенного примера,
float y[4][3] = {
1, 3, 5, 2, 4, 6, 3, 5, 7
};
Инициализатор для y начинается с левой скобки, но для
y[0]
нет, поэтому используются три элемента из списка. Аналогично, следующие три последовательно выполняются дляy[1]
иy[2]
. -end пример]
Основываясь на том, что я понял из приведенной выше цитаты, могу сказать, что должно быть разрешено следующее:
//OKAY. Braces are completely elided for the inner-aggregate
std::array<A, 2> X =
{
0, 0.1,
2, 3.4
};
//OKAY. Completely-braced initialization
std::array<A, 2> Y =
{{
{0, 0.1},
{2, 3.4}
}};
В первом, скобки для внутреннего агрегата полностью исключены, а вторая имеет полностью фиксированную инициализацию. В вашем случае (в случае double
) инициализация использует первый подход (скобки полностью устранены для внутреннего агрегата).
Но это должно быть запрещено:
//ILL-FORMED : neither braces-elided, nor fully-braced
std::array<A, 2> Z =
{
{0, 0.1},
{2, 3.4}
};
Он не имеет ни фигур, ни скобок, и нет достаточного количества фигурных скобок для полной фиксации. Поэтому он плохо сформирован.