2009-11-03 7 views
10

Dans un effort pour rendre mes énumérations plus Typesafe, je me sers des opérateurs macro généré une surcharge de désavouer la comparaison énumérations contre quoi que ce soit, mais un typé identique ENUM:C++ conversion implicite 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) 

Cela a généralement l'effet désiré; comparaisons de la forme color_variable == RED travail, tandis que les comparaisons de la forme color_variable == 1 générer des erreurs de compilation grâce à Boost.StaticAssert. (Est-ce une approche décente?)

Cependant, mon compilateur (CodeGear C++ Builder) essaie également d'utiliser ces opérateurs surchargés pour implémenter des conversions bool implicites. Par exemple, if (color_variable) { ... } est en cours de traduction en if (operator!=(color_variable, 0)) { ... } et déclenche BOOST_STATIC_ASSERT et ne parvient pas à compiler. Je suis à peu près certain que c'est un comportement incorrect de la part de mon compilateur (Comeau et GCC ne le font pas, par exemple) mais je me demandais s'il y avait des linguistes présents qui pourraient confirmer. J'ai essayé de chercher dans le projet de norme C++ 0x moi-même, mais tout ce que je pouvais trouver était l'instruction suivante sous la section 4.12:

Une valeur nulle, une valeur de pointeur nulle ou une valeur de pointeur de membre null est convertie en false; toute autre valeur est convertie en vrai.

sans détails sur la façon dont "une valeur nulle" est vérifiée.

+2

Puisque vous essayez de le rendre plus sûr, ne serait-il pas logique d'interdire la conversion implicite en bool de toute façon? – Grizzly

+0

Je n'avais pas décidé si refuser la conversion en bool était une bonne chose. Le code existant dont je dispose arrange ses énumérations de manière à ce que la valeur entière 0 soit fausse et que tout le reste soit vrai, ainsi les conversions booléennes sont légitimes, et elles améliorent sans doute la lisibilité des conditions. (La lisibilité et le style de programmation sont probablement une question distincte.) –

+0

(Et si je décide de ne pas autoriser les conversions implicites en booléens, je préférerais ne pas le faire d'une manière qui ne fonctionne que sur un compilateur.) –

Répondre

4

Pourquoi n'utilisez-vous pas une classe comme suit?

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; 

Il n'y a pas de conversion implicite bool pour ClassEnum<ColorTypeEnum>.

+0

Je pense qu'il veut la conversion implicite en bool. – xryl669

Questions connexes