С++ неявное преобразование в 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)
Это обычно имеет желаемый эффект; сравнения формы color_variable == RED
работают, а сравнения формы color_variable == 1
генерируют ошибки времени компиляции благодаря Boost.StaticAssert. (Это достойный подход?)
Однако мой компилятор (CodeGear С++ Builder) также пытается использовать эти перегруженные операторы для реализации неявных преобразований bool
. Например, if (color_variable) { ... }
переводится на if (operator!=(color_variable, 0)) { ... }
и запускает BOOST_STATIC_ASSERT
и не компилируется.
Я абсолютно уверен, что это неправильное поведение со стороны моего компилятора (например, Комо и GCC этого не делают), но задавались вопросом, есть ли какие-либо представители языка, которые могут подтвердить. Я пробовал искать в стандартном черновике С++ 0x, но все, что я мог найти, было следующим утверждением в разделе 4.12:
Значение нуля, значение нулевого указателя или значение указателя нулевого элемента преобразуется в значение false; любое другое значение преобразуется в значение true.
без каких-либо подробностей относительно того, как проверяется "нулевое значение".
Ответы
Ответ 1
Почему бы вам не использовать класс вроде следующего?
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;
Нет никакого неявного преобразования в bool для ClassEnum<ColorTypeEnum>
.