Подтвердить что ты не робот

С++ неявное преобразование в 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.

без каких-либо подробностей относительно того, как проверяется "нулевое значение".

4b9b3361

Ответ 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>.