C++ の組み込み列挙型がタイプセーフでないことはよく知られています。タイプセーフな列挙型を実装するクラスがどこで使用されているのか疑問に思っていました...私自身は次の「自転車」を使用していますが、やや冗長で制限があります。
typesafenum.h:
struct TypesafeEnum
{
// Construction:
public:
TypesafeEnum(): id (next_id++), name("") {}
TypesafeEnum(const std::string& n): id(next_id++), name(n) {}
// Operations:
public:
bool operator == (const TypesafeEnum& right) const;
bool operator != (const TypesafeEnum& right) const;
bool operator < (const TypesafeEnum& right) const;
std::string to_string() const { return name; }
// Implementation:
private:
static int next_id;
int id;
std::string name;
};
typesafenum.cpp:
int TypesafeEnum::next_id = 1;
bool TypesafeEnum::operator== (const TypesafeEnum& right) const
{ return id == right.id; }
bool TypesafeEnum::operator!= (const TypesafeEnum& right) const
{ return !operator== (right); }
bool TypesafeEnum::operator< (const TypesafeEnum& right) const
{ return id < right.id; }
使用法:
class Dialog
{
...
struct Result: public TypesafeEnum
{
static const Result CANCEL("Cancel");
static const Result OK("Ok");
};
Result doModal();
...
};
const Dialog::Result Dialog::Result::OK;
const Dialog::Result Dialog::Result::CANCEL;
追加: 要件についてもっと具体的であるべきだったと思います。私はそれらを要約しようとします:
優先度 1: enum 変数を無効な値に設定することは、例外なく不可能 (コンパイル時エラー) であるべきです。
優先度 2: enum 値と int の間の変換は、単一の明示的な関数/メソッド呼び出しで可能にする必要があります。
優先度 3: 可能な限りコンパクトでエレガントで便利な宣言と使用法
優先度 4: enum 値と文字列との変換。
優先度 5: (あると便利) enum 値を反復処理できる可能性。