-
-
Save dscharrer/371337722bb56c45b008 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstddef> | |
#include <bitset> | |
#include <utility> | |
#include <type_traits> | |
template <typename Enum, std::size_t Bits = std::size_t(Enum::flags_count_)> | |
class flags { | |
public: | |
typedef Enum enum_type; | |
static constexpr std::size_t bits = Bits; | |
private: | |
class internal; | |
typedef internal ** zero; | |
typedef std::bitset<bits> type; | |
type _flags; | |
typedef typename std::underlying_type<enum_type>::type int_type; | |
flags(type flag) : _flags(flag) { } | |
public: | |
flags(enum_type flag) : _flags(type().set(int_type(flag))) { } | |
flags(zero = 0) : _flags() { } | |
flags(const flags & o) : _flags(o._flags) { } | |
bool has(enum_type flag) const { return _flags.test(int_type(flag)); } | |
bool has_all(flags o) const { return (_flags & o._flags) == o._flags; } | |
explicit operator bool() const { return _flags.any(); } | |
bool operator!() const { return _flags.none(); } | |
flags operator~() const { return flags(~_flags); } | |
flags operator&(flags o) const { return flags(_flags & o._flags); } | |
flags operator|(flags o) const { return flags(_flags | o._flags); } | |
flags operator^(flags o) const { return flags(_flags ^ o._flags); } | |
flags & operator&=(const flags & o) { return (_flags &= o._flags, *this); } | |
flags & operator|=(flags o) { return (_flags |= o._flags, *this); } | |
flags & operator^=(flags o) { return (_flags ^= o._flags, *this); } | |
flags operator&(enum_type flag) const { return operator&(flags(flag)); } | |
flags operator|(enum_type flag) const { return operator|(flags(flag)); } | |
flags operator^(enum_type flag) const { return operator^(flags(flag)); } | |
flags & operator&=(enum_type flag) { return operator&=(flags(flag)); } | |
flags & operator|=(enum_type flag) { return operator|=(flags(flag)); } | |
flags & operator^=(enum_type flag) { return operator^=(flag); } | |
flags & operator=(flags o) { return (_flags = o._flags, *this); } | |
static flags all() { return flags(type().flip()); } | |
}; | |
template <typename Enum, size_t Bits> | |
flags<Enum, Bits> operator|(Enum a, flags<Enum, Bits> b) { return b | a; } | |
template <typename Enum, size_t Bits> | |
flags<Enum, Bits> operator&(Enum a, flags<Enum, Bits> b) { return b & a; } | |
template <typename Enum, size_t Bits> | |
flags<Enum, Bits> operator^(Enum a, flags<Enum, Bits> b) { return b ^ a; } | |
template <typename Enum> | |
flags<Enum> operator|(Enum a, Enum b) { return flags<Enum>(a) | b; } | |
template <typename Enum> | |
flags<Enum> operator&(Enum a, Enum b) { return flags<Enum>(a) & b; } | |
template <typename Enum> | |
flags<Enum> operator^(Enum a, Enum b) { return flags<Enum>(a) ^ b; } | |
// ------------------------------------------------- | |
enum class flag_a { | |
v1, | |
v2, | |
flags_count_ | |
}; | |
typedef ::flags<flag_a> flags_a; | |
enum class flag_b { | |
v1, | |
v2, | |
flags_count_ | |
}; | |
typedef ::flags<flag_b> flags_b; | |
int main() { | |
flags_a a = 0; // ok | |
// flags_a b = 42; // error | |
flags_a c = flag_a::v1 | flag_a::v2; // ok | |
// flags_a d = flag_a::v1 | flag_b::v2; // error | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment