列挙型をよりタイプセーフにするために、マクロで生成されたオーバーロードされた演算子を使用して、列挙型を同じ型の列挙型以外と比較できないようにしました。
#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
機能しますが、フォームの比較はBoost.StaticAssertcolor_variable == 1
のおかげでコンパイル時エラーを生成します。(これはまともなアプローチですか?)
ただし、私のコンパイラ (CodeGear C++Builder) も、これらのオーバーロードされた演算子を使用して暗黙的bool
な変換を実装しようとしています。たとえば、if (color_variable) { ... }
に変換されif (operator!=(color_variable, 0)) { ... }
て がトリガーされ、BOOST_STATIC_ASSERT
コンパイルに失敗しています。
これは私のコンパイラ側の間違った動作であると確信しています (たとえば、Comeau と GCC はそれを行いません)。自分で C++0x ドラフト標準を調べてみましたが、セクション 4.12 の下にある次のステートメントしか見つかりませんでした。
ゼロ値、NULL ポインター値、または NULL メンバー ポインター値は false に変換されます。その他の値は true に変換されます。
「ゼロ値」がどのようにチェックされるかについての詳細なし。