Détecter si la conversion d'un int en enum entraîne une valeur non énumérée
Disons que j'ai quelque chose comme ceci :
enum CardColor { HEARTS, DIAMONDS, CLUBS, SPADES};
CardColor MyColor = static_cast<CardColor>(100);
Est-il un (simple) de façon à détecter, soit au moment de la compilation ou à l'exécution, que la valeur de MyColor
ne correspond à aucune valeur énumérée ?
Et plus généralement, si les valeurs enum ne sont pas à la suite les uns des autres, par exemple :
enum CardColor { HEARTS = 0, DIAMONDS, CLUBS = 4, SPADES};
source d'informationauteur Jérôme
Vous devez vous connecter pour publier un commentaire.
CashCow présente un décent répondre à cette question: c'est certainement simple à écrire une fonction personnalisée d'effectuer un contrôle de fonte.
Malheureusement, c'est aussi beaucoup de travail et vous devez vous assurer de le garder synchronisés avec l'énumération de sorte que la liste des agents recenseurs dans l'énumération définition est la même que la liste des agents recenseurs dans les bagages fonction de distribution. Vous devez également écrire un de ces pour chaque énumération à laquelle vous souhaitez être en mesure d'effectuer un contrôle de fonte.
Plutôt que de faire tout ce travail manuel, nous pouvons automatiser la génération de l'ensemble de ce code en utilisant le préprocesseur (avec un peu d'aide de l'augmentation de Préprocesseur de la bibliothèque). Voici une macro qui génère une énumération définition avec une
checked_enum_cast
fonction. C'est sans doute un peu effrayant à la recherche (génération de code macros sont souvent horrible à regarder), mais il est extrêmement utile de se familiariser avec.Voici comment vous pouvez l'utiliser avec votre
CardColor
exemple:La première ligne remplace votre
enum CardColor ...
définition; il définit l'énumération et offre une spécialisation qui vous permet d'utiliserchecked_enum_cast
de jeter des entiersCardColor
.Cela peut ressembler à beaucoup de tracas juste pour obtenir un activée fonction de distribution pour votre enums, mais cette technique est très utile et très extensible. Vous pouvez ajouter des fonctions que de faire toutes sortes de choses. Par exemple, j'en ai un qui génère les fonctions de convertir les types énumérés et de la chaîne des représentations et des fonctions qui effectuent plusieurs autres conversions et vérifie que j'utilise pour la plupart de mes énumérations.
Rappelez-vous, vous avez à écrire et déboguer des gros, laid macro une fois seulement, puis vous pouvez l'utiliser partout.
La plus simple solution d'exécution serait de ne pas utiliser static_cast mais l'utilisation d'une fonction qui fait le vérifier pour vous. Si vous mettez votre enum à l'intérieur d'une classe, vous pouvez le faire à travers la classe.
Quelque chose comme:
clang du support de la dynamique de dépassement des contrôles. Voir -fsanitize=enum commutateur. Un programme compilé avec ce commutateur de signal enum affectation des erreurs grâce à l'stderr de sortie. Cela vous permettra de faire des tests de débogage. Il n'est pas adapté pour tester suspect entrée officielle à construire.
Il est courant d'avoir un élément supplémentaire à la fin de l'énumération indiquant le nombre d'éléments qu'il contient. Vous pouvez utiliser cette valeur pour vérifier au moment de l'exécution si la valeur est valide:
Au début - c'est une mauvaise idée de faire cela.
Mais si vous voulez, je vous suggère de coder en dur entier les valeurs de l'énumération:
Puis la surcharge de l'affectation de l'opérateur:
Valeurs d'énumération peuvent se chevaucher ou ont des trous; aussi, les variables réelles peuvent être attribués à zéro, toute la valeur de l'ensemble ou de l'or au niveau du bit OU de valeurs autorisées. Donc:
permet les valeurs 0, 1, 2, 3;
permet à n'importe quelle valeur de 0 à 15.
Si vous utilisez un enum pour définir les valeurs des bits, il est généralement une bonne idée de définir (binaire)
operator&
operator|
operator&=
etoperator|=
. Si vous ne le faites pas, vous aurez besoin d'un cast explicite à chaque fois qu'une valeur qui n'est pas dans le jeu est généré, de sorte que les endroits où cela se passe peut être facilement repéré.Il y a des compilateurs qui peuvent avertir si un nombre en dehors de la plage autorisée, ou si non aucun, de la première ou de tous les noms ont des initialiseurs attaché à eux (c'est une violation de MISRA-C règles).