Comment convertir int en énumération en C ++?

222

Comment convertir un int en une énumération en C ++?

Par exemple:

enum Test
{
    A, B
};

int a = 1;

Comment convertir aen type Test::A?

user1509260
la source
1
link Notez que peu importe si l'int correspond à l'une des constantes du type enum; la conversion de type est toujours illégale.
Iwaz
3
Je crois que si vous voulez transtyper en Test :: A la valeur de int adevra être 0, parce que Test :: A a une valeur implicite de 0 et Test :: B a une valeur implicite de 1. Sauf si le fait de lancer spécifiquement à Test :: A est d'ailleurs le point ...
JohnRDOrazio

Réponses:

243
int i = 1;
Test val = static_cast<Test>(i);
Andrew
la source
21
auto val = static_cast <Test> (i); // C ++ 11
Mitch
3
@Mitch qu'est-ce que j'obtiens pour utiliser autodans ce cas? Y a-t-il des améliorations de performances?
Frederico Pantuzza
2
Aucune amélioration des performances. Le compilateur déduit simplement le type automatiquement si vous spécifiez avec "auto". Si vous décidez de changer votre nom enum à l'avenir, vous modifierez moins votre code car le compilateur déduira automatiquement le nom de type correct.
Aydin Özcan
74
Test e = static_cast<Test>(1);
bames53
la source
10
MSDN: l'opérateur static_cast peut convertir explicitement une valeur intégrale en type d'énumération. Si la valeur du type intégral ne fait pas partie de la plage de valeurs d'énumération, la valeur d'énumération résultante n'est pas définie.
Kirill Kobelev
1
@KirillKobelev si la valeur intégrale peut être représentée par le type sous-jacent de l'énumération, l'énumération résultante doit avoir cette valeur. Sinon, la valeur d'énumération produite sera la valeur résultant de la conversion de l'expression au type sous-jacent de l'énumération. Si VC ++ fait quelque chose de différent, je pense que ce n'est pas conforme.
bames53
2
que doit faire un compilateur conforme, si enum a des valeurs {1,3,5} et que le code tente de faire <static_cast> à partir de la valeur de 2. En quoi cela diffère-t-il de la distribution C?
Kirill Kobelev
6
@KirillKobelev Je n'utilise pas un static_cast car il fait quelque chose de différent d'un cast de style C, j'utilise static_cast parce que les castings C ++ sont stylistiquement préférables aux castes C.
bames53
4
@KirillKobelev " si l'énumération a des valeurs {1,3,5} " Non. Le type d' énumération ne peut pas être limité à seulement ces 3 valeurs possibles: {1,3,5} sont les énumérateurs (valeurs d'énumération nommées), pas l'énumération elle-même . Si 1,3,5 sont des valeurs d' énumération possibles , alors il en est de même de 2.
curiousguy
25

Votre code

enum Test
{
    A, B
}

int a = 1;

Solution

Test castEnum = static_cast<Test>(a);
user1515687
la source
45
C'est une bonne idée d'utiliser la distribution la plus restrictive possible, et d'éviter complètement les conversions de style C, pour donner au compilateur ses meilleures chances de détecter les erreurs. static_castserait un meilleur casting ici.
Mike Seymour
4
@Mike Seymour, le problème est que la distribution statique n'a pas de différence avec la distribution C dans ce cas. Comment et quelle erreur il peut détecter ???
Kirill Kobelev
7
@KirillKobelev: Le problème est qu'une distribution de style C n'est pas explicite. Il peut être égal à a static_cast, mais il pourrait aussi bien être un const_castou pire encore, un reinterpret_castou même une combinaison de ceux-ci. Même si vous savez maintenant en quoi cela se dégradera, supposons que vous passiez aà un autre type plus tard, cela pourrait très bien être le type de changements de transtypage sans que vous n'obteniez autant d'avertissement, vous ne le voulez pas.
KillianDS
4
@KillianDS " supposons que vous changiez a un autre type plus tard " quel type?
curiousguy
2
Oui, ceux-ci ou une distribution implicite si disponible. Il est beaucoup plus clair de savoir quelle est l'intention de la distribution.
KillianDS
8

En tournant la question de clôture, "comment puis-je convertir un en type Test::A" plutôt que d'être rigide quant à l'exigence d'avoir un plâtre là-dedans, et de répondre plusieurs années plus tard, cela semble être une question populaire que personne d'autre ne semble avoir mentionné l'alternative , selon la norme C ++ 11:

5.2.9 Distribution statique

... une expression epeut être explicitement convertie en un type en T utilisant un static_castde la forme static_cast<T>(e)si la déclaration T t(e);est bien formée, pour une variable temporaire inventée t(8.5). L'effet d'une telle conversion explicite équivaut à effectuer la déclaration et l'initialisation puis à utiliser la variable temporaire comme résultat de la conversion.

Par conséquent, l'utilisation directe du formulaire t(e)fonctionnera également, et vous pourriez le préférer pour la propreté:

auto result = Test(a);
Tommy
la source
cette solution fonctionnait dans le cas où l'option du compilateur bloquait static_cast <> (vérification sémantique). Non pas que cela ait du sens pour moi, mais tout de même soigné.
M. Buisson
1

Test castEnum = static_cast<Test>(a-1);va lancer un vers A. Si vous ne voulez pas du sous-sous-réseau 1, vous pouvez redéfinir enum:

enum Test
{
    A:1, B
};

Dans ce cas, `Test castEnum = static_cast (a); ' pourrait être utilisé pour lancer un vers A.

kosolapyj
la source