Skip to main content

Inspect and validate flag enums

When you work with bitmask enums in magic_enum, you can format combinations of flags into strings or validate whether a specific bitmask consists only of defined flags. These operations require the enum to be explicitly registered as a flag type.

Register an enum as flags

To use flag-specific APIs like enum_flags_name and enum_flags_contains, you must specialize magic_enum::customize::enum_range for your enum type and set is_flags to true.

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

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

// Register Color as a flag enum
template <>
struct magic_enum::customize::enum_range<Color> {
static constexpr bool is_flags = true;
};

int main() {
using namespace magic_enum::bitwise_operators;

Color c = Color::RED | Color::BLUE;

// enum_flags_name returns a string with flags separated by '|'
std::cout << magic_enum::enum_flags_name(c) << std::endl; // "RED|BLUE"

return 0;
}

Format flag combinations to strings

The enum_flags_name function converts a bitmask value into a string representation where each defined flag is separated by a delimiter (defaulting to |). If the value contains bits that do not correspond to any defined enum member, or if the value is 0, the function returns an empty string.

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

enum class Status : int {
Active = 1 << 0,
Pending = 1 << 1,
Verified = 1 << 2
};

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

int main() {
using namespace magic_enum::bitwise_operators;

// Valid combination
auto name1 = magic_enum::enum_flags_name(Status::Active | Status::Verified);
std::cout << name1 << std::endl; // "Active|Verified"

// Value 0 returns an empty string
auto name2 = magic_enum::enum_flags_name(static_cast<Status>(0));
std::cout << "Empty: " << name2.empty() << std::endl; // Empty: 1

// Undefined bits return an empty string
auto name3 = magic_enum::enum_flags_name(static_cast<Status>(1 | 8));
std::cout << "Empty: " << name3.empty() << std::endl; // Empty: 1

return 0;
}

Validate flag combinations

The enum_flags_contains function checks if a value is a valid combination of the flags defined in the enum. It supports checking enum values, underlying integers, and string representations. When passing an integer or a string, you must explicitly provide the enum type as a template argument.

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

enum class Permission { Read = 1, Write = 2, Execute = 4 };

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

int main() {
using namespace magic_enum::bitwise_operators;

// Check enum value
bool v1 = magic_enum::enum_flags_contains(Permission::Read | Permission::Write); // true

// Check underlying integer (requires explicit template argument)
bool v2 = magic_enum::enum_flags_contains<Permission>(3); // true (1 | 2)
bool v3 = magic_enum::enum_flags_contains<Permission>(8); // false (undefined)

// Check string representation (requires explicit template argument)
bool v4 = magic_enum::enum_flags_contains<Permission>("Read|Write"); // true

// Case-insensitive check using a custom predicate
bool v5 = magic_enum::enum_flags_contains<Permission>("read|WRITE", [](char lhs, char rhs) {
return std::tolower(static_cast<unsigned char>(lhs)) == std::tolower(static_cast<unsigned char>(rhs));
}); // true

std::cout << std::boolalpha << v1 << " " << v2 << " " << v3 << " " << v4 << " " << v5 << std::endl;

return 0;
}

Troubleshooting flag validation

  • Value 0: By default, magic_enum does not consider 0 a valid flag value unless it is explicitly defined in the enum. Both enum_flags_name and enum_flags_contains will treat 0 as invalid/empty.
  • Template Deduction: enum_flags_contains cannot deduce the enum type from an integer or a string. You must call it as enum_flags_contains<MyEnum>(value).
  • Registration: If you forget to set is_flags = true in magic_enum::customize::enum_range, these functions will not behave as expected for bitwise combinations (e.g., enum_flags_name will return an empty string for combined bits).
  • Bitwise Operators: To use the | operator with scoped enums, ensure magic_enum::bitwise_operators is visible in your scope.