2009-11-03 25 views
10

En un esfuerzo por hacer que mis enumeraciones más typesafe, He estado usando los operadores sobrecargados generados por macro para no permitir la comparación de las enumeraciones en contra de nada, sino una forma idéntica mecanografiado enumeración:C++ conversión implícita 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) 

Esto ha general el efecto deseado; comparaciones del formulario color_variable == RED funcionan, mientras que las comparaciones del formulario color_variable == 1 generan errores en tiempo de compilación gracias a Boost.StaticAssert. (¿Es esto un enfoque decente?)

Sin embargo, mi compilador (CodeGear C++ Builder) también está tratando de utilizar estos operadores sobrecargados para implementar conversiones bool implícitas. Por ejemplo, if (color_variable) { ... } se está traduciendo a if (operator!=(color_variable, 0)) { ... } y está activando BOOST_STATIC_ASSERT y no se puede compilar.

Estoy bastante seguro de que este es un comportamiento incorrecto por parte de mi compilador (Comeau y GCC no lo hacen, por ejemplo) pero me preguntaba si hay abogados de idiomas presentes que puedan confirmarlo. Traté de buscar en el borrador del estándar C++ 0x, pero todo lo que pude encontrar fue la siguiente declaración en la sección 4.12:

Un valor cero, valor de puntero nulo o valor de puntero de miembro nulo se convierte en falso; cualquier otro valor se convierte en verdadero.

sin detalles sobre cómo se comprueba "un valor cero".

+2

Dado que intenta hacer que sea más seguro, ¿no tendría sentido no permitir la conversión implícita a bool de todos modos? – Grizzly

+0

No había decidido si rechazar la conversión a bool era algo bueno. El código existente con el que estoy tratando organiza sus enumeraciones de modo que el valor entero 0 sea falso y todo lo demás sea verdadero, por lo que las conversiones de bool son legítimas, y posiblemente mejoren la legibilidad de las condicionales. (La legibilidad y el estilo de programación es probablemente una pregunta separada.) –

+0

(Y si decido rechazar conversiones implícitas a bools, preferiría no hacerlo de una manera que solo funcione en un compilador). –

Respuesta

4

¿Por qué no utiliza una clase como la siguiente?

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; 

no hay conversión implícita a bool para ClassEnum<ColorTypeEnum>.

+0

Creo que en realidad quiere la conversión implícita a bool. – xryl669

Cuestiones relacionadas