Modern Enum is an enum library intended as a replacement for C++ enum classes.
It introduces two important features:
- Reflection: the program can access enum size and element names, enabling logging of useful debug messages and serialization.
- Type-safe flags: you can manipulate sets of flags in a robust, type-safe way, instead of casting to an unsigned integer.
Modern Enum aims to be efficient and easy to work with:
- Easy to integrate: drop-in header-only library.
- Compile-time: the library is 100% constexpr.
- Ease of debug: human-readable Visual Studio debugging experience.
To quickly get started:
- Build
modern_enum.sln
: compiles the project and runs the unit-tests intest.cpp
; - Run
modern_enum.sln
: executes the sample code inmain.cpp
.
To integrate the library in your project:
- Include
modern_enum.h
; - Include
modern_enum.natvis
(if using VS debugger); - Set C++ standard to c++17 or later;
- Set
/Zc=preprocessor
flag (on MSVC).
MODERN_ENUM(
Week,
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
);
constexpr auto name = Week::GetName(); // "Week"
constexpr auto count = Week::GetCount(); // 7
constexpr Week monday = Week::Monday;
constexpr Week tuesday = Week::FromIndex(1);
constexpr Week wednesday = Week::FromString("Wednesday");
constexpr auto index = Week::Monday.index(); // 0
constexpr auto name = Week::Monday.toString(); // "Monday"
for (Week m : Week::GetElements()) {}
switch (Week::Wednesday) {
case Week::Monday:
case Week::Tuesday:
...
}
constexpr Week::Set weekend = Week::Saturday | Week::Sunday;
constexpr Week::Set monday = Week::Monday;
constexpr Week::Set weekdays = ~weekend;
constexpr Week::Set week = weekdays | weekend;
Week::Set days = Week::Monday;
days |= Week::Saturday;
days ^= weekdays;
constexpr auto count = weekdays.count(); // 5
constexpr auto contains = weekdays.contains(monday); // true
constexpr auto none = weekdays.none(); // false
constexpr auto any = weekdays.any(); // true
constexpr auto all = weekdays.all(); // false
Currently, it is not possible to assign custom values to enum elements:
MODERN_ENUM(
Example,
NoValue,
Value = 5 // not supported
);
This is an intentional choice, because it is not possible to support such feature without degrading the quality of the API. As an example, this is the tradeoff used by the popular Better Enums library to support custom values:
// Static members are NOT of type "Week".
// Internal raw-enum type is leaking
auto mondayInternalType = Week::Monday;
mondayInternalType.toString(); // does not compile
// "+" operator required to convert internal type
Week monday = +mondayInternalType;
(+mondayInternalType).toString();
There is another way to support custom values without exposing internal types to the user, but at the cost of a more complex enum definition. I could consider adding this as an optional extension of the Modern Enum API:
MODERN_ENUM_WITH_CUSTOM_VALUES(
Example,
WITHOUT_VALUE(NoValue),
WITH_VALUE(Value, 5)
);