Skip to main content

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));
}