Inspect and validate flag enums
When you work with bitmask enums in C++, standard string conversion and validation often fail because they expect a single enumerator value rather than a bitwise combination. magic_enum provides specialized APIs in magic_enum/magic_enum_flags.hpp to format these combinations into delimited strings and validate whether a bitmask consists only of recognized flags.
To use these features, you must opt-in your enum by specializing magic_enum::customize::enum_range and setting is_flags to true.
#include <iostream>
#include <magic_enum/magic_enum.hpp>
#include <magic_enum/magic_enum_flags.hpp>
enum class Color : int { RED = 1, GREEN = 2, BLUE = 4 };
// Enable flag-specific logic for this enum
template <>
struct magic_enum::customize::enum_range<Color> {
static constexpr bool is_flags = true;
};
int main() {
using namespace magic_enum::bitwise_operators; // Enable operator| for scoped enums
auto flags = Color::RED | Color::BLUE;
// 1. Get string representation of combined flags
// Returns "RED|BLUE"
std::cout << magic_enum::enum_flags_name(flags) << std::endl;
// 2. Validate if a value is a valid combination of flags
bool is_valid = magic_enum::enum_flags_contains(flags); // true
bool is_invalid = magic_enum::enum_flags_contains(static_cast<Color>(8)); // false
return 0;
}
Formatting flag combinations
The magic_enum::enum_flags_name function produces a string containing the names of all set flags, separated by a delimiter. By default, it uses the pipe character (|), but you can provide a custom separator as the second argument.
#include <iostream>
#include <string>
#include <magic_enum/magic_enum_flags.hpp>
enum class Permission { Read = 1, Write = 2, Execute = 4 };
template <>
struct magic_enum::customize::enum_range<Permission> {
static constexpr bool is_flags = true;
};
void format_example() {
using namespace magic_enum::bitwise_operators;
auto p = Permission::Read | Permission::Write;
// Default separator: "Read|Write"
std::string default_sep = magic_enum::enum_flags_name(p);
// Custom separator: "Read + Write"
std::string custom_sep = magic_enum::enum_flags_name(p, '+');
}
If the value contains bits that do not correspond to any defined enumerator, magic_enum::enum_flags_name returns an empty string.
Validating flag values
The magic_enum::enum_flags_contains function checks if a value (whether passed as the enum type, the underlying integer, or a string) represents a valid set of flags defined in the enum.
#include <magic_enum/magic_enum_flags.hpp>
#include <string_view>
enum class Animal { Cat = 1, Dog = 2, Bird = 4 };
template <>
struct magic_enum::customize::enum_range<Animal> {
static constexpr bool is_flags = true;
};
void validation_example() {
// Check by enum value
bool v1 = magic_enum::enum_flags_contains(static_cast<Animal>(3)); // true (Cat | Dog)
// Check by underlying integer
bool v2 = magic_enum::enum_flags_contains<Animal>(5); // true (Cat | Bird)
// Check by string representation
bool v3 = magic_enum::enum_flags_contains<Animal>("Cat|Dog"); // true
bool v4 = magic_enum::enum_flags_contains<Animal>("Cat|Fish"); // false
}
Handling the zero value
In magic_enum, a value of 0 is not considered a valid flag combination by the enum_flags_* APIs.
magic_enum::enum_flags_namereturns an empty string for0.magic_enum::enum_flags_containsreturnsfalsefor0.
If your enum requires a "None" or "Empty" state represented by 0, you should handle it separately or use the standard magic_enum::enum_name if you have explicitly defined an enumerator for 0.
Requirements for bitwise operations
To combine scoped enum values using operator| (as seen in the examples above), you must make the magic_enum bitwise operators visible in your scope:
using namespace magic_enum::bitwise_operators;
This enables |, &, ~, ^, |=, &=, and ^= for any enum type, allowing you to treat them as bitfields without manual casting to underlying types.