2014-07-25 13 views
5

Ich versuche, Objekte vom Typ Sache zu initialisieren:Wie initialisiere ich ein Objekt von 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} }}; 

ich:

error: no matching function for call to ‘thing<int>::thing(<brace-enclosed initializer list>)’ 
thing<int> t1 {{{1,2},{3,4}}}; 

Ditto mit

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

und einige andere Dinge.

+3

Warum binden Sie, um von einem 2D-Array zu erben? – rashmatash

+2

Wenn Sie versuchen, das Array zu aliasieren, sollten Sie besser 'template mit thing = std :: array , 2>; ' – Quentin

Antwort

9

Wenn Sie einen C++ 17-Compiler verwenden, fehlt nur eine zusätzliche Reihe von geschweiften Klammern. Die folgenden 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 die Regeln für die Aggregate Basisklassen zu ermöglichen, so lange wie sie sind public und nicht virtual.

Von §11.6.1/1 [dcl.init.aggr]

Ein Aggregat ist ein Array oder eine Klasse mit
(1.1) keine vom Benutzer bereitgestellte, explicit oder ererbten Konstruktoren ([class.ctor]),
(1.2) keine privaten oder geschützten nicht statischen Datenelemente ([class.access]),
(1.3) keine virtuellen Funktionen und
(1.4) keine virtuellen, privaten oder geschützten Basisklassen ([class.mi]).

Die Basisklassen werden nun elements of the aggregate, betrachtet und können sich list-Initialisierung mit initialisiert.

Die Elemente ein Aggregat sind:
(2.1) für einen Array, die Array-Elemente in aufsteige Subskript Reihenfolge oder
(2.2) für eine Klasse, die direkten Basisklassen in der Erklärung Reihenfolge, gefolgt von den direkten nicht statischen Datenmembern ([class.mem]), die nicht Mitglieder einer anonymen Union sind, in der Reihenfolge der Deklaration.


C++ 14 und früher, Version der Antwort folgt:

std::array ein Aggregat ist, und die Initialisierung einer verspannt-init-Liste erfolgt mit Hilfe ist Aggregat Initialisierung. thing ist jedoch kein Aggregat, da es eine Basisklasse hat.

Von §8.5.1/1 [dcl.init.aggr]

Ein Aggregat ist ein Array oder eine Klasse (Abschnitt 9) ohne Benutzer bereitgestellten Konstruktoren (12.1), keine privaten oder geschützte nicht-statische Datenelemente (Ziffer 11), keine Basis Klassen (Abschnitt 10) und keine virtuellen Funktionen (10.3).

So Aggregat Initialisierung wird nicht funktionieren. Je nachdem, was du versucht, Sie zu tun, entweder Sie einen Konstruktor für thing zur Verfügung zu stellen, die ein std::array<std::array<T, 2>, 2> Argument, und initialisieren die Basis subobject

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}} }} }; 

Oder haben thing die std::array als Datenelement enthalten. Jetzt ist thing noch ein Aggregat.

template<typename T> 
struct thing 
{ 
    std::array<std::array<T, 2>, 2> arr; 
}; 
thing<int> t{ {{ {{1,2}}, {{3,4}} }} }; 

Wenn ein Alias ​​für eine array<array<T,2>,2> zu tun, was Sie versuchen, haben thing sein, so ist entweder der oben genannten Sie nicht brauchen. Verwenden Sie

template<typename T> 
using thing = std::array<std::array<T, 2>, 2>; 

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