Last active
February 9, 2021 07:05
-
-
Save Ed94/44078a25047a875376bab9239de6d566 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| /* | |
| Bitfield | |
| A wrapper for bitfields with support for specifying enum classes as bitmaskable types, and | |
| ease of use functionality for manipulating the bitfield. | |
| */ | |
| #pragma once | |
| template<typename Enum, typename = void> | |
| /** | |
| @brief Used when the enum does not meet the criteria for bitmaskable. | |
| */ | |
| struct IsBitmaskable : std::false_type | |
| {}; | |
| template<typename Enum> | |
| /** | |
| @brief Will be defined with a true_type when enum has the SpecifyBitmaskable enum value. | |
| */ | |
| struct IsBitmaskable<Enum, decltype(static_cast<void>(Enum::SpecifyBitmaskable))> : std::is_enum<Enum> | |
| {}; | |
| template <typename Enum> | |
| /** | |
| @brief Returns true if IsBitmaskable is false. | |
| */ | |
| constexpr typename std::enable_if<IsBitmaskable<Enum>::value, | |
| bool> Bitmaskable() noexcept | |
| { | |
| return static_cast<size_t>(Enum::SpecifyBitmaskable) > size_t(0) ? true : false; | |
| } | |
| template <typename Enum> | |
| /** | |
| @brief Returns false if bitmaskable is false (Default case). | |
| */ | |
| constexpr typename std::enable_if<! IsBitmaskable<Enum>::value, | |
| bool> Bitmaskable() noexcept | |
| { | |
| return false; | |
| } | |
| template | |
| < | |
| typename EnumType , | |
| typename BitmaskRepresentation | |
| > | |
| class Bitfield | |
| { | |
| private: | |
| EnforceConstraint(Bitmaskable<EnumType>(), "EnumType must be of Bitmaskable type."); | |
| using _ThisType = Bitfield<EnumType, BitmaskRepresentation>; | |
| public: | |
| using Enum = EnumType ; | |
| using Representation = BitmaskRepresentation; | |
| Bitfield() : mask(0) {} | |
| constexpr Bitfield(Representation _mask) : mask(_mask) | |
| {} | |
| template<typename... BitTypes> | |
| constexpr Bitfield(const BitTypes... _bits) : mask(0) | |
| { | |
| mask = (Representation(_bits) | ...); | |
| } | |
| template<typename... BitType> | |
| void Add(const BitType... _bits) | |
| { | |
| mask |= (Representation(_bits) | ...); | |
| } | |
| template<typename... BitType> | |
| bool CheckForEither(const BitType... _bits) const | |
| { | |
| return (mask & (Representation(_bits) | ...)) != 0; | |
| } | |
| template<typename... BitType> | |
| void Clear(const BitType... _bits) | |
| { | |
| if (mask <= 0) return; | |
| mask &= ~(Representation(_bits) | ...); | |
| } | |
| bool HasFlag(const Enum _bit) const | |
| { | |
| return (mask & Representation(_bit)) == Representation(_bit); | |
| } | |
| template<typename... BitType> | |
| bool HasExactly(const BitType... _bits) const | |
| { | |
| return (mask & (Representation(_bits) | ...)) == mask; | |
| } | |
| bool HasAnyFlag() const { return mask != 0 ? true : false; } | |
| bool IsZero () const { return mask == 0 ? true : false; } | |
| void Reset() { mask = 0; } | |
| template<typename... BitType> | |
| void Set(const BitType... _bits) | |
| { | |
| mask = (Representation(_bits) | ...); | |
| } | |
| template<typename... BitType> | |
| void Toggle(const BitType... _bits) | |
| { | |
| mask ^= (Representation(_bits) | ...); | |
| } | |
| operator Representation() const { return mask; } | |
| _ThisType& operator= (const Representation _mask ) { mask = _mask ; return *this; } | |
| _ThisType& operator= (const _ThisType _other) { mask = _other.mask; return *this; } | |
| _ThisType& operator&= (const Representation _mask ) { mask &= mask ; return *this; } | |
| _ThisType& operator&= (const _ThisType _other) { mask &= _other.mask; return *this; } | |
| _ThisType& operator|= (const Representation _mask ) { mask |= mask ; return *this; } | |
| _ThisType& operator|= (const _ThisType _other) { mask |= _other.mask; return *this; } | |
| _ThisType& operator^= (const Representation _mask ) { mask ^= mask ; return *this; } | |
| _ThisType& operator^= (const _ThisType _other) { mask ^= _other.mask; return *this; } | |
| _ThisType& operator<<= (const Representation _mask ) { mask <<= mask ; return *this; } | |
| _ThisType& operator>>= (const _ThisType _other) { mask >>= _other.mask; return *this; } | |
| _ThisType operator~ () const { return ~mask; } | |
| Representation operator& (const Representation _other) const { return mask & _other ; } | |
| _ThisType operator& (const _ThisType _other) const { return mask & _other.mask; } | |
| Representation operator| (const Representation _other) const { return mask | _other ; } | |
| _ThisType operator| (const _ThisType _other) const { return mask | _other.mask; } | |
| Representation operator^ (const Representation _other) const { return mask ^ _other ; } | |
| _ThisType operator^ (const _ThisType _other) const { return mask ^ _other.mask; } | |
| Representation operator<< (const Representation _other) const { return mask << _other ; } | |
| _ThisType operator>> (const _ThisType _other) const { return mask >> _other.mask; } | |
| bool operator== (const Representation _other) const { return mask == _other ; } | |
| bool operator== (const _ThisType _other) const { return mask == _other.mask; } | |
| bool operator!= (const Representation _other) const { return mask != _other ; } | |
| bool operator!= (const _ThisType _other) const { return mask != _other.mask; } | |
| private: | |
| Representation mask; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.