Я пытаюсь инициализировать объекты типа вещь:
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 }};
и несколько других вещей.
Если вы используете компилятор 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
,
От §11.6.1 / 1 [dcl.init.aggr]
совокупный это массив или класс с
(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}} }};