Esto es perfectamente normal, su código se basa en un comportamiento no especificado.
En C++, se supone que una enumeración debe contener valores entre sus valores inferior y superior. Cualquier otra cosa puede ser transformada o ignorada por el compilador.
Por ejemplo, si tengo enum Foo { min = 10, max = 11 };
, entonces el compilador puede representarlo con un solo bit significativo y agregar 10 cuando solicite imprimirlo o convertirlo en un entero.
En general, sin embargo, los compiladores no aprovechan esta "compactación" debido al costo de rendimiento, simplemente seleccionan un tipo subyacente que puede acomodar todos los valores y 0
. La mayoría de las veces es int
, a menos que int
sea demasiado pequeño.
Sin embargo, no impide que asuman que los valores que este int
contienen están restringidos al rango que usted definió. En su caso: [0, 2)
.
Como tal, la declaración switch
simplemente se puede optimizar en una comparación con 0
, ya que ha especificado que su enumeración sólo podía ser 0
o 1
.
En la misma línea, if (foo == 3)
podría considerarse una comparación tautológica (siempre falso) y optimizados de distancia.
De hecho, tal como se describe en el gcc "error" señalado por Hans Passat, esta optimización se produce normalmente en poder de 2s límites para gcc. Por ejemplo, si tenía enum { zero, one, two, three };
y le asignó 4
o superior, se produciría el mismo comportamiento.
Tenga en cuenta que el valor almacenado en realidad no se ve afectada! Esta es la razón por la cual la declaración impresa funciona como esperaba, y es una fuente de confusión.
No sé si hay una advertencia para indicar que el almacenamiento de 4 en esta enumeración dará lugar a un comportamiento no especificado. En cualquier caso, sólo funcionaría para los valores de tiempo de compilación ...
Hans Passat siempre que el gcc "bug" que está abierto a realizar un seguimiento de este "problema".
y Emil Styrke proporcionan la justificación (en este caso es la cotización actualizada para las enumeraciones de ámbito):
5.2.9/10
Un valor de tipo integral o de enumeración se puede convertir explícitamente a un tipo de enumeración. El valor no cambia si el valor original está dentro del rango de los valores de enumeración (7.2). De lo contrario, el valor resultante no está especificado (y podría no estar en ese rango). Un valor de tipo punto flotante también se puede convertir a un tipo de enumeración. El valor resultante es lo mismo que convertir el valor original en el tipo subyacente de la enumeración (4.9) y, posteriormente, en el tipo de enumeración.
Parece que un error del compilador. GCC 4.6.1 lo maneja bien. –
g ++ 4.3.4 'Prog: prog.cpp: 20: int doSomethingWithEnum (MyEnum): '! "Nunca debe llegar hasta aquí"' aserción failed.' –
De acuerdo con @larsmans, parece ser un error en GCC 4.4. –