Skip to main content

Inspect and validate flag enums

To inspect and validate bitwise combinations of enum values in magic_enum, you must first opt-in to flag support by specializing magic_enum::customize::enum_range. Once enabled, you can use enum_flags_name to generate string representations of combined flags and enum_flags_contains to verify if a value or string represents a valid set of defined flags.

Enabling Flag Support

By default, magic_enum treats enums as a sequence of distinct values. To enable bitwise logic and flag-aware string formatting, specialize magic_enum::customize::enum_range for your enum type and set is_flags to true.

#include <iostream>
#include <cstdint>
#include <magic_enum/magic_enum_flags.hpp>

enum class AnimalFlags : std::uint64_t {
HasClaws = 1 << 10,
CanFly = 1 << 20,
EatsFish = 1 << 30,
Endangered = std::uint64_t{1} << 40
};

// Specialize is_flags to enable flag-specific APIs
template <>
struct magic_enum::customize::enum_range<AnimalFlags> {
static constexpr bool is_flags = true;
};

int main() {
// Bring bitwise operators into scope to use | on enum values
using namespace magic_enum::bitwise_operators;

AnimalFlags flags = AnimalFlags::HasClaws | AnimalFlags::CanFly;

// enum_flags_name returns "HasClaws|CanFly"
std::cout << magic_enum::enum_flags_name(flags) << std::endl;

return 0;
}

Formatting Flag Names

The magic_enum::enum_flags_name function produces a string containing the names of all set flags, separated by a delimiter (defaulting to |).

#include <iostream>
#include <magic_enum/magic_enum_flags.hpp>

enum class Color : int { RED = 1, GREEN = 2, BLUE = 4 };

template <>
struct magic_enum::customize::enum_range<Color> {
static constexpr bool is_flags = true;
};

void print_flags(Color c) {
using namespace magic_enum::bitwise_operators;

// Use custom separator if desired
auto name = magic_enum::enum_flags_name(c, '+');

if (!name.empty()) {
std::cout << "Flags: " << name << std::endl;
} else {
std::cout << "Invalid or empty flags" << std::endl;
}
}

Validating Flag Combinations

Use magic_enum::enum_flags_contains to check if a value, integer, or string represents a valid combination of the flags defined in your enum. A combination is valid only if every bit set in the input corresponds to a named flag in the enum definition.

#include <cassert>
#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;
};

void validate() {
using namespace magic_enum::bitwise_operators;

// Validate enum values
assert(magic_enum::enum_flags_contains(Permission::Read | Permission::Write));

// Validate underlying integers
assert(magic_enum::enum_flags_contains<Permission>(3)); // 1 | 2 (Read | Write)
assert(!magic_enum::enum_flags_contains<Permission>(8)); // No flag for bit 3 (value 8)

// Validate string representations
assert(magic_enum::enum_flags_contains<Permission>("Read|Write"));
assert(!magic_enum::enum_flags_contains<Permission>("Read|Delete"));
}

Troubleshooting and Constraints

  • Zero Values: In magic_enum, a value of 0 is not considered a valid flag. enum_flags_name returns an empty string for 0, and enum_flags_contains returns false.
  • Bitwise Operators: To use operators like |, &, ~, or ^ directly on scoped enums, you must include using namespace magic_enum::bitwise_operators; in the relevant scope.
  • Invalid Bits: If a value contains any bit that is not explicitly defined as a flag in the enum, enum_flags_name will return an empty string and enum_flags_contains will return false.
  • Header Requirements: Ensure you include magic_enum/magic_enum_flags.hpp to access these specific flag utilities.