diff --git a/docs/bitset.adoc b/docs/bitset.adoc index d3ae08f..7a96248 100644 --- a/docs/bitset.adoc +++ b/docs/bitset.adoc @@ -55,16 +55,6 @@ Or by specifying which bits are set and using `stdx::place_bits`: auto bs = stdx::bitset<8>{stdx::place_bits, 2, 3}; // bits 2 and 3 set ---- -Or with a string_view (potentially by substring and with a known value for -set bits): -[source,cpp] ----- -using namespace std::string_view_literals; -auto bs1 = stdx::bitset<8>{"1100"sv}; // bits 2 and 3 set -auto bs2 = stdx::bitset<8>{"1100"sv, 0, 2}; // bits 0 and 1 set -auto bs3 = stdx::bitset<8>{"AABB"sv, 0, 2, 'A'}; // bits 0 and 1 set ----- - To convert a bitset back to an integral type, `to` is available where `T` is an unsigned integral type large enough to fit all the bits. And `to_natural` produces the smallest such unsigned integral type. diff --git a/docs/header_graph.mmd b/docs/header_graph.mmd index c38efc0..60a2598 100644 --- a/docs/header_graph.mmd +++ b/docs/header_graph.mmd @@ -83,7 +83,6 @@ flowchart BT byterator --> bit cx_set ---> cx_map bitset --> bit - bitset --> ct_string panic --> ct_string env --> ct_string tuple_algorithms --> tuple diff --git a/include/stdx/bitset.hpp b/include/stdx/bitset.hpp index 0fc78c0..1f780e2 100644 --- a/include/stdx/bitset.hpp +++ b/include/stdx/bitset.hpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -15,7 +14,6 @@ #include #include #include -#include #include #include @@ -58,6 +56,17 @@ namespace detail { template concept bit_spec = std::same_as or std::same_as or std::same_as; + +template consteval auto bitset_size(T t) { + if constexpr (std::integral) { + return static_cast(t); + } else if constexpr (std::is_enum_v) { + return t; + } else { + static_assert( + always_false_v, + "bitset must be instantiated with an integral or an enum argument"); + } } template or std::is_same_v; } - template - friend constexpr auto for_each(F &&f, bitset const &...bs) -> F; - - template - friend constexpr auto transform_reduce(F &&f, R &&r, T init, - bitset const &...bs) -> T; - public: constexpr bitset() = default; constexpr explicit bitset(std::uint64_t value) { @@ -184,21 +186,6 @@ class bitset { } } - constexpr explicit bitset(std::string_view str, std::size_t pos = 0, - std::size_t n = std::string_view::npos, - char one = '1') { - auto const len = std::min(n, str.size() - pos); - auto i = std::size_t{}; - auto const s = str.substr(pos, std::min(len, N)); - // NOLINTNEXTLINE(modernize-loop-convert) - for (auto it = std::rbegin(s); it != std::rend(s); ++it) { - set(i++, *it == one); - } - } - - constexpr explicit bitset(ct_string s) - : bitset{static_cast(s)} {} - template [[nodiscard]] constexpr auto to() const -> T { if constexpr (N == 0) { return {}; @@ -495,9 +482,14 @@ class bitset { return init; } }; +} // namespace detail + +template ())> +using bitset = detail::bitset; template -constexpr auto for_each(F &&f, bitset const &...bs) -> F { +constexpr auto for_each(F &&f, detail::bitset const &...bs) -> F { if constexpr (sizeof...(bs) == 1) { return (bs.template for_each(std::forward(f)), ...); } else { @@ -508,7 +500,8 @@ constexpr auto for_each(F &&f, bitset const &...bs) -> F { template [[nodiscard]] constexpr auto transform_reduce(F &&f, R &&r, T init, - bitset const &...bs) -> T { + detail::bitset const &...bs) + -> T { if constexpr (sizeof...(bs) == 1) { return (bs.transform_reduce(std::forward(f), std::forward(r), std::move(init)), @@ -519,9 +512,10 @@ template } } -template bitset(ct_string) -> bitset; - namespace detail { +using ::stdx::for_each; +using ::stdx::transform_reduce; + template constexpr std::size_t index_of = 0; template diff --git a/test/bitset.cpp b/test/bitset.cpp index 86175d0..9864606 100644 --- a/test/bitset.cpp +++ b/test/bitset.cpp @@ -132,20 +132,6 @@ TEMPLATE_TEST_CASE("construct with values for bits", "[bitset]", std::uint8_t, STATIC_REQUIRE(bs[5]); } -TEMPLATE_TEST_CASE("construct with a string_view", "[bitset]", std::uint8_t, - std::uint16_t, std::uint32_t, std::uint64_t) { - using namespace std::string_view_literals; - STATIC_REQUIRE(stdx::bitset<4, TestType>{"1010"sv} == - stdx::bitset<4, TestType>{0b1010ul}); -} - -TEMPLATE_TEST_CASE("construct with a substring", "[bitset]", std::uint8_t, - std::uint16_t, std::uint32_t, std::uint64_t) { - using namespace std::string_view_literals; - STATIC_REQUIRE(stdx::bitset<4, TestType>{"XOXOXO"sv, 2, 4, 'X'} == - stdx::bitset<4, TestType>{0b1010ul}); -} - TEMPLATE_TEST_CASE("convert to unsigned integral type (same underlying type)", "[bitset]", std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t) { @@ -563,14 +549,6 @@ TEST_CASE("use bitset with enum struct (lowest_unset)", "[bitset]") { CHECK(bs.lowest_unset() == Bits::ONE); } -TEST_CASE("construct with a ct_string", "[bitset]") { - using namespace stdx::literals; - STATIC_REQUIRE(stdx::bitset{"1010"_cts} == - stdx::bitset<4ul, std::uint8_t>{0b1010ul}); - STATIC_REQUIRE(stdx::bitset{"101010101"_cts} == - stdx::bitset<9ul, std::uint16_t>{0b101010101ul}); -} - TEST_CASE("zero size bitset", "[bitset]") { constexpr auto bs1 = stdx::bitset<0>{}; STATIC_REQUIRE(bs1.count() == 0u); @@ -590,3 +568,10 @@ TEST_CASE("zero size bitset", "[bitset]") { bs3 = stdx::bitset<0>{stdx::all_bits}; CHECK(bs3.to() == 0); } + +TEST_CASE("fix type of bitset argument to std::size_t", "[bitset]") { + using A = stdx::bitset<16>; + using B = stdx::bitset<16u>; + STATIC_CHECK(std::same_as); + STATIC_CHECK(std::same_as>); +}