¿Cómo convertir int a enum en C ++?

222

¿Cómo convierto un int a una enumeración en C ++?

Por ejemplo:

enum Test
{
    A, B
};

int a = 1;

¿Cómo convierto aa escribir Test::A?

usuario1509260
fuente
1
link Tenga en cuenta que no importa si int coincide con una de las constantes del tipo enum; La conversión de tipo es siempre ilegal.
Iwaz
3
Creo que si desea convertir a Test :: A, el valor de int atendrá que ser 0, porque Test :: A tiene un valor implícito de 0 y Test :: B tiene un valor implícito de 1. A menos que el hecho de emitir específicamente para Test :: A está más
allá

Respuestas:

243
int i = 1;
Test val = static_cast<Test>(i);
Andrés
fuente
21
auto val = static_cast <prueba> (i); // C ++ 11
Mitch
3
@ Mitch, ¿qué obtengo por usar autoen este caso? ¿Hay alguna mejora en el rendimiento?
Frederico Pantuzza
2
Sin mejoras de rendimiento. El compilador solo deduce el tipo automáticamente si especifica con "auto". Si decide cambiar su nombre de enumeración en el futuro, modificará menos su código ya que el compilador deducirá automáticamente el nombre de tipo correcto.
Aydin Özcan
74
Test e = static_cast<Test>(1);
bames53
fuente
10
MSDN: el operador static_cast puede convertir explícitamente un valor integral en un tipo de enumeración. Si el valor del tipo integral no se encuentra dentro del rango de valores de enumeración, el valor de enumeración resultante no está definido.
Kirill Kobelev
1
@KirillKobelev si el valor integral puede ser representado por el tipo subyacente de la enumeración, entonces la enumeración resultante debe tener ese valor. De lo contrario, el valor enum producido será el valor resultante de convertir la expresión al tipo subyacente de la enumeración. Si VC ++ hace algo diferente, entonces creo que no es conforme.
bames53
2
qué debe hacer un compilador conforme, si enum tiene valores {1,3,5} y el código intenta hacer <static_cast> del valor de 2. ¿Cómo diferirá eso del C-cast?
Kirill Kobelev
66
@KirillKobelev No estoy usando un static_cast porque hace algo diferente de un molde de estilo C, estoy usando static_cast porque los moldes de C ++ son estilísticamente preferibles a los moldes de C.
bames53
44
@KirillKobelev " si la enumeración tiene valores {1,3,5} " No. El tipo de enumeración no puede limitarse solo a estos 3 valores posibles: {1,3,5} son los enumeradores (denominados valores de enumeración), no la enumeración en sí . Si 1,3,5 son posibles valores de enumeración , entonces también lo es 2.
curiousguy
25

Tu codigo

enum Test
{
    A, B
}

int a = 1;

Solución

Test castEnum = static_cast<Test>(a);
usuario1515687
fuente
45
Es una buena idea usar el modelo más restrictivo posible y evitar los modelos de estilo C por completo, para darle al compilador la mejor oportunidad de detectar errores. static_castSería un mejor elenco aquí.
Mike Seymour
44
@ Mike Seymour, el problema es que el reparto estático no tiene ninguna diferencia con el reparto C en este caso. ¿Cómo y qué error puede detectar?
Kirill Kobelev
77
@KirillKobelev: El problema es que un reparto de estilo C no es explícito. Puede ser igual a a static_cast, pero bien podría ser const_castao incluso peor, areinterpret_cast o incluso una combinación de ellas. Incluso si sabe ahora en qué se degradará, suponga que cambia aa otro tipo más adelante, podría muy bien ser el tipo de cambios de lanzamiento sin siquiera recibir una advertencia, no quiere eso.
KillianDS
44
@KillianDS " supongamos que cambia un a otro tipo más adelante " ¿qué tipo?
curioso
2
Sí, ya sea esos o un elenco implícito si está disponible. Es mucho más claro cuál es la intención del elenco.
KillianDS
8

Escupiendo la pregunta de cierre, "¿cómo convierto un a tipo Test::A" en lugar de ser rígido sobre el requisito de tener un elenco allí, y respondiendo varios años tarde, esto parece ser una pregunta popular que nadie más parece haber mencionado la alternativa , según el estándar C ++ 11:

5.2.9 Fundición estática

... una expresión ese puede convertir explícitamente a un tipo T usando a static_castde la forma static_cast<T>(e)si la declaración T t(e);está bien formada, para alguna variable temporal inventada t(8.5). El efecto de una conversión tan explícita es el mismo que realizar la declaración e inicialización y luego usar la variable temporal como resultado de la conversión.

Por lo tanto, directamente usando el formulario t(e) también funcionará, y es posible que lo prefiera por pulcritud:

auto result = Test(a);
Tommy
fuente
esta solución funcionó en caso de que la opción del compilador bloqueara static_cast <> (verificación semántica) No es que tenga sentido para mí, pero aún así ordenado.
Sr. Buisson el
1

Test castEnum = static_cast<Test>(a-1);lanzará un a A. Si no quieres la subestructura 1, puedes redefinir enum:

enum Test
{
    A:1, B
};

En este caso, 'Test castEnum = static_cast (a);' podría usarse para lanzar un a A.

kosolapyj
fuente