2009-11-03 14 views
10

W wysiłku, aby moje teksty stałe więcej typesafe, Używam operatorów makro generowane przeciążony aby uniemożliwić porównując teksty stałe przed czymkolwiek ale identycznie wpisany ENUM:C++ niejawna konwersja do bool

#include <boost/static_assert.hpp> 

#define MAKE_ENUM_OPERATOR_TYPESAFE(enumtype, op) \ 
    template<typename T> \ 
    inline bool operator op(enumtype lhs, T rhs) \ 
    { \ 
    BOOST_STATIC_ASSERT(sizeof(T) == 0); \ 
    return false; \ 
    } \ 
    \ 
    template<> \ 
    inline bool operator op(enumtype lhs, enumtype rhs) \ 
    { \ 
    return static_cast<int>(lhs) op static_cast<int>(rhs); \ 
    } 

#define MAKE_ENUM_TYPESAFE(enumtype) \ 
    MAKE_ENUM_OPERATOR_TYPESAFE(enumtype, ==) \ 
    MAKE_ENUM_OPERATOR_TYPESAFE(enumtype, !=) \ 
    MAKE_ENUM_OPERATOR_TYPESAFE(enumtype, >) \ 
    MAKE_ENUM_OPERATOR_TYPESAFE(enumtype, <) \ 
    MAKE_ENUM_OPERATOR_TYPESAFE(enumtype, >=) \ 
    MAKE_ENUM_OPERATOR_TYPESAFE(enumtype, <=) 

// Sample usage: 
enum ColorType { NO_COLOR, RED, BLUE, GREEN }; 
MAKE_ENUM_TYPESAFE(ColorType) 

to zazwyczaj ma pożądany efekt; porównania formularza color_variable == RED pracy, podczas gdy porównania formularza color_variable == 1 generują błędy kompilacji dzięki Boost.StaticAssert. (Czy to przyzwoite podejście?)

Jednak mój kompilator (CodeGear C++ Builder) również próbuje wykorzystać te przeciążone operatory do implementacji niejawnych konwersji bool. Na przykład if (color_variable) { ... } jest tłumaczony na if (operator!=(color_variable, 0)) { ... } i wyzwala BOOST_STATIC_ASSERT i nie można go skompilować.

Jestem dość pewny, że jest to nieprawidłowe zachowanie ze strony mojego kompilatora (na przykład Comeau i GCC nie robię tego), ale zastanawiałem się, czy są jacyś prawnicy, którzy mogliby potwierdzić. Próbowałem przeglądać w projekcie standardu C++ 0x, ale wszystko, co mogłem znaleźć, to następująca instrukcja w sekcji 4.12:

Wartość zerowa, zerowa wartość wskaźnika lub wartość wskaźnika elementu zerowego jest przekształcana na wartość false; każda inna wartość jest konwertowana na wartość true.

bez szczegółów dotyczących sprawdzania "wartości zerowej".

+2

Skoro próbujesz uczynić go bardziej bezpiecznym, czy nie ma sensu odrzucanie niejawnej konwersji na Bool? – Grizzly

+0

Nie zdecydowałem, czy niedopuszczenie do konwersji na język bool było dobrą rzeczą. Istniejący kod, z którym mam do czynienia, porządkuje swoje wyliczenia tak, że wartość całkowita 0 jest fałszywa, a wszystko inne jest prawdziwe, więc konwersje bool są uzasadnione i prawdopodobnie poprawiają czytelność warunków. (Czytelność i styl programowania to prawdopodobnie osobne pytanie.) –

+0

(A jeśli postanowię odrzucić niejawne konwersje do boolów, wolałbym nie robić tego w sposób, który działa tylko na jednym kompilatorze.) –

Odpowiedz

4

Dlaczego nie używasz klasy podobnej do tej?

template<class Enum> 
class ClassEnum 
{ 
public: 
    explicit ClassEnum(Enum value) : value(value) {} 
    inline bool operator ==(ClassEnum rhs) { return value == rhs.value; } 
    inline bool operator !=(ClassEnum rhs) { return value != rhs.value; } 
    inline bool operator <=(ClassEnum rhs) { return value <= rhs.value; } 
    inline bool operator >=(ClassEnum rhs) { return value >= rhs.value; } 
    inline bool operator <(ClassEnum rhs) { return value < rhs.value; } 
    inline bool operator >(ClassEnum rhs) { return value > rhs.value; } 

    // Other operators... 
private: 
    Enum value; 
} 

enum ColorTypeEnum { NO_COLOR, RED, BLUE, GREEN }; 
typedef ClassEnum<ColorTypeEnum> ColorType; 

Nie ma żadnej niejawnej konwersji na wartość bool dla ClassEnum<ColorTypeEnum>.

+0

Myślę, że on faktycznie chce niejawnej konwersji na wartość bool. – xryl669

Powiązane problemy