66 votes

Comment initialiser un tableau de membres avec une liste initializer_list?

Je me familiarise avec C ++ 0x et je teste les choses avec g ++ 4.6

J'ai juste essayé le code suivant, pensant que cela fonctionnerait, mais il ne compile pas. Je reçois l'erreur:

incompatible types in assignment of ‘std::initializer_list<const int>' to ‘const int [2]'

 struct Foo
  {
    int const data[2];

    Foo(std::initializer_list<int const>& ini)
    : data(ini)
    {}
  };

Foo f = {1,3};
 

72voto

JohannesD Points 4935

Vous pouvez utiliser un constructeur de modèle variadique au lieu d'un constructeur de liste d'initialisation:

 struct foo { 
    int x[2]; 
    template <typename... T> 
    foo(T... ts) : x{ts...} { // note the use of brace-init-list
    } 
};

int main() {
    foo f1(1,2);   // OK
    foo f2{1,2};   // Also OK
    foo f3(42);    // OK; x[1] zero-initialized
    foo f4(1,2,3); // Error: too many initializers
    foo f5(3.14);  // Error: narrowing conversion not allowed
    foo f6("foo"); // Error: no conversion from const char* to int
}
 

EDIT: Si vous pouvez vivre sans constance, une autre façon serait de sauter l'initialisation et de remplir le tableau dans le corps de la fonction:

 struct foo {
    int x[2]; // or std::array<int, 2> x;
    foo(std::initializer_list<int> il) {
       std::copy(x, x+2, il.begin());
       // or std::copy(x.begin(), x.end(), il.begin());
       // or x.fill(il.begin());
    }
}
 

De cette façon, cependant, vous perdez les limites de compilation en vérifiant ce que fournit l'ancienne solution.

20voto

Potatoswatter Points 70305

Pour autant que je sache, l'utilisation de l'initialisation de liste de l'argument de fonction du constructeur (8.5.4 / 1) devrait être légale et résout de nombreux problèmes ci-dessus. Cependant, GCC 4.5.1 sur ideone.com ne correspond pas au constructeur et le rejette.

 #include <array>

struct Foo
  {
    std::array< int, 2 > const data;

    Foo(std::array<int, 2> const& ini) // parameter type specifies size = 2
    : data( ini )
    {}
  };

Foo f( {1,3} ); // list-initialize function argument per 8.5.4/1
 

Si vous insistez vraiment sur initializer_list , vous pouvez utiliser reinterpret_cast pour transformer le tableau sous-jacent du initializer_list en un tableau de style C.

 Foo(std::initializer_list<int> ini) // pass without reference- or cv-qualification
: data( reinterpret_cast< std::array< int, 2 > const & >( * ini.begin() )
 

6voto

haohaolee Points 225

Selon la discussion ici :

la bonne syntaxe pour la deuxième solution de Potatoswatter est:

 Foo f( {{1,3}} ); //two braces
 

un peu moche, pas compatible avec un usage courant

6voto

Drop Points 4965

Juste un petit ajout à la grande JohannesD réponse.

En cas de non-arguments passés à foo constructeur, le tableau sera initialisé par défaut. Mais parfois, vous voulez garder les sous-jacents de la matrice de uninitilized (peut-être pour des raisons de performances). Vous ne pouvez pas ajouter de constructeur par défaut avec variadic-basé sur un modèle un. Solution de contournement est argument supplémentaire pour variadic-basé sur un modèle constructeur, pour la distinguer de zéro argument du constructeur:

template<class T, size_t rows, size_t cols>
class array2d
{
    std::array<T, rows * cols> m_Data;
    public:

    array2d() {}

    template <typename T, typename... Types>
    array2d(T t, Types... ts) : m_Data{ { t, ts... } } {}
};

Alors, maintenant, vous pouvez brace-initilize de l'objet ou de gauche elle non initialisée:

array2d<int, 6, 8> arr = { 0, 1, 2, 3 };  // contains 0, 1, 2, 3, 0, 0, 0, ...
array2d<int, 6, 8> arr2;                  // contains garbage

2voto

Bo Persson Points 42821

Vous ne pouvez pas, les tableaux ne sont pas comme les autres types (et n'ont pas de constructeurs prenant une std :: initializer_list).

Essayez plutôt ceci:

 struct Foo  
{  
  const std::vector<int>   data;
  Foo(std::initializer_list<int>& ini) : data(ini)
  {}
}; 
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X