Skip to content

Instantly share code, notes, and snippets.

@fschoenberger
Created June 1, 2024 22:25
Show Gist options
  • Save fschoenberger/54c5342f220af510e1f78308a8994a45 to your computer and use it in GitHub Desktop.
Save fschoenberger/54c5342f220af510e1f78308a8994a45 to your computer and use it in GitHub Desktop.
Flags class for C++
module;
#include <compare>
#include <type_traits>
export module util:flags;
export namespace util {
template <typename BitType>
requires std::is_enum_v<BitType>
class Flags {
public:
using MaskType = std::underlying_type_t<BitType>;
// constructors
constexpr Flags() noexcept
: mask_(0)
{
}
explicit(false) constexpr Flags(BitType bit) noexcept
: mask_(static_cast<MaskType>(bit))
{
}
constexpr Flags(Flags<BitType> const& rhs) noexcept = default;
constexpr explicit Flags(MaskType flags) noexcept
: mask_(flags)
{
}
// relational operators
constexpr auto operator<=>(Flags<BitType> const&) const = default;
// logical operator
constexpr bool operator!() const noexcept { return !mask_; }
// bitwise operators
constexpr Flags<BitType> operator&(Flags<BitType> const& rhs) const noexcept { return Flags<BitType>(mask_ & rhs.mask_); }
constexpr Flags<BitType> operator|(Flags<BitType> const& rhs) const noexcept { return Flags<BitType>(mask_ | rhs.mask_); }
constexpr Flags<BitType> operator^(Flags<BitType> const& rhs) const noexcept { return Flags<BitType>(mask_ ^ rhs.mask_); }
constexpr Flags<BitType> operator~() const noexcept { return Flags<BitType>(mask_ ^ static_cast<MaskType>(-1)); }
// assignment operators
constexpr Flags<BitType>& operator=(Flags<BitType> const& rhs) noexcept = default;
constexpr Flags<BitType>& operator|=(Flags<BitType> const& rhs) noexcept
{
mask_ |= rhs.mask_;
return *this;
}
constexpr Flags<BitType>& operator&=(Flags<BitType> const& rhs) noexcept
{
mask_ &= rhs.mask_;
return *this;
}
constexpr Flags<BitType>& operator^=(Flags<BitType> const& rhs) noexcept
{
mask_ ^= rhs.mask_;
return *this;
}
// cast operators
explicit constexpr operator bool() const noexcept { return !!mask_; }
explicit constexpr operator MaskType() const noexcept { return mask_; }
private:
MaskType mask_;
};
// bitwise operators
template <typename BitType>
requires std::is_enum_v<BitType>
constexpr Flags<BitType> operator&(BitType bit, Flags<BitType> const& flags) noexcept
{
return flags.operator&(bit);
}
template <typename BitType>
requires std::is_enum_v<BitType>
constexpr Flags<BitType> operator|(BitType bit, Flags<BitType> const& flags) noexcept
{
return flags.operator|(bit);
}
template <typename BitType>
requires std::is_enum_v<BitType>
constexpr Flags<BitType> operator^(BitType bit, Flags<BitType> const& flags) noexcept
{
return flags.operator^(bit);
}
// bitwise operators on BitType
template <typename BitType>
requires std::is_enum_v<BitType>
inline constexpr Flags<BitType> operator&(BitType lhs, BitType rhs) noexcept
{
return Flags<BitType>(lhs) & rhs;
}
template <typename BitType>
requires std::is_enum_v<BitType>
inline constexpr Flags<BitType> operator|(BitType lhs, BitType rhs) noexcept
{
return Flags<BitType>(lhs) | rhs;
}
template <typename BitType>
requires std::is_enum_v<BitType>
inline constexpr Flags<BitType> operator^(BitType lhs, BitType rhs) noexcept
{
return Flags<BitType>(lhs) ^ rhs;
}
template <typename BitType>
requires std::is_enum_v<BitType>
inline constexpr Flags<BitType> operator~(BitType bit) noexcept
{
return ~(Flags<BitType>(bit));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment