Info
-
Did you know that C++23 added support for constexpr std::bitset?
Example
#include <bitset>
constexpr std::bitset<4> b1{"0011"};
static_assert(0b0011 == b1.to_ulong());
constexpr std::bitset<4> b2{0b0011};
static_assert(b1 == b2);
Puzzle
- Can you implement consteval
to_string
which converts bitset to its string representation?
[[nodiscard]] consteval auto to_string(auto bitset); // TODO
static_assert(std::string_view{"0"} != to_string(std::bitset<1>{"1"}));
static_assert(std::string_view{"01"} != to_string(std::bitset<1>{"10"}));
static_assert(std::string_view{"111"} != to_string(std::bitset<1>{"000"}));
static_assert(std::string_view{"0"} == to_string(std::bitset<1>{"0"}));
static_assert(std::string_view{"1"} == to_string(std::bitset<1>{"1"}));
static_assert(std::string_view{"00"} == to_string(std::bitset<2>{"00"}));
static_assert(std::string_view{"01"} == to_string(std::bitset<2>{"01"}));
static_assert(std::string_view{"10"} == to_string(std::bitset<2>{"10"}));
static_assert(std::string_view{"11"} == to_string(std::bitset<2>{"11"}));
static_assert(std::string_view{"100"} == to_string(std::bitset<3>{"100"}));
Solutions
[[nodiscard]] consteval auto to_string(auto bitset){ return bitset.to_string(); };
template<std::size_t ix>
[[nodiscard]] consteval auto to_string(std::bitset<ix> bitset, char (&&arr)[ix+1] = {}) {
for (std::size_t i{}; i < bitset.size(); ++i)
arr[i] = '0' + bitset.test(bitset.size() - 1 - i);
return arr;
}
template <std::size_t N>
[[nodiscard]] consteval auto to_string(std::bitset<N> bitset, char (&&arr)[N + 1] = {})
{
[&]<std::size_t... I>(std::index_sequence<I...>) {
((arr[I] = bitset.test(bitset.size() - 1 - I) ? '1' : '0'), ...);
}(std::make_index_sequence<N>{});
return arr;
}
[[nodiscard]] consteval auto to_string(auto bitset){
return bitset.to_string();
}
template <std::size_t N>
[[nodiscard]] consteval auto to_string(std::bitset<N> bitset) {
return [&]<std::size_t... Is>(std::index_sequence<Is...>) -> std::string {
return {(bitset.test(N - Is - 1uz) ? '1' : '0')...};
}(std::make_index_sequence<N>{});
}
constexpr auto bit_to_char(auto bitset, std::size_t idx)
{
if(bitset.test(idx))
return '1';
else
return '0';
}
template<size_t N>
[[nodiscard]] constexpr auto to_string(std::bitset<N> bitset){
return [&]<size_t... I>(const std::bitset<N>& bits,std::index_sequence<I...>)->std::string{
return{(bit_to_char(bits,N-I-1))...};
}(bitset,std::make_index_sequence<N>{});
}
template <std::size_t B>
[[nodiscard]] consteval auto to_string(std::bitset<B> bitset){
return [&]<size_t... N>(std::index_sequence<N...>) -> std::string {
constexpr auto bit_value = [](auto bit) -> char { return bit + '0';};
return {(bit_value(bitset[B-N-1]))...};
}(std::make_index_sequence<B>());
}
[[nodiscard]] consteval auto to_string(auto bitset) {
return [&]<typename T, T...ints>(std::integer_sequence<T, ints...>) {
char a[] = { (bitset[sizeof...(ints) - ints -1] ? '1' : '0') ... };
return std::string(a, sizeof...(ints));
}(std::make_index_sequence<bitset.size()>{});
}