secret
Last active

  • Download Gist
gistfile1.cpp
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
 
#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
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.