Inspect and validate flag enums
To use an enumeration as a set of bitwise flags in magic_enum, you must explicitly enable flag support by specializing the magic_enum::customize::enum_range struct. Once enabled, you can use enum_flags_name to format combined flag values and enum_flags_contains to validate whether a specific value or string represents a valid combination of flags.
Enabling Flag Support
By default, magic_enum treats enumerations as a collection of distinct values. To enable bitwise logic and flag-aware string formatting, set is_flags = true in a specialization of magic_enum::customize::enum_range.
#include <cstdint>
#include <magic_enum/magic_enum.hpp>
enum class Color : std::uint32_t {
RED = 1 << 0,
GREEN = 1 << 1,
BLUE = 1 << 2
};
// Enable flag support for Color
template <>
struct magic_enum::customize::enum_range<Color> {
static constexpr bool is_flags = true;
};
Using Bitwise Operators
To combine scoped enum values using bitwise operators like |, &, and ~, bring the magic_enum::bitwise_operators namespace into scope.
#include <iostream>
#include <magic_enum/magic_enum.hpp>
void combine_flags() {
using namespace magic_enum::bitwise_operators;
// Combine flags using operator|
Color yellow = Color::RED | Color::GREEN;
// Check for specific flag using operator&
if ((yellow & Color::RED) == Color::RED) {
// ...
}
}
Formatting Flag Names
The magic_enum::enum_flags_name function returns a string representation of a flag combination. If multiple flags are set, it concatenates their names using a separator (defaulting to |).
#include <iostream>
#include <string>
#include <magic_enum/magic_enum.hpp>
void print_flag_names() {
using namespace magic_enum::bitwise_operators;
Color combined = Color::RED | Color::GREEN;
// Returns "RED|GREEN"
std::string name = magic_enum::enum_flags_name(combined);
std::cout << name << std::endl;
// Custom separator
std::string custom_name = magic_enum::enum_flags_name(combined, '+');
std::cout << custom_name << std::endl; // "RED+GREEN"
}
Note: If a value contains bits that do not correspond to any defined flag in the enum, enum_flags_name returns an empty string. A value of 0 also results in an empty string.
Validating Flag Combinations
The magic_enum::enum_flags_contains function validates if a value is a valid combination of the flags defined in the enum. It supports validation via the enum type, the underlying integer type, or a string.
#include <cassert>
#include <magic_enum/magic_enum.hpp>
void validate_flags() {
using namespace magic_enum::bitwise_operators;
// Validate using enum value
assert(magic_enum::enum_flags_contains(Color::RED | Color::GREEN));
assert(!magic_enum::enum_flags_contains(static_cast<Color>(8))); // 8 is not a valid flag
// Validate using underlying integer
assert(magic_enum::enum_flags_contains<Color>(1 | 2)); // RED | GREEN
assert(!magic_enum::enum_flags_contains<Color>(0)); // 0 is not considered a valid flag
// Validate using string representation
assert(magic_enum::enum_flags_contains<Color>("RED|GREEN"));
assert(magic_enum::enum_flags_contains<Color>("GREEN|RED")); // Order does not matter
assert(!magic_enum::enum_flags_contains<Color>("RED|PURPLE"));
}
Case-Insensitive Validation
You can perform case-insensitive validation by passing a custom binary predicate to enum_flags_contains.
#include <cassert>
#include <cctype>
#include <magic_enum/magic_enum.hpp>
void case_insensitive_validation() {
auto predicate = [](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|green", predicate));
}