Created
March 9, 2019 02:39
-
-
Save michaelbartnett/dea9aafca371cdaf949cf12de12e41e5 to your computer and use it in GitHub Desktop.
eh?
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 <type_traits> | |
#include <cstdint> | |
#include <iostream> | |
template<typename T_ENUM> | |
class EnumFlags | |
{ | |
static_assert(std::is_enum<T_ENUM>::value, "T_ENUM must be an enum type"); | |
public: | |
using BaseType = typename std::underlying_type<T_ENUM>::type; | |
using SelfType= EnumFlags<T_ENUM>; | |
private: | |
BaseType m_storage = 0; | |
public: | |
EnumFlags() = default; | |
EnumFlags(T_ENUM initialFlag) : | |
m_storage{static_cast<BaseType>(1 << static_cast<BaseType>(initialFlag))} | |
{ | |
} | |
void Set( T_ENUM flag ) | |
{ | |
m_storage |= (1 << static_cast<BaseType>(flag)); | |
} | |
void Clear( T_ENUM flag ) | |
{ | |
m_storage &= ~(1 << static_cast<BaseType>(flag)); | |
} | |
void ClearAll() | |
{ | |
m_storage = 0; | |
} | |
bool Has(T_ENUM flag) const | |
{ | |
return m_storage & (1 << static_cast<BaseType>(flag)); | |
} | |
bool HasAny() const | |
{ | |
return m_storage; | |
} | |
BaseType &AsBase() { return m_storage; } | |
const BaseType &AsBase() const { return m_storage; } | |
SelfType& operator |= (const SelfType& other) | |
{ | |
m_storage |= other.m_storage; | |
return *this; | |
} | |
SelfType& operator &= (const SelfType& other) | |
{ | |
m_storage &= other.m_storage; | |
return *this; | |
} | |
SelfType operator | (SelfType other) const | |
{ | |
other |= *this; | |
return other; | |
} | |
SelfType operator & (SelfType other) const | |
{ | |
other &= *this; | |
return other; | |
} | |
template<typename ...TNames> | |
void log(TNames ...names) | |
{ | |
m_log(0, names...); | |
} | |
private: | |
template<typename ...TNames> | |
void m_log(int acc, const char *name, TNames ...names) | |
{ | |
std::cout << name << ": " << Has(static_cast<T_ENUM>(acc)) << "\n"; | |
m_log(acc + 1, names...); | |
} | |
void m_log(int acc, const char* name) | |
{ | |
std::cout << name << ": " << Has(T_ENUM(acc)) << "\n"; | |
} | |
}; | |
template<typename T_ENUM> | |
struct EnumTraits | |
{ | |
static constexpr bool enable_operators = false; | |
}; | |
#define ENABLE_ENUMFLAGS_OPERATORS(enum_type) \ | |
static_assert(std::is_enum<enum_type>::value, "enum_type is not an enum"); \ | |
template<> \ | |
struct EnumTraits<enum_type> \ | |
{ \ | |
static constexpr bool enable_operators = true; \ | |
}; | |
template<typename T_ENUM> | |
EnumFlags<T_ENUM> operator |(T_ENUM a, T_ENUM b) | |
{ | |
static_assert(EnumTraits<T_ENUM>::enable_operators, "Define the EnumTraits::enable_operators on your enum to use operator|"); | |
EnumFlags<T_ENUM> result{a}; | |
result.Set(b); | |
return result; | |
} | |
enum class Flags : uint8_t | |
{ | |
One, | |
Two, | |
Three, | |
}; | |
ENABLE_ENUMFLAGS_OPERATORS(Flags); | |
int main() | |
{ | |
auto flags = Flags::One | Flags::Three; | |
flags.log("One", "Two", "Three"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment