2011-05-23 8 views
16

Me gustaría obtener un error o advertencia del compilador cuando no se manejan todos los valores enum posibles en una instrucción switch. Por supuesto, puedo agregar un caso predeterminado con una afirmación y (eventualmente) obtener un error en el tiempo de ejecución. Pero me gustaría obtener un error en tiempo de compilación.Reclamo en tiempo de compilación cuando no todos los valores enum se manejan en una sentencia switch en C++

no estoy seguro de si esto es posible en absoluto con C++, pero tal vez alguien sabe un truco ...

Editar: Usando -Wswitch parece ser la solución para GCC. ¿Hay algo similar para VS2010? (No estoy usando GCC).

Edit2: Bueno, he encontrado la solución para VC++ (VS2010):

Activación de advertencia C4062 produce una advertencia cuando se pierde un valor und no se proporciona ningún caso por defecto.

La advertencia de habilitación C4061 produce una advertencia cuando falta un valor, incluso si se proporciona un caso predeterminado.

+1

qué compilador? –

Respuesta

6

No ha mencionado qué compilador está utilizando. Si está utilizando GCC, puede obtenerlo de forma gratuita simplemente habilitando -Wswitch (que se activa automáticamente al -Wall).

1

g ++ lo hace automáticamente si habilita todas las advertencias con -Wall.

4

Si está usando g ++, con -Wall, entonces lo obtendrá.

Por ejemplo, esto:

enum Abc 
{ 
    A =1, 
    B, 
    C 
}; 

Abc a = A; 
switch(a) 
{ 
case A: 
    break; 
case B: 
    break; 
} 

va a causar una advertencia.

Pero es mejor utilizar el caso default con la afirmación fallida, porque cuando agrega un nuevo valor enum, tiene que cambiar todos los archivos en los que está utilizando encender esta enumeración.

+3

¡Parece una razón * no * para usar 'default'! Seguramente quiere que el compilador lo ayude a ubicar las ubicaciones 'enum', en lugar de enmascarar el problema. –

+0

@Oli Eso depende de tus preferencias. Si te gustan las advertencias del compilador, agregar una enum te obliga a cambiar todos los modificadores. Si prefiere la advertencia de tiempo de ejecución, puede concentrarse en pequeños fragmentos de código (dividir y conquistar). –

+3

@VJo: ** siempre ** debe preferir las advertencias del compilador (como errores, idealmente) donde estén disponibles.Confiar en las advertencias de tiempo de ejecución significa que no puede estar seguro de que todo está arreglado hasta que haya ejecutado todas las rutas de código posibles con cada combinación de entrada posible; ¡eso es ridículo si el compilador lo detecta trivialmente! –

2

AFAIK no existe una forma convencional de lograr lo que desea con MSVC. Hay trucos para hacer cosas similares, pero implican un sofisticado vudú de plantillas o acertijos de macros realmente feroces.

Por ejemplo, en lugar de definir su enumeración de una manera convencional, haga lo siguiente:

#define MyEnumEntries(m) \ 
    m(A, 1) \ 
    m(B, 2) \ 
    m(C, 3) \ 

enum Abc { 

    // the following will expand into your enum values definitions 
# define M_Decl(name, value) name = value, 
    MyEnumEntries(M_Decl) 
}; 

Ahora, su conmutador puede reescribirse en esto:

Abc a = A; 

switch(a) 
{ 
#define M_Goto(name, value) \ 
case value: 
    goto label_##name; 

MyEnumEntries(M_Goto) 


case label_A: 
    // TODO 
    break; 
case label_B: 
    // TODO 
    break; 
} 

Lo anterior no compilará si no agregará la entrada de interruptor label_... para todos los valores enum.

Cuestiones relacionadas