2014-07-25 3 views
5

Я пытаюсь инициализировать объекты типа вещи:Как инициализировать объект 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}}}; 

Ditto с

thing<int> t0{{ 1, 2, 3, 4 }}; 

и несколько других вещей.

+3

Почему вы привязываетесь к наследованию от 2D-массива? – rashmatash

+2

Если вы пытаетесь создать псевдоним массива, вам лучше сделать 'template using thing = std :: array , 2>;' – Quentin

ответ

9

Если вы используете компилятор C++ 17, вам не хватает дополнительного набора фигурных скобок. Следующий compiles:

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 modified правила для агрегатов, чтобы обеспечить базовые классы, до тех пор, пока они public и не- virtual.

От §11.6.1/1 [dcl.init.aggr]

совокупности представляет собой массив или класс с
(1.1) нет пользователем при условии, explicit или наследоваться конструкторы ([class.ctor]),
(1.2) нет частных или защищенных нестатических элементов данных ([класс.access]),
(1.3) нет виртуальных функций, и
(1.4) нет виртуальных, закрытых или защищенных базовых классов ([class.mi]).

Базовые классы теперь считаются elements of the aggregate, и сами по себе могут быть инициализированы с помощью списка инициализацию,

В элементах из агрегата являются:
(2.1) для множества, элементы массива в порядке возрастания индекса, или
(2.2) для класса классов прямых базовых в декларации порядок, за которым следуют прямые нестатические члены данных ([class.mem]), которые не являются членами анонимного объединения, в порядке объявления.


C++ 14, а ранее, вариант ответа следующим образом:

std::array представляет собой агрегат, и инициализация выполняется с помощью рамно-Init-списка является совокупной инициализация. Однако thing не является агрегатом, потому что он имеет базовый класс.

От §8.5.1/1 [dcl.init.Aggr]

An агрегатного представляет собой массив или класс (пункт 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}} }}; 
Смежные вопросы