Skip to main content

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_name uses 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.