Core/Flags: Reworked Flags class

This commit is contained in:
Jérôme Leclercq
2017-11-21 12:26:22 +01:00
parent f2506ee918
commit 3589a2bc8e
13 changed files with 49 additions and 39 deletions

View File

@@ -16,18 +16,34 @@ namespace Nz
template<typename E>
struct EnumAsFlags
{
static constexpr bool value = false;
static constexpr int max = 0;
};
// From: https://stackoverflow.com/questions/11927032/sfinae-check-for-static-member-using-decltype
template <typename T>
class IsEnumFlag
{
template<typename U, typename = typename std::enable_if<!std::is_member_pointer<decltype(&EnumAsFlags<U>::max)>::value>::type>
static std::true_type check(int);
template <typename> static std::false_type check(...);
public:
static constexpr bool value = decltype(check<T>(0))::value;
};
template<typename E>
class Flags
{
static_assert(std::is_enum<E>::value, "Type must be an enumeration");
static_assert(EnumAsFlags<E>::value, "Enum has not been enabled as flags by an EnumAsFlags specialization");
static_assert(IsEnumFlag<E>::value, "Enum has not been enabled as flags by an EnumAsFlags specialization");
static constexpr std::size_t MaxValue = static_cast<std::size_t>(EnumAsFlags<E>::max);
using BitField16 = typename std::conditional<(MaxValue > 8), UInt16, UInt8>::type;
using BitField32 = typename std::conditional<(MaxValue > 16), UInt32, BitField16>::type;
public:
using BitField = typename std::conditional<(EnumAsFlags<E>::max > 32), UInt64, UInt32>::type;
using BitField = typename std::conditional<(MaxValue > 32), UInt64, BitField32>::type;
constexpr Flags(BitField value = 0);
constexpr Flags(E enumVal);
@@ -49,7 +65,7 @@ namespace Nz
static constexpr BitField GetFlagValue(E enumValue);
static constexpr BitField ValueMask = ((BitField(1) << (EnumAsFlags<E>::max + 1)) - 1);
static constexpr BitField ValueMask = ((BitField(1) << (MaxValue + 1)) - 1);
private:
BitField m_value;
@@ -58,10 +74,10 @@ namespace Nz
// Little hack to have them in both Nz and global scope
namespace FlagsOperators
{
template<typename E> constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator~(E lhs);
template<typename E> constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator|(E lhs, E rhs);
template<typename E> constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator&(E lhs, E rhs);
template<typename E> constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator^(E lhs, E rhs);
template<typename E> constexpr std::enable_if_t<IsEnumFlag<E>::value, Flags<E>> operator~(E lhs);
template<typename E> constexpr std::enable_if_t<IsEnumFlag<E>::value, Flags<E>> operator|(E lhs, E rhs);
template<typename E> constexpr std::enable_if_t<IsEnumFlag<E>::value, Flags<E>> operator&(E lhs, E rhs);
template<typename E> constexpr std::enable_if_t<IsEnumFlag<E>::value, Flags<E>> operator^(E lhs, E rhs);
}
using namespace FlagsOperators;