#include <type_traits> #include <iostream> #define ENUM_FLAG(F) (1 << (F)) #define ENUM_FLAGS(F) \ enum class Flags : unsigned; \ inline F operator~ (F a) { using U = std::underlying_type<F>::type; return (F)(~(U)a ); } \ inline F operator| (F a, F b) { using U = std::underlying_type<F>::type; return (F)( (U)a | (U)b); } \ inline F operator& (F a, F b) { using U = std::underlying_type<F>::type; return (F)( (U)a & (U)b); } \ inline F operator^ (F a, F b) { using U = std::underlying_type<F>::type; return (F)( (U)a ^ (U)b); } \ inline F& operator|=(F& a, F b) { return a = a | b; } \ inline F& operator&=(F& a, F b) { return a = a & b; } \ inline F& operator^=(F& a, F b) { return a = a ^ b; } \ template<typename Func> \ inline void for_enum_flags(F f, Func && func) \ { \ using U = std::underlying_type<F>::type; \ auto u = (U)f; \ for (auto flag = U{}; (flag = u & -u); u ^= flag) \ func((F)flag); \ } \ enum class Flags : unsigned // static_assert(std::is_unsigned<std::underlying_type<F>::type>::value, "Flag enum F must be unsigned"); ENUM_FLAGS(Flags) { one = ENUM_FLAG(0), two = ENUM_FLAG(1), three = ENUM_FLAG(2), }; int main() { auto flags = Flags{Flags::one | Flags::three}; flags |= Flags::two; flags &= ~Flags::three; for_enum_flags(flags, [](Flags flag) { switch (flag) { #define FLAG_PRINT(FLAG) case Flags::FLAG: std::cout << #FLAG << std::endl; break; FLAG_PRINT(one) FLAG_PRINT(two) FLAG_PRINT(three) #undef FLAG_PRINT default: std::cout << "UNKNOWN" << std::endl; } }); }