2015-09-17 3 views
2

J'ai un exemple simple où je crée un std::array de certains nombre d'éléments Foo:utilisateur d'appel constructeur défini sur des éléments dans std :: tableau

struct Foo 
{ 
    Foo(int bar=0) : m_bar(bar) 
    { 
     // Code depending on the value of bar 
    } 

    int m_bar; 
}; 

const unsigned int num = // get array size 
std::array<Foo, num> fooArr; 

Quand j'utiliser la liste initialiseur dans le constructeur m_bar(bar) ce jeux tous les Foo.m_bar à 0 (car il s'agit de la valeur par défaut du constructeur). Si je ne fais pas cela, alors il est plein avec des valeurs de déchets.

Ma question est comment puis-je passer une autre valeur différente de la valeur par défaut au constructeur de chaque élément dans le tableau sans connaître la taille du tableau avant la main?

J'ai essayé d'utiliser une liste init lors de la création du tableau, comme ceci: std::array<Foo, 5> fooArr{3} mais cela ne fait que définir le m_bar du premier élément à 3.

+1

Qu'en est-fooArr {{1,2,3,4,5}}? – Gombat

+0

Désolé, ce n'était pas très clair, mais je ne devrais pas connaître la taille du tableau avant la main, pour être en mesure de le faire. J'ai modifié la question en conséquence. –

+0

Dans Cppreference, il y a cet exemple: std :: array a3 = {std :: string ("a"), "b"}; Est-ce ce que vous cherchez? – Melkon

Répondre

6

Vous devez simplement construire par défaut le std::array puis utiliser sa méthode fill pour le remplir avec une valeur fixe. Beaucoup de compilateurs peuvent optimiser cela efficacement, donc vous ne paierez pas pour l'initialisation "supplémentaire".

Pour satisfaire votre cas d'utilisation, le code ressemblerait à quelque chose comme ceci:

fooArr.fill(Foo(3)); 
+2

Le problème avec cela (à moins que je ne comprenne pas ce que vous voulez dire) est que si j'ai du code dans le constructeur de Foo() qui dépend de la valeur de la taille, il obtiendra toujours 0's wont it? –

+0

Je voudrais même l'envelopper dans une fonction de commodité pour l'utiliser dans l'initialisation. – juanchopanza

+1

@ G.Rassovsky Qu'est-ce que 'size' et comment' Foo' en sait quelque chose? – juanchopanza

3

Faire une integer_sequence avec des éléments N, et construire le tableau avec une expansion pack. Ceci est plus utile si votre constructeur par défaut effectue un travail non trivial ou n'existe pas.

template<std::size_t N, class T, std::size_t... Ns> 
std::array<T, N> make_repeating_array(const T& value, std::index_sequence<Ns...>) { 
    return {(void(Ns), value)... }; 
} 

template<std::size_t N, class T> 
std::array<T, N> make_repeating_array(const T& value) { 
    return make_repeating_array<N>(value, std::make_index_sequence<N>()); 
} 

Utilisation comme

std::array<Foo, num> fooArr = make_repeating_array<num>(Foo(5)); 
+0

J'apprécie l'exemple même si je ne suis pas sûr exactement comment cela fonctionne. J'ai accepté la réponse de John Zwinck car elle est plus simple et fonctionne pour mon cas mais s'il vous plaît gardez le vôtre car je peux imaginer que cela soit plus utile dans des situations plus complexes. –

+0

À quoi sert le '(void (Ns), value)'? – xtofl

+0

@xtofl Essentiellement, il répète 'value'' sizeof ... (Ns) '(qui est' N') fois. Le ',' est l'opérateur de virgule. –