diff --git a/include/sparta/utils/EnumBitSet.h b/include/sparta/utils/EnumBitSet.h index e271493..530c0c9 100644 --- a/include/sparta/utils/EnumBitSet.h +++ b/include/sparta/utils/EnumBitSet.h @@ -7,7 +7,7 @@ #pragma once -#include +#include #include #include @@ -19,7 +19,7 @@ namespace sparta { * `EnumBitSet` can be used to store an OR-combination of enum values, * where `Enum` is an enum class type. * - * `Enum` underlying values must be unsigned integers between 0 and 63. `Enum` + * `Enum` underlying values must be unsigned integers. `Enum` * must have a `_Count` member containing the maximum value. */ template @@ -29,36 +29,33 @@ class EnumBitSet final { static_assert( std::is_unsigned_v>, "The underlying type of Enum must be an unsigned arithmetic type"); - static_assert(static_cast>(Enum::_Count) < 64u, - "Enum::_Count must be less than 64"); + static_assert(static_cast>(Enum::_Count) >= 0, + "Enum::_Count must contain the maximum value"); + static_assert( + static_cast>(Enum::_Count) < 512u, + "Enum::_Count is too large, consider using a sparse set instead"); public: using EnumType = Enum; using EnumUnderlyingT = std::underlying_type_t; private: - using IntT = std::conditional_t< - static_cast(Enum::_Count) < 8u, - std::uint8_t, - std::conditional_t(Enum::_Count) < 32u, - std::uint32_t, - std::uint64_t>>; + using BitSetT = std::bitset(Enum::_Count) + 1>; - static constexpr IntT enum_to_bit(Enum value) { - return static_cast(1) - << static_cast(static_cast(value)); + static constexpr BitSetT enum_to_bit(Enum value) { + return BitSetT{}.set(static_cast(value), true); } public: EnumBitSet() = default; /* implicit */ constexpr EnumBitSet(Enum value) - : value_(enum_to_bit(value)) {} + : value_{enum_to_bit(value)} {} /* implicit */ constexpr EnumBitSet(std::initializer_list set) - : value_(0u) { + : value_{} { for (auto value : set) { - value_ |= enum_to_bit(value); + value_.set(static_cast(value), true); } } @@ -118,48 +115,38 @@ class EnumBitSet final { constexpr EnumBitSet operator~() const { return EnumBitSet(~value_); } - explicit constexpr operator bool() const { return value_ != 0; } + explicit operator bool() const { return value_.any(); } - constexpr bool operator!() const { return value_ == 0; } + bool operator!() const { return value_.none(); } - constexpr bool operator==(EnumBitSet set) const { - return value_ == set.value_; - } + bool operator==(const EnumBitSet& set) const { return value_ == set.value_; } - constexpr bool operator!=(EnumBitSet set) const { - return value_ != set.value_; - } + bool operator!=(EnumBitSet set) const { return value_ != set.value_; } - constexpr bool test(Enum value) const { - return (value_ & enum_to_bit(value)) == enum_to_bit(value); + bool test(Enum value) const { + return value_[static_cast(value)]; } constexpr EnumBitSet& set(Enum value, bool on = true) { - if (on) { - value_ |= enum_to_bit(value); - } else { - value_ &= ~enum_to_bit(value); - } + value_.set(static_cast(value), on); return *this; } - constexpr bool empty() const { return value_ == 0; } + bool empty() const { return value_.none(); } - constexpr void clear() { value_ = 0; } + constexpr void clear() { value_.reset(); } - constexpr bool is_subset_of(EnumBitSet set) const { + bool is_subset_of(EnumBitSet set) const { return (value_ | set.value_) == set.value_; } - constexpr bool has_single_bit() const { - return (value_ && !(value_ & (value_ - 1))); - } + bool has_single_bit() const { return value_.count() == 1; } private: - explicit constexpr EnumBitSet(IntT value) : value_(value) {} + explicit constexpr EnumBitSet(BitSetT value) : value_(std::move(value)) {} private: - IntT value_ = 0; + BitSetT value_ = 0; }; } // namespace sparta