Skip to content

Instantly share code, notes, and snippets.

@dscharrer
Created December 11, 2012 23:24
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dscharrer/371337722bb56c45b008 to your computer and use it in GitHub Desktop.
Save dscharrer/371337722bb56c45b008 to your computer and use it in GitHub Desktop.
#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