6
votes

Y a-t-il un moyen de ne pas avertir de «Compter» Enum constantes manquées de l'interrupteur dans GCC?

Si un commutateur avec un argument de type ENUM manque une partie des constantes et n'a pas de branche par défaut, l'option GCC -wswitch provoque un avertissement comme xxx

Cependant, beaucoup nos commutateurs sont comme: xxx

où le FOO_COUNT n'apparaît jamais comme valeur, mais est utilisé pour connaître le nombre de valeurs définies et peut apparaître dans la variable. Parce que nous indexerons une matrice avec la valeur enum ou l'emballage de bit et devez vérifier cela ira ou quelque chose. Ainsi, une énumération qui gère toutes les valeurs devraient pas incluez cette constante. Existe-t-il un moyen de garder cet avertissement, mais évitez-le pour de telles valeurs spéciales? C'est-à-dire xxx

devrait donner un avertissement, mais: xxx

devrait pas .


2 commentaires

Fwiw Je pense que le problème est que votre énumé est dans un état de péché. Il contient une valeur qui (puisque vous n'avez pas à le gérer dans l'interrupteur) n'est pas une valeur possible du type. C'est-à-dire que personne ne devrait jamais écrire foo f = foo_count; , mais vous leur avez donné les moyens de le faire. Je suppose que vous ne voulez pas écrire statique const int foo_count = foo_two + 1; après l'énum, ​​ou même #define foo_count (foo_two + 1) à l'intérieur de l'énum, En raison du risque que vous oublierez de le mettre à jour lorsque vous ajoutez FOO_TRORE?


Une autre option, seulement légèrement rupture de Steve's Commentaire: Ajouter FOO_LAST = FOO_TWO En énumération. Il n'ajoutera pas une nouvelle valeur dans Enum et vous éviterez l'espace de noms de préprocesseur polluant (et en C ++, foo_last sera dans l'espace de noms correct).


3 Réponses :


2
votes

Si vous savez déjà lequel de votre code> interrupteur code> s Gérer toutes les valeurs, vous pouvez ajouter le mot clé code> par défaut: code> à ceux, mais en même temps, il attrapera tout Autres valeurs qui ne figurent pas dans votre Switch-case code>, vous ne serez donc pas avertis que si vous avez oublié par exemple case foo_one: code>.

#define m_ignore_switch_case_warnings default: break
//and define it like this to enable the warnings again
#define m_ignore_switch_case_warnings

switch(value){
    case FOO_ONE:
        break;

    m_ignore_switch_case_warnings;
}


1 commentaires

Le problème de cette approche est qu'il ne fera pas avertir si vous oubliez un autre énumérateur, que Jan semble toujours vouloir être averti.



2
votes

Si vous voulez toujours avoir des avertissements pour le reste d'entre eux, la seule chose à laquelle je peux penser est de créer le cas: xxx


3 commentaires

Soit cela, ou un vide par défaut: clause. Je ne peux penser à aucune raison extrêmement évidente de préférer un sur l'autre, bien que ...


@Twalberg: la raison de préférer case foo_count: sur par défaut: est pour toujours obtenir l'avertissement lorsque vous oubliez d'inclure foo_two dans le Interrupteur (ou lorsque vous ajoutez ultérieurement foo_three sur Enum et oubliez de mettre à jour le commutateur). Par défaut: signifie "Manipuler tout", ce que nous voulons, c'est "gérer la valeur spéciale seulement".


@Stevejessop Bon point ... Je pensais plus du code généré par les deux cas, qui devrait être à peu près la même chose. N'a pas pensé à l'affaire par défaut éventuellement obscurcir des avertissements supplémentaires.



3
votes

Je préfère personnellement une autre approche: générer le Enum code> via une macro pour configurer le compte.

enum foo {
    FOO_ONE,
    FOO_TWO
};

inline size_t size(enum foo) { return 2; }


2 commentaires

Quelle syntaxe de macro utilisez-vous pour compter automatiquement le nombre d'entrées de valeurs ENUM dans votre macro Generate_Enum ()?


@RYRYEAGER: J'utilise la bibliothèque de préprocesseur Boost et plus spécifiquement le boost_pp_seq_size macro qui se développe à la taille de la séquence.