【发布时间】:2010-12-12 16:11:40
【问题描述】:
为了使我的枚举更加类型安全,我一直在使用宏生成的重载运算符来禁止将枚举与除相同类型的枚举之外的任何内容进行比较:
#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 转换。例如,if (color_variable) { ... } 正在被转换为 if (operator!=(color_variable, 0)) { ... } 并正在触发 BOOST_STATIC_ASSERT 并且无法编译。
我相当确定这是我的编译器的错误行为(例如,Comeau 和 GCC 不这样做),但我想知道是否有任何语言律师可以确认。我自己尝试在 C++0x 草案标准中查找,但我只能找到第 4.12 节下的以下语句:
将零值、空指针值或空成员指针值转换为假;任何其他值都将转换为 true。
没有关于如何检查“零值”的详细信息。
【问题讨论】:
-
既然您试图使其更加类型安全,那么无论如何禁止隐式转换为 bool 是否有意义?
-
我还没有决定禁止转换为 bool 是否是一件好事。我正在处理的现有代码将其枚举安排为整数值 0 为假,其他一切为真,因此 bool 转换是合法的,并且可以说它们提高了条件的可读性。 (可读性和编程风格可能是一个单独的问题。)
-
(如果我决定禁止隐式转换为布尔值,我不希望以仅适用于一个编译器的方式进行。)
标签: c++ conditional boolean implicit