@@ -156,20 +156,21 @@ template <std::size_t N, typename StorageElem> class bitset {
156156 }
157157
158158 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,
162164 " 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) ;
165167 } else {
166-
167- T result{highbits ()};
168+ U result{highbits ()};
168169 for (auto i = storage_size - 2u ; i < storage_size; --i) {
169170 result = static_cast <T>(result << storage_elem_size);
170171 result |= storage[i];
171172 }
172- return result;
173+ return static_cast <T>( result) ;
173174 }
174175 }
175176
@@ -182,13 +183,16 @@ template <std::size_t N, typename StorageElem> class bitset {
182183
183184 constexpr static std::integral_constant<std::size_t , N> size{};
184185
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));
186189 auto const [index, offset] = indices (pos);
187190 return (storage[index] & (bit << offset)) != 0 ;
188191 }
189192
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));
192196 auto const [index, offset] = indices (pos);
193197 if (value) {
194198 storage[index] |= static_cast <StorageElem>(bit << offset);
@@ -241,7 +245,9 @@ template <std::size_t N, typename StorageElem> class bitset {
241245 return *this ;
242246 }
243247
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));
245251 auto const [index, offset] = indices (pos);
246252 storage[index] &= static_cast <StorageElem>(~(bit << offset));
247253 return *this ;
@@ -262,7 +268,8 @@ template <std::size_t N, typename StorageElem> class bitset {
262268 return set (lsb, len, false );
263269 }
264270
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));
266273 auto const [index, offset] = indices (pos);
267274 storage[index] ^= static_cast <StorageElem>(bit << offset);
268275 return *this ;
@@ -406,8 +413,10 @@ constexpr auto for_each(F &&f, bitset<M, S> const &...bs) -> F {
406413}
407414} // namespace detail
408415
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>())>;
411420
412421} // namespace v1
413422} // namespace stdx
0 commit comments