Как мне инициализировать объект 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,

Из §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}} }};
Другие вопросы по тегам