Skip to content

Instantly share code, notes, and snippets.

@michaelbartnett
Created March 9, 2019 02:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save michaelbartnett/dea9aafca371cdaf949cf12de12e41e5 to your computer and use it in GitHub Desktop.
Save michaelbartnett/dea9aafca371cdaf949cf12de12e41e5 to your computer and use it in GitHub Desktop.
eh?
#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