Enumerations have many uses in development. For example, when creating games, they are used for programming character states or possible directions of movement:enum State {Idle, Fidget, Walk, Scan, Attack}; enum Direction {North, South, East, West}; State: Fidget β is displayed in the console instead of β State: 1 β. Also, it is often necessary to serialize enums into JSON, YAML or another format, moreover in the form of string values. Besides the fact that strings are easier to perceive than numbers, their use in the serialization format increases the resistance to changes in the numerical values ββof enumeration constants. Ideally, "Fidget" should reference the Fidget , even if a new constant is declared, and Fidget has a value other than 1. BETTER_ENUM(State, int, Idle, Fidget, Walk, Scan, Attack) BETTER_ENUM(Direction, int, North, South, East, West) State state = State::Fidget; state._to_string(); // "Fidget" std::cout << "state: " << state; // "state: Fidget" state = State::_from_string("Scan"); // State::Scan (3) // switch, . switch (state) { case State::Idle: // ... break; // ... } for (Direction direction : Direction._values()) character.try_moving_in_direction(direction); BETTER_ENUM(Flags, char, Allocated = 1, InUse = 2, Visited = 4, Unreachable = 8) Flags::_size(); // 4 constexpr functions. You can, for example, write a constexpr function that will calculate the maximum value of an enumeration and make it available at compile time. Even if the values ββof the constants are chosen arbitrarily and are not declared in ascending order.enum.h to the project folder. Try it, maybe it will help you in solving your problems. BETTER_ENUM(Direction, int, North = 1, South = 2, East = 4, West = 8) struct Direction { enum _Enum : int {North = 1, South = 2, East = 4, West = 8}; static const int _values[] = {1, 2, 4, 8}; static const char * const _names[] = {"North", "South", "East", "West"}; int _value; // ..., ... }; _values or _names and return its corresponding value or string to another array._values generated by referring to the constants of the internal enumeration _Enum . This part of the macro looks like this: static const int _values[] = {__VA_ARGS__}; static const int _values[] = {North = 1, South = 2, East = 4, West = 8}; template <typename T> struct _eat { T _value; template <typename Any> _eat& operator =(Any value) { return *this; } // . explicit _eat(T value) : _value(value) { } // T. operator T() const { return _value; } // T. } static const int _values[] = {(_eat<_Enum>)North = 1, (_eat<_Enum>)South = 2, (_eat<_Enum>)East = 4, (_eat<_Enum>)West = 8}; # ) - the preprocessor operator for string translation. It converts __VA_ARGS__ into something like this: static const char * const _names[] = {"North = 1", "South = 2", "East = 4", "West = 8"}; _names in the _names array _names it perceives the characters of spaces and equality as additional line boundaries. So when searching for β North = 1 β, Better Enums will only find β North β.constexpr functions working with static constexpr , due to the constexpr of different compilers. Also, certain difficulties may be associated with the decomposition of as much of the macro as possible into templates in order to speed up compilation (templates do not need to be reparsed during creation, but macro extensions are needed).Source: https://habr.com/ru/post/277757/
All Articles