Les extra-accolades est nécessaire parce que l' std::array
est un agrégat et la GOUSSE d', contrairement à d'autres conteneurs de la bibliothèque standard. std::array
n'ont pas défini par l'utilisateur constructeur. C'est le premier membre de données est un tableau de taille N
(ce qui vous passe comme argument de modèle), et ce membre est directement initialisé avec l'initialiseur. Les extra-accolades est nécessaire à l' intérieur de la matrice de ce qui est directement en cours d'initialisation.
La situation est identique:
//define this aggregate - no user-defined constructor
struct Aarray
{
A data[2]; //data is an internal array!
};
Comment initialiser ce? Si vous faites cela:
Aarray a1 =
{
{0, 0.1},
{2, 3.4}
};
il donne d'erreur de compilation:
erreur: trop de initialiseurs pour "Aarray'
C'est la même erreur que vous obtenez dans le cas d' std::array
également (si vous utilisez GCC)!
Donc la bonne façon est d'utiliser des accolades comme:
Aarray a1 =
{
{ //<--this tells the compiler that initialization of `data` starts!
{ //<-- initialization of `data[0]` starts!
0, 0.1
}, //<-- initialization of `data[0]` ends
{2, 3.4} //initialization of data[1] starts and ends, as above!
} //<--this tells the compiler that initialization of `data` ends!
};
qui compile amende. Une fois de plus l'extra-accolades est nécessaire parce que vous êtes à l'initialisation de l' intérieur de la matrice.
--
Maintenant, la question est, pourquoi supplémentaire accolades ne sont pas nécessaires dans le cas d' double
?
C'est parce qu' double
n'est pas un agrégat, tout en A
est. En d'autres termes, std::array<double, 2>
est un agrégat de total, alors que std::array<A, 2>
est un agrégé de agrégé de agrégé1.
1. Je pense que les extra-accolades est toujours nécessaire en cas de double aussi (comme cela), pour être complètement le Standard conforme, mais il fonctionne sans elle. Il semble que j'ai besoin de creuser la spec de nouveau!.
Plus sur les accolades et extra accolades
Je creuse la spec. Cette section (§8.5.1/11 à partir de C++11) est intéressant et s'applique à la présente affaire:
Dans une déclaration de la forme
T x = { a };
les accolades peuvent être gommés dans un initialiseur-liste comme suit. Si l'initialiseur-liste commence par une accolade gauche, puis le suivant liste séparée par des virgules de initialiseur-clauses initialise les membres d'une subaggregate; il est erroné pour qu'il y ait plus d'initialiseur-clauses de membres. Si, toutefois, l'initialiseur de liste pour un subaggregate
ne commence pas par une accolade gauche, puis seulement assez d'initialiseur-les clauses de la liste sont prises pour initialiser les membres de la subaggregate; tout solde de l'initialiseur-des clauses de gauche pour initialiser le prochain membre de la somme dont l'actuel subaggregate est membre. [ Exemple:
float y[4][3] = {
{ 1, 3, 5 },
{ 2, 4, 6 },
{ 3, 5, 7 },
};
est complètement contreventées l'initialisation: 1, 3, et 5 initialiser la première ligne du tableau y[0]
, à savoir l' y[0][0]
, y[0][1]
, et y[0][2]
. De même, les deux lignes suivantes initialiser y[1]
et y[2]
. L'initialisation se termine tôt et, par conséquent, y[3]s
des éléments sont initialisés comme si explicitement initialisée avec une expression de la forme float(), qui est initialisé avec 0.0. Dans l'exemple suivant, les accolades dans l'initialiseur-liste sont gommés; cependant l'initialiseur-liste a le même effet que l'complètement contreventées initialiseur-liste de l'exemple ci-dessus,
float y[4][3] = {
1, 3, 5, 2, 4, 6, 3, 5, 7
};
L'initialiseur, pour y commence par une accolade gauche, mais l'un pour l' y[0]
n'a donc pas les trois éléments de la liste sont utilisés. De même, les trois sont pris successivement pour y[1]
et y[2]
. fin de l'exemple ]
Basé sur ce que j'ai compris de la citation ci-dessus, je peux dire que les éléments suivants devraient être autorisés:
//OKAY. Braces are completely elided for the inner-aggregate!
std::array<A, 2> X =
{
0, 0.1,
2, 3.4
};
//OKAY. Completely-braced initialization!
std::array<A, 2> Y =
{{
{0, 0.1},
{2, 3.4}
}};
Dans le premier des accolades à l'intérieur-l'ensemble sont totalement gommés, tandis que le second est complètement contreventées d'initialisation. Dans votre cas (le cas de l' double
), l'initialisation utilise la première approche (accolades sont totalement gommés pour l'agrégat interne!).
Mais ce doit être rejetée:
//ILL-FORMED : it is neither!
std::array<A, 2> Z =
{
{0, 0.1},
{2, 3.4}
};
Il est ni bretelles-élidés, il n'existe pas suffisamment d'appareils pour être complètement contreventées d'initialisation. Par conséquent, il est mal formé!