Inspect and validate flag enums
To inspect and validate flag enums in magic_enum, you must first enable flag support for your enum type and then use the specialized flag APIs. The magic_enum::enum_flags_name function generates a delimited string of active flags, while magic_enum::enum_flags_contains verifies if a specific combination of bits or names corresponds to valid flags defined in the enum.
Enable Flag Support
By default, magic_enum treats enums as a sequence of distinct values. To use flag-based logic, you must specialize magic_enum::customize::enum_range for your enum type and set is_flags to true. You should also make magic_enum::bitwise_operators visible to use the | operator with scoped enums.
#include <iostream>
#include <cstdint>
#include <magic_enum/magic_enum_flags.hpp>
enum class Settings : std::uint32_t {
None = 0,
HighQuality = 1 << 0,
HardwareAccel = 1 << 1,
LoggingEnabled = 1 << 2
};
// Enable flag support for the Settings enum
template <>
struct magic_enum::customize::enum_range<Settings> {
static constexpr bool is_flags = true;
};
int main() {
using namespace magic_enum::bitwise_operators;
Settings s = Settings::HighQuality | Settings::LoggingEnabled;
// magic_enum::enum_flags_name returns a string of names separated by '|'
// Output: HighQuality|LoggingEnabled
std::cout << magic_enum::enum_flags_name(s) << std::endl;
return 0;
}
Validate Flag Combinations
You can validate whether a value represents a valid combination of flags using magic_enum::enum_flags_contains. This function supports enum values, raw integers, and strings. When passing an integer or a string, you must explicitly provide the enum type as a template argument.
#include <iostream>
#include <magic_enum/magic_enum_flags.hpp>
enum class Color : int {
Red = 1 << 0,
Green = 1 << 1,
Blue = 1 << 2
};
template <>
struct magic_enum::customize::enum_range<Color> {
static constexpr bool is_flags = true;
};
int main() {
using namespace magic_enum::bitwise_operators;
// Validate using the enum type directly
bool valid_enum = magic_enum::enum_flags_contains(Color::Red | Color::Green); // true
// Validate using an integer (requires explicit template argument)
bool valid_int = magic_enum::enum_flags_contains<Color>(3); // true (Red | Green)
bool invalid_int = magic_enum::enum_flags_contains<Color>(10); // false (contains undefined bits)
// Validate using a string (requires explicit template argument)
bool valid_str = magic_enum::enum_flags_contains<Color>("Red|Blue"); // true
bool invalid_str = magic_enum::enum_flags_contains<Color>("Red|Yellow"); // false
std::cout << std::boolalpha
<< "Valid Enum: " << valid_enum << "\n"
<< "Valid Int: " << valid_int << "\n"
<< "Invalid Int: " << invalid_int << "\n"
<< "Valid Str: " << valid_str << "\n"
<< "Invalid Str: " << invalid_str << std::endl;
return 0;
}
Handling Zero and Invalid Values
In magic_enum, a value of 0 is not considered a valid flag combination by the enum_flags_* APIs unless it is explicitly named in the enum and included in the reflected range. If a value contains bits that do not correspond to any defined flag, or if the string contains unknown names, the functions will return false or an empty string.
#include <iostream>
#include <string>
#include <magic_enum/magic_enum_flags.hpp>
enum class Permission : int {
Read = 1,
Write = 2,
Execute = 4
};
template <>
struct magic_enum::customize::enum_range<Permission> {
static constexpr bool is_flags = true;
};
int main() {
// enum_flags_name returns an empty string for 0 or invalid combinations
std::string empty = magic_enum::enum_flags_name(static_cast<Permission>(0));
if (empty.empty()) {
std::cout << "Value 0 is not a valid flag combination." << std::endl;
}
// enum_flags_contains returns false for 0
bool has_zero = magic_enum::enum_flags_contains<Permission>(0); // false
// enum_flags_contains returns false for values with undefined bits (e.g., 8)
bool has_invalid = magic_enum::enum_flags_contains<Permission>(9); // false (1 | 8)
std::cout << std::boolalpha
<< "Contains 0: " << has_zero << "\n"
<< "Contains 9: " << has_invalid << std::endl;
return 0;
}
Usage Notes
- Header: Always include
<magic_enum/magic_enum_flags.hpp>to access flag-specific functions. - Bitwise Operators: Scoped enums require
using namespace magic_enum::bitwise_operators;to use|,&,~, and^. - String Formatting:
magic_enum::enum_flags_nameuses the|character as the default separator. You can provide a custom separator as a second argument, for example:magic_enum::enum_flags_name(value, ','). - Reflection Limits: The flags must fall within the range defined by
magic_enum::customize::enum_range. If a flag's bit position is outside the reflected range, it will not be detected.