2009-11-03 7 views
10

Nel tentativo di rendere i miei enumerazioni più typesafe, ho usato gli operatori macro-generated sovraccarico per non consentire il confronto enumerazioni contro tutt'altro che un identico digitato enum:C++ conversione implicita a 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) 

Questo è generalmente l'effetto desiderato; confronti del modulo color_variable == RED funzionano, mentre i confronti del modulo color_variable == 1 generano errori in fase di compilazione grazie a Boost.StaticAssert. (È un approccio decente?)

Tuttavia, il mio compilatore (CodeGear C++ Builder) sta anche tentando di utilizzare questi operatori sovraccaricati per implementare le conversioni implicite bool. Ad esempio, if (color_variable) { ... } viene convertito in if (operator!=(color_variable, 0)) { ... } e sta attivando BOOST_STATIC_ASSERT e non riesce a compilare.

Sono abbastanza sicuro che questo è un comportamento scorretto da parte del mio compilatore (Comeau e GCC non lo fanno, per esempio), ma mi chiedevo se ci sono avvocati di lingua presenti che potrebbero confermare. Ho provato a cercare lo standard di bozze C++ 0x, ma tutto ciò che ho trovato è stata la seguente dichiarazione nella sezione 4.12:

Un valore zero, un valore di puntatore nullo o un valore di puntatore membro nullo viene convertito in falso; qualsiasi altro valore viene convertito in vero.

senza dettagli su come viene verificato "un valore zero".

+2

Poiché si sta tentando di renderlo più tipicamente, non avrebbe senso non consentire la conversione implicita in bool in ogni caso? – Grizzly

+0

Non avevo deciso se non autorizzare la conversione in bool fosse una buona cosa. Il codice esistente con cui ho a che fare organizza le sue enumerazioni in modo tale che il valore intero 0 sia falso e tutto il resto è vero, quindi le conversioni bool sono legittime e probabilmente migliorano la leggibilità dei condizionali. (La leggibilità e lo stile di programmazione sono probabilmente una domanda a parte). –

+0

(E se decido di non consentire conversioni implicite ai bool, preferirei non farlo in un modo che funziona solo su un compilatore.) –

risposta

4

Perché non usi un corso simile al seguente?

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; 

non c'è conversione implicita a bool per ClassEnum<ColorTypeEnum>.

+0

Penso che in realtà vuole la conversione implicita in bool. – xryl669