Skip to main content

Inspect and validate flag enums

To inspect and validate bitwise combinations of enum values in magic_enum, you must first mark the enum as a flags enum by specializing magic_enum::customize::enum_range. Once configured, you can use enum_flags_name to generate string representations of combined flags and enum_flags_contains to verify if a specific value, integer, or string represents a valid set of flags.

Configure and Format Flag Enums

To enable flag-specific logic, specialize magic_enum::customize::enum_range for your enum type and set is_flags = true. This allows enum_flags_name to decompose a bitwise-ORed value into its constituent names separated by a delimiter (defaulting to |).

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

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

// Mark the enum as a flags 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 enums

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

// Get string representation: "RED|BLUE"
auto name = magic_enum::enum_flags_name(c);
if (!name.empty()) {
std::cout << "Flags: " << name << std::endl;
}

// Returns empty string for values containing undefined bits
auto invalid = magic_enum::enum_flags_name(static_cast<Color>(8));
std::cout << "Invalid is empty: " << std::boolalpha << invalid.empty() << std::endl;

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 returns false if the value contains any bits that are not part of a named enumerator, or if the value is 0 (as 0 is not considered a flag).

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

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

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

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

// Validate enum values
bool v1 = magic_enum::enum_flags_contains(Permissions::Read | Permissions::Write); // true
bool v2 = magic_enum::enum_flags_contains(static_cast<Permissions>(10)); // false (8 is missing)

// Validate integer values (requires explicit template argument)
bool v3 = magic_enum::enum_flags_contains<Permissions>(3); // true (1 | 2)
bool v4 = magic_enum::enum_flags_contains<Permissions>(0); // false

std::cout << "Valid (3): " << v3 << ", Valid (0): " << v4 << std::endl;

return 0;
}

Validate String Representations

You can also validate whether a string correctly represents a combination of flags. This is useful for parsing user input or configuration files. Like the integer overload, the string overload of enum_flags_contains requires an explicit template argument.

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

enum class Status { Active = 1, Pending = 2, Deleted = 4 };

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

int main() {
// Standard validation
bool s1 = magic_enum::enum_flags_contains<Status>("Active|Pending"); // true
bool s2 = magic_enum::enum_flags_contains<Status>("Active|Unknown"); // false

// Case-insensitive validation using a custom predicate
auto ignore_case = [](char lhs, char rhs) {
return std::tolower(static_cast<unsigned char>(lhs)) == std::tolower(static_cast<unsigned char>(rhs));
};

bool s3 = magic_enum::enum_flags_contains<Status>("active|PENDING", ignore_case); // true

std::cout << "Valid string: " << s1 << ", Case-insensitive: " << s3 << std::endl;

return 0;
}