Skip to content

Commit

Permalink
Use std::bitset to implement EnumBitSet
Browse files Browse the repository at this point in the history
Summary: This diff changes EnumBitSet to use `std::bitset` internally, which means we are not restricted to 64 enum values anymore.

Reviewed By: arnaudvenet

Differential Revision: D51668589

fbshipit-source-id: 614f35f489eb7e925dbc9739c562f4d9641e4ad3
  • Loading branch information
arthaud authored and facebook-github-bot committed Nov 29, 2023
1 parent 3f9d7ae commit 49e71e5
Showing 1 changed file with 26 additions and 39 deletions.
65 changes: 26 additions & 39 deletions include/sparta/utils/EnumBitSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#pragma once

#include <cstdint>
#include <bitset>
#include <initializer_list>
#include <type_traits>

Expand All @@ -19,7 +19,7 @@ namespace sparta {
* `EnumBitSet<Enum>` 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 <typename Enum>
Expand All @@ -29,36 +29,33 @@ class EnumBitSet final {
static_assert(
std::is_unsigned_v<std::underlying_type_t<Enum>>,
"The underlying type of Enum must be an unsigned arithmetic type");
static_assert(static_cast<std::underlying_type_t<Enum>>(Enum::_Count) < 64u,
"Enum::_Count must be less than 64");
static_assert(static_cast<std::underlying_type_t<Enum>>(Enum::_Count) >= 0,
"Enum::_Count must contain the maximum value");
static_assert(
static_cast<std::underlying_type_t<Enum>>(Enum::_Count) < 512u,
"Enum::_Count is too large, consider using a sparse set instead");

public:
using EnumType = Enum;
using EnumUnderlyingT = std::underlying_type_t<Enum>;

private:
using IntT = std::conditional_t<
static_cast<EnumUnderlyingT>(Enum::_Count) < 8u,
std::uint8_t,
std::conditional_t<static_cast<EnumUnderlyingT>(Enum::_Count) < 32u,
std::uint32_t,
std::uint64_t>>;
using BitSetT = std::bitset<static_cast<EnumUnderlyingT>(Enum::_Count) + 1>;

static constexpr IntT enum_to_bit(Enum value) {
return static_cast<IntT>(1)
<< static_cast<IntT>(static_cast<EnumUnderlyingT>(value));
static constexpr BitSetT enum_to_bit(Enum value) {
return BitSetT{}.set(static_cast<EnumUnderlyingT>(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<Enum> set)
: value_(0u) {
: value_{} {
for (auto value : set) {
value_ |= enum_to_bit(value);
value_.set(static_cast<EnumUnderlyingT>(value), true);
}
}

Expand Down Expand Up @@ -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<EnumUnderlyingT>(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<EnumUnderlyingT>(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

0 comments on commit 49e71e5

Please sign in to comment.