2010-09-07 24 views
2

J'utilise un initialiseur agrégé pour configurer un bloc de données statiques pour un test unitaire.Puis-je provoquer une erreur de compilation sur "trop ​​peu d'initialiseurs"?

Je voudrais utiliser la taille du tableau que le nombre prévu d'éléments, mais cela peut échouer si trop peu initialiseurs sont fournis:

my_struct_type expected[14] = 
{ 
    { 1.234, 0, 'c' }, 
    { 3.141, 1, 'z' }, 
    { 2.718, 0, 'a' } 
}; 

Cela donne aucune erreur du compilateur dans Visual Studio 2008.

Je voudrais pouvoir l'utiliser comme tel:

const unsigned expected_size = sizeof(expected)/sizeof(my_struct_type); 

BOOST_CHECK_EQUAL(points.size(), expected_size); 

for(int i = 0; i < expected_size; i++) 
{ 
    BOOST_CHECK_EQUAL(points[i].value, expected[i].value); 
    BOOST_CHECK_EQUAL(points[i].count, expected[i].count); 
    BOOST_CHECK_EQUAL(points[i].sym, expected[i].sym); 
} 

mais parce que je n'ai pas une garantie de compilation de 14 points, ce ruisseler le e nd du tableau fin des valeurs fournies et dans les valeurs initialisées par défaut. Puis-je d'une certaine manière appliquer le nombre d'initialiseurs de tableaux agrégés au moment de la compilation?

Répondre

4

Premièrement: Il pourrait y avoir un avertissement pour cela. Avez-vous essayé de compiler au plus haut niveau d'alerte?

Puis: Si vous échangez dont la valeur est calculée et qui est littéral, vous pourriez soulever une erreur de compilation:

my_struct_type my_array[] = // <== note the empty [] 
{ 
    { 1.234, 0, 'c' }, 
    { 3.141, 1, 'z' }, 
    { 2.718, 0, 'a' } 
}; 

BOOST_STATIC_ASSERT(sizeof(my_array)/sizeof(my_array[0]) == 14); 
+0

J'ai aimé @ réponse de Potatoswatter pour sa nouveauté, mais le vôtre est le plus pragmatique et applicable sans toucher à mes structures existantes. – mskfisher

0

Selon le msdn, si moins d'initialiseurs sont spécifiés, les éléments restants sont initialisés avec 0, donc le code devrait néanmoins fonctionner.

+0

Certes, il va compiler, mais il n'aura pas la sémantique que je recherche. – mskfisher

5

En fait, il ne fonctionnera pas à l'extrémité du tableau, car le compilateur initialise par défaut tous les éléments du tableau que vous n'avez pas initialisés vous-même.

Si vous essayez de vous assurer que vous avez un nombre spécifique d'initialiseurs configurés, je ne sais pas comment faire.

Si vous voulez juste vous assurer que le tableau est le nombre d'articles que vous avez:

my_struct_type expected[] = 
{ 
    { 1.234, 0, 'c' }, 
    { 3.141, 1, 'z' }, 
    { 2.718, 0, 'a' } 
}; 

fera l'affaire. Ensuite, utilisez simplement sizeof(expected)/sizeof(expected[0]) pour obtenir le nombre total d'éléments de tableau.

+2

Pas d'initialisation zéro, mais utiliser l'initialiseur par défaut. –

+0

@Vlad: Je viens de voir ta réponse.Je me souviens d'avoir demandé une initialisation zéro, mais je suppose que non. Donc, si vous avez vu mon autre commentaire, ça ne bouge pas :) –

+1

@Vlad Lazarenko: Eh bien, selon la dernière spécification C++, les éléments restants seront soumis à * value-initialization *. En fait, il n'y a pas de "default * initializer *" en C++. Il y a * default-initialization *, mais c'est ce qui arriverait en C++ 98. En C++ 03 cependant * l'initialisation de valeur * a lieu. – AnT

1

Juste pour l'amour d'une réponse non-Boost ...

Vous pouvez ajouter une condition d'initialisation en modifiant my_struct_type.

template< typename T > 
struct must_be_initialized { 
    T value; 

    must_be_initialized(T const &v) : value(v) {} 
    // no default constructor! 

    operator T&() { return value; } 
    operator T const&() const { return value; } 
}; 

struct my_struct_type { 
    must_be_initialized<double> f; 
    int i; 
    char c; 
}; 

my_struct_type expected[14] = 
{ 
    { 1.234, 0, 'c' }, 
    { 3.141, 1, 'z' }, 
    { 2.718, 0, 'a' } 
    // error: no default constructor exists 
}; 

my_struct_type est encore un agrégat, mais ce n'est pas POD.

+0

Intéressant. Il semble également que l'initialisation uniforme de C++ 0x permettrait à un constructeur par défaut privé d'accomplir cela. http://en.wikipedia.org/wiki/C%2B%2B0x#Uniform_initialization – mskfisher

+0

@msk: ou un constructeur par défaut supprimé. – Potatoswatter

+0

Encore mieux, pas de spécificateurs d'accès inutiles. – mskfisher

1

ISO/CEI 14882 (Première édition 1998-09-01) dans p. 8.5.1.7 stipule ce qui suit:

If there are fewer initializers in the list than there are members in the aggregate, then each member not explicitly initialized shall be default-initialized (8.5). [Example: struct S { int a; char* b; int c; }; S ss = { 1, "asdf" }; initializes ss.a with 1, ss.b with "asdf", and ss.c with the value of an expression of the form int(), that is, 0. ]

Simplement, la réponse à votre question est non.