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_enumdoes not consider0a valid flag value unless it is explicitly defined in the enum. Bothenum_flags_nameandenum_flags_containswill treat0as invalid/empty. - Template Deduction:
enum_flags_containscannot deduce the enum type from an integer or a string. You must call it asenum_flags_contains<MyEnum>(value). - Registration: If you forget to set
is_flags = trueinmagic_enum::customize::enum_range, these functions will not behave as expected for bitwise combinations (e.g.,enum_flags_namewill return an empty string for combined bits). - Bitwise Operators: To use the
|operator with scoped enums, ensuremagic_enum::bitwise_operatorsis visible in your scope.