Общеизвестно, что встроенные перечисления в С++ не являются типичными. Мне было интересно, какие классы, реализующие typesafe enums, используются там... Я сам использую следующий "велосипед", но он несколько подробный и ограниченный:
typesafeenum.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;
};
typesafeenum.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: Установка переменной перечисления в недопустимое значение должна быть невозможной (ошибка времени компиляции) без исключений.
Приоритет 2: Преобразование значения enum в/из int должно быть возможным с помощью одного явного вызова функции/метода.
Приоритет 3: как можно более компактное, элегантное и удобное объявление и использование
Приоритет 4: Преобразование значений перечисления в строки и из строк.
Приоритет 5: (Приятно иметь) Возможность итерации над значениями перечисления.