Как мне инициализировать объект std:: array<std:: array <T, 2>, 2>?
Я пытаюсь инициализировать объекты типа вещь:
template<typename T>
struct thing : std::array<std::array<T, 2>, 2>
{
};
thing<int> t1 {{ {1,2}, {3,4} }};
Я получил:
error: no matching function for call to ‘thing<int>::thing(<brace-enclosed initializer list>)’
thing<int> t1 {{{1,2},{3,4}}};
То же самое с
thing<int> t0{{ 1, 2, 3, 4 }};
и несколько других вещей.
1 ответ
Если вы используете компилятор C++17, вам не хватает только дополнительного набора скобок. Следующие компиляции:
thing<int> t1 { { { {1,2}, {3,4} } } };
// | | | |- braces for inner array
// | | |--- braces for outer array
// | |----- braces for base sub object of thing
// |------- braces for list initialization of thing
C++17 изменил правила для агрегатов, чтобы разрешить базовые классы, если они public
и неvirtual
,
Агрегат - это массив или класс с
(1.1) не предоставлено пользователем,explicit
или унаследованные конструкторы ([class.ctor]),
(1.2) нет личных или защищенных нестатических элементов данных ([class.access]),
(1.3) нет виртуальных функций, и
(1.4) нет виртуальных, частных или защищенных базовых классов ([class.mi]).
Базовые классы теперь считаются элементами агрегата и могут сами инициализироваться с помощью инициализации списка.
Элементы совокупности:
(2.1) для массива, элементы массива в порядке возрастания индекса или
(2.2) для класса - прямые базовые классы в порядке объявления, за которыми следуют прямые нестатические члены данных ([class.mem]), которые не являются членами анонимного объединения, в порядке объявления.
C++ 14 и более ранняя версия ответа следующие:
std::array
является агрегатом, а инициализация, выполненная с использованием списка в скобках, является инициализацией агрегата. Тем не мение, thing
не является агрегатом, поскольку имеет базовый класс.
Из §8.5.1/1 [dcl.init.aggr]
Агрегат - это массив или класс (раздел 9) без предоставленных пользователем конструкторов (12.1), без закрытых или защищенных нестатических элементов данных (пункт 11), без базовых классов (пункт 10) и без виртуальных функций (10.3).
Таким образом, агрегатная инициализация не будет работать. В зависимости от того, что вы пытаетесь сделать, вы либо хотите предоставить конструктор для thing
это занимает std::array<std::array<T, 2>, 2>
аргумент и инициализировать базовый подобъект
template<typename T>
struct thing : std::array<std::array<T, 2>, 2>
{
thing(std::array<std::array<T, 2>, 2> arr)
: std::array<std::array<T, 2>, 2>(arr)
{}
};
thing<int> t{ {{ {{1,2}}, {{3,4}} }} };
Или есть thing
содержать std::array
в качестве члена данных. Сейчас thing
все еще совокупность.
template<typename T>
struct thing
{
std::array<std::array<T, 2>, 2> arr;
};
thing<int> t{ {{ {{1,2}}, {{3,4}} }} };
Если то, что вы пытаетесь сделать, это иметь thing
быть псевдонимом для array<array<T,2>,2>
, тогда вам не нужно ничего из вышеперечисленного. использование
template<typename T>
using thing = std::array<std::array<T, 2>, 2>;
thing<int> t{{ {{1,2}}, {{3,4}} }};