2012-05-05 5 views
9

Mam następujący kod:Dlaczego gcc nie ostrzega, gdy wartość enum lub int jest przekazywana jako argument funkcji, który jest 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; 
} 

Kompilacja ten kod nie generuje żadnego ostrzeżenia, nawet z -Wall -Wextra opcji podanych do kompilatora. Próbowałem nawet z opcją -Wconversion, która nie przyniosła skutku, ponieważ bool i enum wydawały się być tego samego rozmiaru dla g ++. (rozmiar enum typu nie jest zdefiniowany w specyfikacji o ile mi wiadomo)

Przeszedłem przez podręcznik GCC i nic nie znalazłem.

Pytania:

  • Czy istnieje sposób zmusić kompilator generuje ostrzeżenie w takich przypadkach?
  • A może to, że ten niejawny casting jest zgodny ze specyfikacją C++?

Compiler, że używam: gcc 4.1.2


editted

Wniosek:

Jedynym realnym rozwiązaniem wydaje się zdefiniowanie nowego typu do reprezentowania 0 lub 1 i użyj go zamiast bool.

Kod będzie jak po, i g ++ narzeka typu konwersji:

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

Ponieważ C++” system typu jest dobry tylko dla typów zdefiniowanych przez użytkownika, dla typów wbudowanych niezmiennie jest do bani. Konsekwencja dziedzictwa C. –

+0

Tak, wydaje się, że tak.Postanowiłem napisać nowy typ dedykowany do reprezentowania tylko 0 lub 1 i używać go zamiast bool, który wydaje się być przeznaczony do wyrażenia _true_ lub _false_. – orchistro

Odpowiedz

10

Tak, te konwersje niejawne są całkowicie legalne.

C++ 11 Wstępny n3290, §4.12 logiczne konwersje:

prvalue arytmetyczne, unscoped wyliczenia wskaźnika lub kursora do typu grupy można przekształcić w prvalue typu bool. Wartość zerowa, zerowa wartość wskaźnika lub wartość wskaźnika elementu zerowego jest konwertowana na wartość false; każda inna wartość jest konwertowana na wartość true. Wartość progowa typu std :: nullptr_t może zostać przekonwertowana na wartość typu bool ; wynikowa wartość jest fałszywa.

Ostrzeżenia dotyczące tych konwersji (dla typów arytmetycznych) prawdopodobnie doprowadziłyby do ogromnej liczby ostrzeżeń w całym miejscu, nie sądzę, że byłoby to wykonalne.

w C++ 11, można użyć scoped wyliczenia uniemożliwienia tej niejawna konwersja:

To nie skompilować z powodu braku konwersji z Foo do bool:

enum class Foo { ONE }; 

void tryit(bool b) { } 

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

Dziękuję, Mat. Jeśli jest to zgodne ze specyfikacją C++, domyślam się, że jedynym sposobem osiągnięcia tego, czego chcę, jest wpisanie nowego typu boolowskiego tylko dla projektu, aby członkowie projektu nie popełniali błędów, takich jak fragment kodu. – orchistro

+0

Niestety, gcc 4.1.2 nie obsługuje "enoped enums". Myślę, że powinienem uciekać się do rozwiązania typedef i to faktycznie działa. Zazwyczaj nie jest to konieczne. Ale w pewnych okolicznościach, takich jak ty, refaktoryzujesz kod innych ludzi, bez tego "ścisłego" sprawdzania typu, byłoby ci przykro. Może powinienem był użyć kłaczków. – orchistro

+0

@orchistro: Jeśli to możliwe, spróbuj przejść do nowszej wersji na gcc (wiem, że to nie jest łatwe ...). gcc 4.1.x to dość stara gałąź. –