Dupliquer possible:
Comment initialiser un tableau de membres avec une liste d’initialisation?
Vous pouvez construire un std :: array avec une liste d’initialisation:
std::array a = {1, 2, 3}; // works fine
Cependant, lorsque j’essaie de le construire à partir de std::initializer_list
tant que membre de données ou object de base dans une classe, cela ne fonctionne pas:
#include #include template struct enum_addressable_array : public std::array { typedef std::array base_t; typedef typename base_t::reference reference; typedef typename base_t::const_reference const_reference; typedef typename base_t::size_type size_type; enum_addressable_array(std::initializer_list il) : base_t{il} {} reference operator[](EnumT n) { return base_t::operator[](static_cast(n)); } const_reference operator[](EnumT n) const { return base_t::operator[](static_cast(n)); } }; enum class E {a, b, c}; enum_addressable_array ea = {'a', 'b', 'c'};
Erreurs avec gcc 4.6:
test.cpp: In constructor 'enum_addressable_array::enum_addressable_array(std::initializer_list) [with T = char, unsigned int size = 3u, EnumT = E]': test.cpp:26:55: instantiated from here test.cpp:12:68: error: no matching function for call to 'std::array::array()' test.cpp:12:68: note: candidates are: include/c++/4.6.1/array:60:12: note: std::array::array() include/c++/4.6.1/array:60:12: note: candidate expects 0 arguments, 1 provided include/c++/4.6.1/array:60:12: note: constexpr std::array::array(const std::array&) include/c++/4.6.1/array:60:12: note: no known conversion for argument 1 from 'std::initializer_list' to 'const std::array&' include/c++/4.6.1/array:60:12: note: constexpr std::array::array(std::array&&) include/c++/4.6.1/array:60:12: note: no known conversion for argument 1 from 'std::initializer_list' to 'std::array&&'
Comment puis-je le faire fonctionner afin que ma classe de wrapper puisse être initialisée avec une liste d’initialisation, en tant que telle:
enum_addressable_array ea = {'a', 'b', 'c'};
Un std::array<>
ne possède aucun constructeur prenant un std::initializer_list<>
(constructeur de la liste d’initialisation) et il n’y a pas de support de langage particulier pour ce que cela peut vouloir dire de passer un constructeur de classe à une classe tel que cela peut fonctionner. Donc ça échoue.
Pour que cela fonctionne, votre classe dérivée doit attraper tous les éléments, puis les transmettre, un modèle de constructeur:
template enum_addressable_array(E&&...e) : base_t{{std::forward(e)...}} {}
Notez que vous avez besoin de {{...}}
dans ce cas parce que l’élision d’accolades (en omettant les accolades comme dans votre cas) ne fonctionne pas à cet endroit. Cela n’est autorisé que dans les déclarations de la forme T t = { ... }
. Comme std::array<>
consiste en une structure incorporant un tableau brut, il faudra deux niveaux d’accolades. Malheureusement, je pense que la structure globale exacte de std::array<>
n’est pas spécifiée. Vous devrez donc espérer que cela fonctionnera avec la plupart des implémentations.
Dans la mesure où std::array
est une structure contenant un agrégat (il ne s’agit pas d’un agrégat lui-même ni de constructeur prenant un std::initializer_list
), vous pouvez initialiser l’agrégat sous-jacent à l’intérieur de la structure avec une liste d’initialisation à l’aide de une syntaxe à doubles accolades comme celle-ci:
std::array my_array = {{1, 2, 3, 4}};
Notez que ceci n’utilise pas std::initializer_list
… c’est simplement utiliser une liste d’initialisation C ++ pour initialiser le membre de tableau accessible au public de std::array
.
Un std::array
n’a pas de constructeur qui prend un std::initializer_list
. C’est une bonne chose, car les listes d’initialiseurs peuvent être plus grandes que la taille fixe du tableau.
Vous pouvez l’initialiser en testant que la liste d’initialisation n’est pas plus grande que la taille du tableau, puis en copiant les éléments de la liste d’initialisation dans le membre elems
de std::array
avec std::copy
.