Какие типы типов Enum в C++ вы используете?

Общеизвестно, что встроенные перечисления 9X_design-patterns в C++ небезопасны. Мне было интересно, какие 9X_enum классы, реализующие типизированные перечисления, используются 9X_enumerations там ... Я сам использую следующий «велосипед», но 9X_design-pattern он несколько многословен и ограничен:

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; 

Дополнение: Думаю, мне 9X_enum следовало более конкретно рассказать о требованиях. Попробую 9X_gof их резюмировать:

Приоритет 1: установка недопустимого 9X_gof значения для переменной enum должна быть 9X_enum невозможной (ошибка времени компиляции) без 9X_c++03 исключений.

Приоритет 2: преобразование значения 9X_patterns перечисления в / из int должно быть возможным 9X_gang-of-four с помощью одного явного вызова функции / метода.

Приоритет 9X_patterns 3: максимально компактное, элегантное и 9X_design-patterns удобное объявление и использование

Приоритет 9X_enumerations 4: преобразование значений перечисления 9X_patterns в строки и обратно.

Приоритет 5: (Приятно 9X_design-pattern иметь) возможность перебирать значения перечисления.

45
0
8
Общее количество ответов: 8

Ответ #1

Ответ на вопрос: Какие типы типов Enum в C++ вы используете?

В настоящее время я играю с предложением 9X_enums Boost.Enum из Boost Vault (filename enum_rev4.6.zip). Хотя он никогда 9X_enumerations официально не подавался на включение в Boost, его 9X_gang-of-four можно использовать как есть. (Документация 9X_enumeration отсутствует, но она компенсируется ясным 9X_type-safety исходным кодом и хорошими тестами.)

Boost.Enum 9X_c++03 позволяет вам объявить перечисление следующим 9X_enums образом:

BOOST_ENUM_VALUES(Level, const char*, (Abort)("unrecoverable problem") (Error)("recoverable problem") (Alert)("unexpected behavior") (Info) ("expected behavior") (Trace)("normal flow of execution") (Debug)("detailed object state listings") ) 

И пусть он автоматически расширяется 9X_patterns до этого:

class Level : public boost::detail::enum_base { public: enum domain { Abort, Error, Alert, Info, Trace, Debug, }; BOOST_STATIC_CONSTANT(index_type, size = 6); Level() {} Level(domain index) : boost::detail::enum_base(index) {} typedef boost::optional optional; static optional get_by_name(const char* str) { if(strcmp(str, "Abort") == 0) return optional(Abort); if(strcmp(str, "Error") == 0) return optional(Error); if(strcmp(str, "Alert") == 0) return optional(Alert); if(strcmp(str, "Info") == 0) return optional(Info); if(strcmp(str, "Trace") == 0) return optional(Trace); if(strcmp(str, "Debug") == 0) return optional(Debug); return optional(); } private: friend class boost::detail::enum_base; static const char* names(domain index) { switch(index) { case Abort: return "Abort"; case Error: return "Error"; case Alert: return "Alert"; case Info: return "Info"; case Trace: return "Trace"; case Debug: return "Debug"; default: return NULL; } } typedef boost::optional optional_value; static optional_value values(domain index) { switch(index) { case Abort: return optional_value("unrecoverable problem"); case Error: return optional_value("recoverable problem"); case Alert: return optional_value("unexpected behavior"); case Info: return optional_value("expected behavior"); case Trace: return optional_value("normal flow of execution"); case Debug: return optional_value("detailed object state listings"); default: return optional_value(); } } }; 

Он удовлетворяет всем пяти перечисленным 9X_c++03 вами приоритетам.

42
5

  • зачем это нужно для решения проблемы, которой не существует ?? !! * г ...

Ответ #2

Ответ на вопрос: Какие типы типов Enum в C++ вы используете?

Хороший компромиссный метод заключается 9X_pattern в следующем:

struct Flintstones { enum E { Fred, Barney, Wilma }; }; Flintstones::E fred = Flintstones::Fred; Flintstones::E barney = Flintstones::Barney; 

Это небезопасно с точки зрения 9X_enumeration типов в том же смысле, что и ваша версия, но 9X_gang-of-four использование лучше, чем стандартные перечисления, и 9X_gang-of-four вы все равно можете воспользоваться преимуществами 9X_c++03 целочисленного преобразования, когда оно 9X_enumeration вам нужно.

18
4

  • Продолжение вопроса о пространстве имен: для перечислений, которые находятся внутри класса или структуры, вы не можете использовать пространство имен. Если п ...

Ответ #3

Ответ на вопрос: Какие типы типов Enum в C++ вы используете?

Я использую C++0x typesafe enums. Я использую несколько вспомогательных 9X_gof шаблонов / макросов, которые обеспечивают 9X_design-pattern функциональность строки "от / до".

enum class Result { Ok, Cancel}; 

14
3

  • @Roddy: значит, вы используете функцию, которую поддерживает только ** один ** к ...

Ответ #4

Ответ на вопрос: Какие типы типов Enum в C++ вы используете?

Я не знаю. Слишком много накладных расходов 9X_enum без особой пользы. Кроме того, очень удобным 9X_enum инструментом является возможность преобразовывать 9X_enums перечисления в разные типы данных для сериализации. Я 9X_design-patterns никогда не видел случая, когда перечисление 9X_gof «Типобезопасное» стоило бы накладных расходов 9X_design-patterns и сложности, когда C++ уже предлагает достаточно 9X_design-patterns хорошую реализацию.

6
1

  • Типобезопасное перечисление может быть реализовано с использованием ...

Ответ #5

Ответ на вопрос: Какие типы типов Enum в C++ вы используете?

Я считаю, что вы придумываете проблему, а 9X_patterns затем подбираете для нее решение. Я не вижу 9X_gof необходимости создавать сложную структуру 9X_patterns для перечисления ценностей. Если вы преданы, чтобы 9X_type-safety ваши значения были только членами определенного 9X_enums набора, вы можете взломать вариант уникального 9X_enums типа данных набора.

2
0

Ответ #6

Ответ на вопрос: Какие типы типов Enum в C++ вы используете?

Я лично использую адаптированную версию 9X_c++03 typesafe enum idiom. Он не обеспечивает всех пяти «требований», которые 9X_enums вы указали в своей редакции, но я все равно 9X_pattern категорически не согласен с некоторыми из 9X_gang-of-four них. Например, я не понимаю, как Prio # 4 9X_pattern (преобразование значений в строки) имеет 9X_design-pattern какое-либо отношение к безопасности типов. В 9X_patterns большинстве случаев строковое представление 9X_enum отдельных значений в любом случае должно 9X_enumerations быть отделено от определения типа (подумайте 9X_patterns о i18n по простой причине). Prio # 5 (итерация, необязательный) - одна 9X_enumeration из самых приятных вещей, которые я хотел 9X_enumerations бы видеть естественным в перечислениях, поэтому мне 9X_c++03 было грустно, что в вашем запросе это выглядит 9X_type-safety как "необязательное", но кажется, что 9X_design-patterns это лучше решать с помощью separate iteration system, такого как 9X_enumeration функции begin / end или enum_iterator, что позволяет 9X_gang-of-four им без проблем работать с STL и C++ 11 foreach.

OTOH 9X_design-patterns эта простая идиома прекрасно обеспечивает 9X_design-patterns Prio # 3 Prio # 1 благодаря тому, что в 9X_design-pattern основном она только обертывает enum с дополнительной 9X_enums информацией о типе. Не говоря уже о том, что 9X_gang-of-four это очень простое решение, которое по большей 9X_type-safety части не требует никаких внешних заголовков 9X_c++03 зависимостей, поэтому его довольно легко 9X_enumerations носить с собой. Он также имеет то преимущество, что 9X_enum перечисления имеют область видимости а-ля-C++ 11:

// This doesn't compile, and if it did it wouldn't work anyway enum colors { salmon, .... }; enum fishes { salmon, .... }; // This, however, works seamlessly. struct colors_def { enum type { salmon, .... }; }; struct fishes_def { enum type { salmon, .... }; }; typedef typesafe_enum colors; typedef typesafe_enum fishes; 

Единственная 9X_gof "дыра", которую предоставляет 9X_c++03 решение, состоит в том, что оно не учитывает 9X_patterns тот факт, что оно не препятствует прямому 9X_gang-of-four сравнению enum разных типов (или enum и int), потому 9X_enumeration что когда вы используете значения напрямую, вы 9X_pattern вызываете неявное преобразование в int:

if (colors::salmon == fishes::salmon) { .../* Ooops! */... } 

Но до 9X_enumeration сих пор я обнаружил, что такие проблемы 9X_c++03 можно решить, просто предлагая лучшее сравнение 9X_enums с компилятором - например, явно предоставляя 9X_design-pattern оператор, который сравнивает любые два разных 9X_gang-of-four типа enum, а затем заставляя его терпеть неудачу:

// I'm using backports of C++11 utilities like static_assert and enable_if template typename enable_if< (is_enum::value && is_enum::value) && (false == is_same::value) , bool > ::type operator== (Enum1, Enum2) { static_assert (false, "Comparing enumerations of different types!"); } 

Хотя 9X_pattern пока кажется, что это не нарушает код, а 9X_gang-of-four явно решает конкретную проблему, не делая 9X_gang-of-four чего-то еще, я не уверен, что это то, что 9X_patterns нужно "" "do (я подозреваю, что 9X_design-pattern это будет мешать enum уже принимать участие 9X_pattern в операторах преобразования, объявленных 9X_enumerations где-то в другом месте; я с радостью получу 9X_enum комментарий по этому поводу).

Сочетание этого 9X_enums с приведенной выше идиомой типизации дает 9X_patterns нечто, относительно близкое к C++ 11 enum class по 9X_enum человечности (удобочитаемость и ремонтопригодность) без 9X_gof необходимости делать что-то слишком непонятное. И 9X_pattern я должен признать, что это было весело, я 9X_design-patterns никогда не думал на самом деле спросить у компилятора, имею 9X_pattern ли я дело с enum s или нет ...

2
0

Ответ #7

Ответ на вопрос: Какие типы типов Enum в C++ вы используете?

Я думаю, что Java enum будет хорошей моделью 9X_gof для подражания. По сути, форма Java будет 9X_type-safety выглядеть так:

public enum Result { OK("OK"), CANCEL("Cancel"); private final String name; Result(String name) { this.name = name; } public String getName() { return name; } } 

Что интересно в подходе Java, так 9X_enumeration это то, что OK и CANCEL являются неизменяемыми одноэлементными 9X_gang-of-four экземплярами Result (с методами, которые вы видите). Вы 9X_c++03 не можете создавать дополнительные экземпляры 9X_enum Result. Поскольку они синглтоны, вы можете сравнивать 9X_type-safety их по указателю / ссылке --- очень удобно. :-)

ETA: в 9X_enumerations Java вместо того, чтобы создавать битовые 9X_patterns маски вручную, вместо этого вы используете 9X_enum EnumSet для указания набора бит (он реализует интерфейс 9X_enums Set и работает как наборы, но реализован с 9X_design-pattern использованием битовых масок). Намного более 9X_enum читабельно, чем рукописные манипуляции с 9X_design-patterns битовой маской!

1
0

Ответ #8

Ответ на вопрос: Какие типы типов Enum в C++ вы используете?

Я дал ответ на этот here по другой теме. Это 9X_type-safety другой стиль подхода, который позволяет 9X_enumeration использовать большую часть тех же функций, не 9X_design-patterns требуя изменения исходного определения перечисления 9X_enumeration (и, следовательно, разрешая использование 9X_type-safety в случаях, когда вы не определяете перечисление). Он 9X_gang-of-four также позволяет проверять диапазон во время 9X_type-safety выполнения.

Обратной стороной моего подхода 9X_design-patterns является то, что он не обеспечивает программного 9X_design-pattern обеспечения связи между перечислением и 9X_pattern вспомогательным классом, поэтому их нужно 9X_enumeration обновлять параллельно. У меня работает, но 9X_patterns YMMV.

1
0