In an effort to make my enums more typesafe, I've been using macro-generated overloaded operators to disallow comparing enums against anything but an identically typed enum:
#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, GREE开发者_如何学CN };
MAKE_ENUM_TYPESAFE(ColorType)
This generally has the desired effect; comparisons of the form color_variable == RED
work, while comparisons of the form color_variable == 1
generate compile-time errors thanks to Boost.StaticAssert. (Is this a decent approach?)
However, my compiler (CodeGear C++Builder) is also trying to use these overloaded operators to implement implicit bool
conversions. For example, if (color_variable) { ... }
is being translated to if (operator!=(color_variable, 0)) { ... }
and is triggering the BOOST_STATIC_ASSERT
and failing to compile.
I'm fairly certain that this is incorrect behavior on the part of my compiler (Comeau and GCC don't do it, for example) but was wondering if there are any language lawyers present who could confirm. I tried looking up in the C++0x draft standard myself, but all I could find was the following statement under section 4.12:
A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true.
without details as to how "a zero value" is checked for.
Why don't you use a class like following?
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;
There is no implicit conversion to bool for ClassEnum<ColorTypeEnum>
.
精彩评论