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
0is not considered a valid flag.enum_flags_namereturns an empty string for0, andenum_flags_containsreturnsfalse. - Bitwise Operators: To use operators like
|,&,~, or^directly on scoped enums, you must includeusing 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_namewill return an empty string andenum_flags_containswill returnfalse. - Header Requirements: Ensure you include
magic_enum/magic_enum_flags.hppto access these specific flag utilities.