Inspect and validate flag enums
When you work with bitwise flag enums in C++, standard string conversion and validation functions often fail to handle combined values (e.g., Color::Red | Color::Blue). magic_enum provides specialized APIs in magic_enum/magic_enum_flags.hpp to format these combinations into delimited strings and validate whether a bitset represents a valid set of flags.
Enable Flag Support
To use flag-specific functions, you must explicitly mark your enum as a flag type by specializing magic_enum::customize::enum_range. This tells magic_enum to treat the enum as a bitmask rather than a sequential list of values.
#include <magic_enum/magic_enum_flags.hpp>
enum class Color { RED = 1, GREEN = 2, BLUE = 4 };
// Enable flag support for Color
template <>
struct magic_enum::customize::enum_range<Color> {
static constexpr bool is_flags = true;
};
Format Flag Combinations to Strings
The magic_enum::enum_flags_name function converts an enum value (or a bitwise combination of values) into a string. If multiple flags are set, it concatenates their names using a separator (defaulting to |).
To combine scoped enum values using the | operator, you must make magic_enum::bitwise_operators visible.
#include <iostream>
#include <magic_enum/magic_enum_flags.hpp>
using namespace magic_enum::bitwise_operators; // Enables operator| for enums
void print_color(Color c) {
// Returns a string like "RED|BLUE"
std::cout << magic_enum::enum_flags_name(c) << std::endl;
}
int main() {
print_color(Color::RED | Color::BLUE); // Output: RED|BLUE
return 0;
}
Validate Flag Values
The magic_enum::enum_flags_contains function checks if a value represents a valid flag or a valid combination of flags defined in the enum. It supports checking raw enum values, underlying integers, or string representations.
Validate Enum and Integer Values
A value is considered valid if every bit set in the value corresponds to a named flag in the enum.
#include <magic_enum/magic_enum_flags.hpp>
#include <cassert>
using namespace magic_enum::bitwise_operators;
void validate_flags() {
// Valid combinations
assert(magic_enum::enum_flags_contains(Color::RED | Color::GREEN));
assert(magic_enum::enum_flags_contains<Color>(1 | 4)); // RED | BLUE
// Invalid values (bits that don't exist in the enum)
assert(!magic_enum::enum_flags_contains<Color>(8));
assert(!magic_enum::enum_flags_contains<Color>(1 | 8));
}
Validate String Representations
You can also validate if a string correctly names a set of flags. This is useful for parsing configuration or user input.
#include <magic_enum/magic_enum_flags.hpp>
#include <cctype>
#include <cassert>
void validate_strings() {
// Basic validation
assert(magic_enum::magic_enum::enum_flags_contains<Color>("RED|GREEN"));
// Case-insensitive validation using a custom predicate
auto case_insensitive = [](char lhs, char rhs) {
return std::tolower(static_cast<unsigned char>(lhs)) == std::tolower(static_cast<unsigned char>(rhs));
};
assert(magic_enum::enum_flags_contains<Color>("red|BLUE", case_insensitive));
}
Test for Specific Flags
While enum_flags_contains validates the entire bitset, magic_enum::enum_flags_test checks if a specific flag is set within a bitset.
#include <magic_enum/magic_enum_flags.hpp>
#include <cassert>
using namespace magic_enum::bitwise_operators;
void test_bits() {
Color c = Color::RED | Color::BLUE;
assert(magic_enum::enum_flags_test(c, Color::RED));
assert(!magic_enum::enum_flags_test(c, Color::GREEN));
}
Troubleshooting and Constraints
- Zero Values: In magic_enum,
0is not considered a valid flag.magic_enum::enum_flags_namereturns an empty string for0, andmagic_enum::enum_flags_containsreturnsfalse. - Missing Specialization: If you forget to set
is_flags = trueinmagic_enum::customize::enum_range, theenum_flags_*functions will not correctly identify combined bitmasks and may return empty results or fail to compile. - Operator Overloading: Scoped enums (
enum class) do not support bitwise operators by default. You must includeusing namespace magic_enum::bitwise_operators;in the scope where you perform the OR operation.