Skip to content

Instantly share code, notes, and snippets.

@Ed94
Last active February 9, 2021 07:05
Show Gist options
  • Select an option

  • Save Ed94/44078a25047a875376bab9239de6d566 to your computer and use it in GitHub Desktop.

Select an option

Save Ed94/44078a25047a875376bab9239de6d566 to your computer and use it in GitHub Desktop.
/*
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;
};
@Ed94
Copy link
Author

Ed94 commented Sep 8, 2020

Example enum:

enum class ETest : uint32
{
      SpecifyBitmaskable = sizeof(uint32)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment