Se si utilizza un compilatore C++ 17, mancherà solo un set aggiuntivo di parentesi graffe. Il seguente 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 le regole per aggregati per consentire classi di base, purché siano public
e non virtual
.
Da §11.6.1/1 [dcl.init.aggr]
Un aggregato è un array o una classe con
(1.1) senza costruttori forniti dall'utente, explicit
, o ereditato ([class.ctor]),
(1.2) nessun membro di dati non statici privato o protetto ([class.access]),
(1.3) senza funzioni virtuali e
(1.4) nessuna classe di base virtuale, privata o protetta ([class.mi]).
Le classi base sono ora considerati elements of the aggregate, e possono a loro volta essere inizializzate con lista-inizializzazione.
Gli elementi di un aggregato sono:
(2.1) per un array, gli elementi della matrice in ordine crescente pedice o
(2.2) per una classe, le classi base dirette in dichiarazione ordine, seguito dai membri diretti non statici dei dati ([class.mem]) che non sono membri di un'unione anonima, in ordine di dichiarazione.
C++ 14, e precedenti, la versione della risposta segue:
std::array
è un aggregato, e l'inizializzazione fatto utilizzando un-init-list rinforzato è aggregata inizializzazione. Tuttavia, thing
non è un aggregato perché ha una classe base.
Da §8.5.1/1 [dcl.init.aggr]
Un aggregato è un array o una classe (Clausola 9) senza costruttori forniti dall'utente (12.1), senza componenti di dati privati o protetti non statico (par 11), nessuna base classi (articolo 10) e nessuna funzione virtuale (10.3).
Pertanto, l'inizializzazione di aggregazione non funzionerà. A seconda di cosa si sta cercando di fare, sia desidera fornire un costruttore per thing
che prende un argomento std::array<std::array<T, 2>, 2>
, e inizializzare il sotto-oggetto base di
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}} }} };
O avere thing
contengono la std::array
come un membro di dati. Ora thing
è ancora un aggregato.
template<typename T>
struct thing
{
std::array<std::array<T, 2>, 2> arr;
};
thing<int> t{ {{ {{1,2}}, {{3,4}} }} };
Se state cercando di fare è di avere thing
essere un alias per un array<array<T,2>,2>
, allora non hai bisogno né di quanto sopra. Usa
template<typename T>
using thing = std::array<std::array<T, 2>, 2>;
thing<int> t{{ {{1,2}}, {{3,4}} }};
perché stai legando per ereditare da un array 2D? – rashmatash
Se si sta tentando di creare un alias dell'array, è meglio fare 'template usando thing = std :: array , 2>;' –
Quentin