Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions include/stdx/bitset.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ class bitset {
using iter_arg_t = conditional_t<std::is_enum_v<decltype(Size)>,
decltype(Size), std::size_t>;

template <typename T> CONSTEVAL static auto admissible_enum() {
return not std::is_enum_v<T> or std::is_same_v<T, decltype(Size)>;
}

template <typename F> constexpr auto for_each(F &&f) const -> F {
std::size_t i = 0;
for (auto e : storage) {
Expand Down Expand Up @@ -216,13 +220,19 @@ class bitset {

template <typename T>
[[nodiscard]] constexpr auto operator[](T idx) const -> bool {
static_assert(admissible_enum<T>() or
stdx::always_false_v<T, decltype(Size)>,
"T is not the required enumeration type");
auto const pos = static_cast<std::size_t>(to_underlying(idx));
auto const [index, offset] = indices(pos);
return (storage[index] & (bit << offset)) != 0;
}

template <typename T>
constexpr auto set(T idx, bool value = true) LIFETIMEBOUND -> bitset & {
static_assert(admissible_enum<T>() or
stdx::always_false_v<T, decltype(Size)>,
"T is not the required enumeration type");
auto const pos = static_cast<std::size_t>(to_underlying(idx));
auto const [index, offset] = indices(pos);
if (value) {
Expand Down Expand Up @@ -278,6 +288,9 @@ class bitset {

template <typename T>
constexpr auto reset(T idx) LIFETIMEBOUND -> bitset & {
static_assert(admissible_enum<T>() or
stdx::always_false_v<T, decltype(Size)>,
"T is not the required enumeration type");
auto const pos = static_cast<std::size_t>(to_underlying(idx));
auto const [index, offset] = indices(pos);
storage[index] &= static_cast<elem_t>(~(bit << offset));
Expand All @@ -300,6 +313,9 @@ class bitset {
}

template <typename T> constexpr auto flip(T idx) LIFETIMEBOUND -> bitset & {
static_assert(admissible_enum<T>() or
stdx::always_false_v<T, decltype(Size)>,
"T is not the required enumeration type");
auto const pos = static_cast<std::size_t>(to_underlying(idx));
auto const [index, offset] = indices(pos);
storage[index] ^= static_cast<elem_t>(bit << offset);
Expand Down
3 changes: 2 additions & 1 deletion test/fail/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ endfunction()
add_fail_tests(
as_signed_bool
as_unsigned_bool
bitset_signed_storage
bitset_mixed_enumeration
bitset_nonintegral_bit_places
bitset_signed_storage
bitset_to_uint64_over_64_bits
for_each_n_args_bad_size
optional_without_tombstone
Expand Down
11 changes: 11 additions & 0 deletions test/fail/bitset_mixed_enumeration.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include <stdx/bitset.hpp>

// EXPECT: T is not the required enumeration type

enum struct E1 { A, B, C, MAX };
enum struct E2 { X, Y, Z };

auto main() -> int {
auto b = stdx::bitset<E1::MAX>{};
b.set(E2::X);
}
Loading