19#include "lib/stdcompat/bit.h"
33template <
size_t kBits>
41 std::conditional_t<kBits <= 16,
43 std::conditional_t<kBits <= 32, uint32_t, uint64_t>>>;
47 template <
unsigned long long kValue>
49 static_assert(cpp20::countl_zero(kValue) >=
sizeof(kValue) * 8 - kBits,
50 "The value must fit within the BitSet");
56 template <
typename... Args,
57 typename = std::enable_if_t<(std::is_same_v<Args, bool> && ...)>>
59 static_assert(
sizeof...(Args) == kBits,
60 "One bool argument must be provided for each bit");
61 return BitSet(LittleBoolsToBits(bits_least_to_most_significant...));
66 constexpr BitSet(
const BitSet&) =
default;
67 constexpr BitSet& operator=(
const BitSet&) =
default;
69 template <
size_t kOtherBits,
typename = std::enable_if_t<kBits >= kOtherBits>>
70 constexpr BitSet(
const BitSet<kOtherBits>& other) : bits_{other.bits_} {}
72 template <
size_t kOtherBits,
typename = std::enable_if_t<kBits >= kOtherBits>>
73 constexpr BitSet& operator=(
const BitSet& other) {
79 [[nodiscard]]
constexpr bool operator==(
const BitSet& other)
const {
80 return bits_ == other.bits_;
82 [[nodiscard]]
constexpr bool operator!=(
const BitSet& other)
const {
83 return bits_ != other.bits_;
86 template <
size_t kBit>
87 [[nodiscard]]
constexpr bool test()
const {
88 CheckBitIndices<kBit>();
92 [[nodiscard]]
constexpr bool all()
const {
93 if constexpr (kBits == 0) {
96 return bits_ == kAllSet;
99 [[nodiscard]]
constexpr bool any()
const {
return bits_ != 0; }
100 [[nodiscard]]
constexpr bool none()
const {
return bits_ == 0; }
102 [[nodiscard]]
constexpr size_t count()
const {
103 return static_cast<size_t>(cpp20::popcount(bits_));
105 [[nodiscard]]
constexpr size_t size()
const {
return kBits; }
109 constexpr BitSet& set() {
114 template <
size_t... kBitsToSet>
115 constexpr BitSet& set() {
116 CheckBitIndices<kBitsToSet...>();
117 bits_ |= ((
value_type{1} << kBitsToSet) | ...);
121 constexpr BitSet& reset() {
126 template <
size_t... kBitsToReset>
127 constexpr BitSet& reset() {
128 CheckBitIndices<kBitsToReset...>();
129 bits_ &= ~((
value_type{1} << kBitsToReset) | ...);
133 constexpr BitSet& flip() {
138 template <
size_t... kBitsToFlip>
139 constexpr BitSet& flip() {
140 CheckBitIndices<kBitsToFlip...>();
141 bits_ ^= ((
value_type{1} << kBitsToFlip) | ...);
147 constexpr BitSet& operator&=(
const BitSet& other) {
148 bits_ &= other.bits_;
151 constexpr BitSet& operator|=(
const BitSet& other) {
152 bits_ |= other.bits_;
155 constexpr BitSet& operator^=(
const BitSet& other) {
156 bits_ ^= other.bits_;
160 constexpr BitSet& operator<<=(
size_t pos) {
161 bits_ = (bits_ << pos) & kAllSet;
165 constexpr BitSet& operator>>=(
size_t pos) {
170 constexpr BitSet operator~()
const {
171 return BitSet(
static_cast<value_type>(~bits_ & kAllSet));
174 friend constexpr BitSet operator&(
const BitSet& lhs,
const BitSet& rhs) {
175 return BitSet(lhs.bits_ & rhs.bits_);
177 friend constexpr BitSet operator|(
const BitSet& lhs,
const BitSet& rhs) {
178 return BitSet(lhs.bits_ | rhs.bits_);
180 friend constexpr BitSet operator^(
const BitSet& lhs,
const BitSet& rhs) {
181 return BitSet(lhs.bits_ ^ rhs.bits_);
184 friend constexpr BitSet operator<<(
const BitSet& bs,
size_t pos) {
185 return BitSet((bs.bits_ << pos) & kAllSet);
188 friend constexpr BitSet operator>>(
const BitSet& bs,
size_t pos) {
189 return BitSet(bs.bits_ >> pos);
196 static_assert(kBits <= 64,
"BitSet currently only supports up to 64 bits");
201 template <
size_t... kIndices>
202 static constexpr void CheckBitIndices() {
203 static_assert(((kIndices < kBits) && ...),
204 "The specified bit index is out of range of this BitSet");
207 static constexpr value_type LittleBoolsToBits() {
return 0; }
209 template <
typename... Args,
210 typename = std::enable_if_t<(std::is_same_v<Args, bool> && ...)>>
211 static constexpr value_type LittleBoolsToBits(
bool first, Args... bits) {
212 return (first ? (
value_type{1} << (kBits -
sizeof...(Args) - 1)) : 0) |
213 LittleBoolsToBits(bits...);
216 explicit constexpr BitSet(
value_type bits) : bits_(bits) {}
234 using value_type = uint8_t;
236 constexpr BitSet() =
default;
243 [[nodiscard]]
constexpr bool operator==(
const BitSet&)
const {
return true; }
244 [[nodiscard]]
constexpr bool operator!=(
const BitSet&)
const {
return false; }
246 template <
size_t kBit>
247 [[nodiscard]]
constexpr bool test()
const {
248 static_assert(kBit < 0,
"test() is not supported for zero-bit BitSets");
252 [[nodiscard]]
constexpr bool all()
const {
return true; }
253 [[nodiscard]]
constexpr bool any()
const {
return false; }
254 [[nodiscard]]
constexpr bool none()
const {
return true; }
256 constexpr size_t count()
const {
return 0; }
257 constexpr size_t size()
const {
return 0; }
260 constexpr BitSet& set() {
return *
this; }
261 constexpr BitSet& reset() {
return *
this; }
262 constexpr BitSet& flip() {
return *
this; }
264 constexpr BitSet& operator&=(
const BitSet&) {
return *
this; }
265 constexpr BitSet& operator|=(
const BitSet&) {
return *
this; }
266 constexpr BitSet& operator^=(
const BitSet&) {
return *
this; }
268 constexpr BitSet& operator<<=(
size_t) {
return *
this; }
269 constexpr BitSet& operator>>=(
size_t) {
return *
this; }
271 constexpr BitSet operator~()
const {
return *
this; }
286 constexpr value_type
to_integer()
const {
return 0; }
constexpr value_type to_integer() const
Returns the bit set as an integer.
Definition: bitset.h:193
static constexpr BitSet LittleEndian(Args... bits_least_to_most_significant)
Definition: bitset.h:58
std::conditional_t< kBits<=8, uint8_t, std::conditional_t< kBits<=16, uint16_t, std::conditional_t< kBits<=32, uint32_t, uint64_t > > > value_type
Definition: bitset.h:43
static constexpr BitSet Of()
Definition: bitset.h:48
The Pigweed namespace.
Definition: alignment.h:27