Skip to main content

Inspect and validate flag enums

To inspect and validate flag enums in magic_enum, you must first enable flag support by specializing the magic_enum::customize::enum_range trait. Once enabled, you can use enum_flags_name to generate string representations of combined flags and enum_flags_contains to verify if a value represents a valid set of flags.

Enable Flag Support

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

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

// Required: Define the enum as a flag set
template <>
struct magic_enum::customize::enum_range<AnimalFlags> {
static constexpr bool is_flags = true;
};

Combine Flags with Bitwise Operators

To use standard bitwise operators (|, &, ^, ~) with scoped enums, bring the magic_enum::bitwise_operators namespace into scope. This allows you to combine flags before passing them to inspection functions.

using namespace magic_enum::bitwise_operators;

// Combine flags using operator|
AnimalFlags flags = AnimalFlags::HasClaws | AnimalFlags::CanFly;

Format Flag Names

The magic_enum::enum_flags_name function returns a string containing the names of all set flags, joined by a separator (default is '|'). If the value contains bits that do not correspond to any named flag, the function returns an empty string.

// Default separator '|'
// Output: "HasClaws|CanFly"
std::cout << magic_enum::enum_flags_name(flags) << std::endl;

// Custom separator ','
// Output: "HasClaws,CanFly"
std::cout << magic_enum::enum_flags_name(flags, ',') << std::endl;

Validate Flag Values

Use magic_enum::enum_flags_contains to check if a value (enum, integer, or string) is a valid combination of the defined flags. A value is considered valid if it is non-zero and composed entirely of bits defined in the enum.

// Check enum values
bool valid = magic_enum::enum_flags_contains(AnimalFlags::HasClaws | AnimalFlags::CanFly); // true
bool invalid = magic_enum::enum_flags_contains(static_cast<AnimalFlags>(0)); // false (0 is not a flag)

// Check underlying integer values
bool is_valid_int = magic_enum::enum_flags_contains<AnimalFlags>(1024); // true (HasClaws)
bool is_invalid_int = magic_enum::enum_flags_contains<AnimalFlags>(1); // false (Undefined bit)

// Check string representations
bool is_valid_str = magic_enum::enum_flags_contains<AnimalFlags>("HasClaws|CanFly"); // true
bool is_invalid_str = magic_enum::enum_flags_contains<AnimalFlags>("HasClaws,CanFly"); // false (wrong separator)

Test for Specific Flags

While enum_flags_contains validates the entire set, magic_enum::enum_flags_test and magic_enum::enum_flags_test_any allow you to check for specific bits within a flag set.

AnimalFlags my_animal = AnimalFlags::HasClaws | AnimalFlags::EatsFish;

// Check if ALL specified flags are set
bool has_both = magic_enum::enum_flags_test(my_animal, AnimalFlags::HasClaws | AnimalFlags::EatsFish); // true

// Check if ANY specified flags are set
bool flies_or_swims = magic_enum::enum_flags_test_any(my_animal, AnimalFlags::CanFly | AnimalFlags::EatsFish); // true

Troubleshooting

  • Empty String Output: If enum_flags_name returns an empty string, ensure that the value you passed does not contain "garbage" bits (bits not defined in the enum) and that the value is not 0.
  • Compilation Errors on |: If you cannot use bitwise operators, ensure you have included using namespace magic_enum::bitwise_operators; in the local scope.
  • Validation Fails for 0: enum_flags_contains and enum_flags_test return false for a value of 0 because 0 is technically the absence of all flags.