为了使我的枚举更具有类型安全性,我一直在使用宏生成的重载操作符来禁止将枚举与任何内容进行比较,除了相同类型的枚举:
#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)
这通常具有期望的效果;比较形式color_variable == RED的工作,而比较形式color_variable == 1生成编译时错误感谢Boost.StaticAssert.(这是一个体面的方法吗?)
然而,我的编译器(CodeGear C Builder)也试图使用这些重载的运算符来实现隐式的bool转换.例如,如果(color_variable){…}被转换为if(operator!=(color_variable,0)){…}并触发BOOST_STATIC_ASSERT并且无法编译.
我相当肯定,这是我的编译器(Comeau和GCC不这样做)的错误行为,但是想知道有没有任何语言律师可以确认.我试着自己查看C 0x草案标准,但我可以找到的是根据第4.12节的以下声明:
A zero value,null pointer value,or null member pointer value is converted to false; any other value is converted to true.
没有关于如何检查“零值”的细节.
解决方法
你为什么不使用像下面的类?
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,GREEN }; typedef ClassEnum<ColorTypeEnum> ColorType;
ClassEnum< ColorTypeEnum>没有隐式转换为bool.