Inspect and validate flag enums
To inspect and validate bitmask-style enums in magic_enum, you must explicitly mark the enum as a flag type and use the specialized flag APIs. This allows you to format combinations of flags into strings and verify if a specific bitmask represents a valid set of defined enumerators.
Enable Flag Support
Before using flag-specific functions, you must specialize magic_enum::customize::enum_range for your enum type and set is_flags to true. This tells magic_enum to treat the enum as a bitmask rather than a simple list of values.
#include <magic_enum/magic_enum.hpp>
#include <magic_enum/magic_enum_flags.hpp>
#include <iostream>
enum class Color { RED = 1, GREEN = 2, BLUE = 4 };
// Mandatory specialization to enable flag support
template <>
struct magic_enum::customize::enum_range<Color> {
static constexpr bool is_flags = true;
};
int main() {
// Use bitwise operators by bringing them into scope
using namespace magic_enum::bitwise_operators;
Color c = Color::RED | Color::BLUE;
// magic_enum::enum_flags_name returns "RED|BLUE"
std::cout << magic_enum::enum_flags_name(c) << std::endl;
return 0;
}
Format Flag Combinations to Strings
The magic_enum::enum_flags_name function converts a bitmask value into a string containing the names of all set flags, separated by a pipe (|) by default.
- Order of Names: The resulting string lists flag names according to their declaration order in the enum, not the order in which they were combined.
- Invalid Values: If the input contains bits that do not correspond to any defined enumerator, or if the value is
0, the function returns an empty string.
#include <magic_enum/magic_enum_flags.hpp>
#include <cassert>
#include <string>
enum class Directions { Left = 1, Down = 2, Up = 4, Right = 8 };
template <>
struct magic_enum::customize::enum_range<Directions> {
static constexpr bool is_flags = true;
};
void example() {
using namespace magic_enum::bitwise_operators;
// Normal combination
auto d1 = Directions::Right | Directions::Left;
assert(magic_enum::enum_flags_name(d1) == "Left|Right");
// Custom separator
auto d2 = Directions::Up | Directions::Down;
assert(magic_enum::enum_flags_name(d2, '+') == "Down+Up");
// Invalid value (bit 16 is not defined)
auto invalid = static_cast<Directions>(16);
assert(magic_enum::enum_flags_name(invalid).empty());
// Zero value (not considered a valid flag combination)
assert(magic_enum::enum_flags_name(static_cast<Directions>(0)).empty());
}
Validate Flag Values
The magic_enum::enum_flags_contains function checks if a value represents a valid combination of defined flags. It supports validation from enum types, underlying integers, and strings.
Validate by Enum Value or Integer
This is useful for checking if a bitmask contains only bits that are explicitly defined in the enum.
#include <magic_enum/magic_enum_flags.hpp>
#include <cassert>
enum class Permission { Read = 1, Write = 2, Execute = 4 };
template <>
struct magic_enum::customize::enum_range<Permission> {
static constexpr bool is_flags = true;
};
void validate_bits() {
using namespace magic_enum::bitwise_operators;
// Valid combination
assert(magic_enum::enum_flags_contains(Permission::Read | Permission::Write));
// Valid integer representation (1 | 4 = 5)
assert(magic_enum::enum_flags_contains<Permission>(5));
// Invalid: contains bit 8 which is not defined
assert(!magic_enum::enum_flags_contains<Permission>(Permission::Read | static_cast<Permission>(8)));
// Invalid: 0 is not a valid flag combination
assert(!magic_enum::enum_flags_contains(static_cast<Permission>(0)));
}
Validate by String
You can verify if a string correctly names one or more flags separated by |.
#include <magic_enum/magic_enum_flags.hpp>
#include <cassert>
void validate_string() {
// Valid string (order does not matter for validation)
assert(magic_enum::enum_flags_contains<Permission>("Write|Read"));
// Invalid: contains an unknown name
assert(!magic_enum::enum_flags_contains<Permission>("Read|Delete"));
// Invalid: empty string
assert(!magic_enum::enum_flags_contains<Permission>(""));
}
Troubleshooting
- Bitwise Operators: If you get compilation errors when using
|or&with scoped enums, ensure you have addedusing namespace magic_enum::bitwise_operators;in the local scope. - Empty Strings: If
enum_flags_namereturns an empty string for a value you expect to be valid, verify that theenum_rangespecialization is present and that the value does not include any undefined bits. - Zero Values: magic_enum treats
0as an invalid flag value.enum_flags_containswill returnfalsefor0, andenum_flags_namewill return an empty string. If your enum uses0for a "None" state, you must handle it separately from the magic_enum flag APIs.