@@ -156,20 +156,21 @@ template <std::size_t N, typename StorageElem> class bitset {
156
156
}
157
157
158
158
template <typename T> [[nodiscard]] constexpr auto to () const -> T {
159
- static_assert (unsigned_integral<T>,
160
- " Conversion must be to an unsigned integral type!" );
161
- static_assert (N <= std::numeric_limits<T>::digits,
159
+ using U = underlying_type_t <T>;
160
+ static_assert (
161
+ unsigned_integral<U>,
162
+ " Conversion must be to an unsigned integral type or enum!" );
163
+ static_assert (N <= std::numeric_limits<U>::digits,
162
164
" Bitset too big for conversion to T" );
163
- if constexpr (std::is_same_v<StorageElem, T >) {
164
- return storage[0 ] & lastmask;
165
+ if constexpr (std::is_same_v<StorageElem, U >) {
166
+ return static_cast <T>( storage[0 ] & lastmask) ;
165
167
} else {
166
-
167
- T result{highbits ()};
168
+ U result{highbits ()};
168
169
for (auto i = storage_size - 2u ; i < storage_size; --i) {
169
170
result = static_cast <T>(result << storage_elem_size);
170
171
result |= storage[i];
171
172
}
172
- return result;
173
+ return static_cast <T>( result) ;
173
174
}
174
175
}
175
176
@@ -182,13 +183,16 @@ template <std::size_t N, typename StorageElem> class bitset {
182
183
183
184
constexpr static std::integral_constant<std::size_t , N> size{};
184
185
185
- [[nodiscard]] constexpr auto operator [](std::size_t pos) const -> bool {
186
+ template <typename T>
187
+ [[nodiscard]] constexpr auto operator [](T idx) const -> bool {
188
+ auto const pos = static_cast <std::size_t >(to_underlying (idx));
186
189
auto const [index, offset] = indices (pos);
187
190
return (storage[index] & (bit << offset)) != 0 ;
188
191
}
189
192
190
- constexpr auto set (std::size_t pos,
191
- bool value = true ) LIFETIMEBOUND -> bitset & {
193
+ template <typename T>
194
+ constexpr auto set (T idx, bool value = true ) LIFETIMEBOUND -> bitset & {
195
+ auto const pos = static_cast <std::size_t >(to_underlying (idx));
192
196
auto const [index, offset] = indices (pos);
193
197
if (value) {
194
198
storage[index] |= static_cast <StorageElem>(bit << offset);
@@ -241,7 +245,9 @@ template <std::size_t N, typename StorageElem> class bitset {
241
245
return *this ;
242
246
}
243
247
244
- constexpr auto reset (std::size_t pos) LIFETIMEBOUND -> bitset & {
248
+ template <typename T>
249
+ constexpr auto reset (T idx) LIFETIMEBOUND -> bitset & {
250
+ auto const pos = static_cast <std::size_t >(to_underlying (idx));
245
251
auto const [index, offset] = indices (pos);
246
252
storage[index] &= static_cast <StorageElem>(~(bit << offset));
247
253
return *this ;
@@ -262,7 +268,8 @@ template <std::size_t N, typename StorageElem> class bitset {
262
268
return set (lsb, len, false );
263
269
}
264
270
265
- constexpr auto flip (std::size_t pos) LIFETIMEBOUND -> bitset & {
271
+ template <typename T> constexpr auto flip (T idx) LIFETIMEBOUND -> bitset & {
272
+ auto const pos = static_cast <std::size_t >(to_underlying (idx));
266
273
auto const [index, offset] = indices (pos);
267
274
storage[index] ^= static_cast <StorageElem>(bit << offset);
268
275
return *this ;
@@ -406,8 +413,10 @@ constexpr auto for_each(F &&f, bitset<M, S> const &...bs) -> F {
406
413
}
407
414
} // namespace detail
408
415
409
- template <std::size_t N, typename StorageElem = void >
410
- using bitset = detail::bitset<N, decltype (smallest_uint<N, StorageElem>())>;
416
+ template <auto N, typename StorageElem = void >
417
+ using bitset =
418
+ detail::bitset<to_underlying(N),
419
+ decltype (smallest_uint<to_underlying(N), StorageElem>())>;
411
420
412
421
} // namespace v1
413
422
} // namespace stdx
0 commit comments