2012-05-05 10 views
9

He siguiente código:¿Por qué gcc no avisa cuando se pasa un valor enum o int como un argumento de función que es bool?

typedef enum 
{ 
    FOO, 
    BAR, 
    BAZ 
} foo_t; 

static void afunc(bool is_it_on) 
{ 
    /* do the job */ 
} 

int main(void) 
{ 
    afunc(BAZ); 
    return 0; 
} 

Compilar este código no genera ningún mensaje de advertencia, incluso con -Wall -Wextra opciones que se ofrecen al compilador. Incluso he intentado con la opción -Wconversion, que no tuvo efecto porque bool y enum parecían ser del mismo tamaño para g ++. (el tamaño del tipo enum no está definido en la especificación hasta donde yo sé)

He peinado a través del manual de gcc y no he encontrado nada al respecto.

Preguntas:

  • ¿Hay una manera de forzar al compilador que genere una advertencia en casos como este?
  • ¿O es que este casting implícito es legal por especificación C++?

compilador que estoy usando: gcc 4.1.2


Editted

Conclusión:

La única solución viable a este parece definir un nuevo tipo para representar 0 o 1, y úselo en lugar de bool.

el código sería como seguir, y g ++ se queja de conversión de tipo:

typedef enum 
{ 
    FOO1, 
    FOO2 
} foo_t; 

typedef enum 
{ 
    MY_FALSE, 
    MY_TRUE 
} my_bool_t; 

void foo(my_bool_t a) 
{ 
} 

int main(void) 
{ 
    /* 
     * gcc generates an error. 
     * error: cannot convert ‘foo_t’ to ‘my_bool_t’ 
     * for argument ‘1’ to ‘void foo(my_bool_t)’ 
     */ 
    foo(FOO1); 
    return 0; 
} 
+1

Debido a que C++' el sistema tipo solo es bueno para los tipos definidos por el usuario, para los tipos incorporados invariablemente es una mierda. Consecuencia de su herencia C –

+0

Sí, parece que sí.Decidí escribir un nuevo tipo dedicado para representar solo 0 o 1, y usarlo en lugar de bool, que parece estar destinado a expresar _true_ o _false_. – orchistro

Respuesta

10

Sí, esas conversiones implícitas son perfectamente legal.

C++ 11 proyectos de n3290, §4.12 conversiones booleanas:

A prvalue de la aritmética, la enumeración sin ámbito, puntero, o puntero a tipo de miembro se puede convertir en un prvalue de tipo bool. Un valor cero, un valor de puntero nulo o un valor de puntero de miembro nulo se convierte en falso; cualquier otro valor se convierte en verdadero. Un prvalue de tipo std :: nullptr_t se puede convertir a un prvalue de type bool; el valor resultante es falso.

Las advertencias sobre estas conversiones (para los tipos aritméticos) probablemente darían lugar a un gran número de advertencias en todo el lugar, no creo que sea manejable.

En C++ 11, puede utilizar con ámbito enumeraciones para evitar que la conversión implícita:

Esta falla al compilar por falta de una conversión de Foo a bool:

enum class Foo { ONE }; 

void tryit(bool b) { } 

int main() 
{ 
    tryit(Foo::ONE); 
} 
+0

Gracias, Mat. Si es legal según la especificación C++, supongo que la única manera de lograr lo que quiero es escribir un nuevo tipo booleano solo para el proyecto, de modo que los miembros del proyecto no cometan errores, como el fragmento de código. – orchistro

+0

Lamentablemente, gcc 4.1.2 no parece ser compatible con las 'enums delimitadas'. Supongo que debería recurrir a la solución typedef, y realmente funciona. Normalmente, no es necesario. Pero en algunas circunstancias, como si estuviera refaccionando el código de otras personas, sin esta verificación de tipo "estricta", lo lamentaría. Tal vez debería haber usado pelusa. – orchistro

+0

@orchistro: Si es posible, intente pasar a una versión más nueva en gcc (sé que no es fácil ...). gcc 4.1.x es una rama bastante antigua. –

Cuestiones relacionadas