Example
consteval auto to_number(auto str) {
int value;{}
std::from_chars(std::cbegin(str), std::cend(str), value);
return value;
}
static_assert(42 == to_number(std::string_view{"42"}));
Puzzle
- Can you implement to_string which converts number to an array by applying constexpr to_chars?
[[nodiscard]] consteval auto to_string(auto value);
static_assert(std::array{'0', '0', '0', '1'} == to_string(1));
static_assert(std::array{'0', '0', '4', '2'} == to_string(42));
static_assert(std::array{'1', '2', '3', '4'} == to_string(1234));
Solutions
[[nodiscard]] consteval auto to_string(auto value){
std::array<char, 4> result {'0','0','0','0'};
auto [ptr, _] = std::to_chars(result.begin(), result.end(), value);
::std::rotate(result.begin(), ptr, result.end());
return result;
}
[[nodiscard]] consteval auto to_string(std::integral auto value)
requires(!std::is_same_v<decltype(value), bool>)
{
std::array<char, 4> arr{'0', '0', '0'}; // at least 1 character is filled
if (value >= 10000 ||
std::errc{} != std::to_chars(
arr.data() + (value < 1000) + (value < 100) + (value < 10),
arr.data() + 4, value
).ec)
throw;
return arr;
}
template <int N = 4>
[[nodiscard]] consteval auto to_string(auto value) {
std::array<char, N> res{};
std::fill_n(std::begin(res), N, '0');
if (auto [ptr, ec] = std::to_chars(std::begin(res), std::end(res), value);
ec == std::errc{}) {
std::rotate(std::begin(res), ptr, std::end(res));
}
return res;
}
[[nodiscard]] consteval auto to_string(auto value){
constexpr size_t N = 4;
char buf[N] = {'0','0','0','0'};
std::array<char,N> return_val{'0','0','0','0'};
const std::to_chars_result res = std::to_chars(buf, buf + N, value);
if (res.ec == std::errc{})
{
const auto num_chars = static_cast<int>(res.ptr - buf);
const auto starting_offset = N-num_chars;
for (size_t i = 0; i < num_chars; i++){
return_val.at(starting_offset + i) = buf[i];
}
}
return return_val;
};
[[nodiscard]] consteval auto to_string(auto value){
constexpr auto total_digits = 4;
std::array<char, total_digits> result{'0', '0', '0', '0'};
const auto num_digits = std::floor(std::log10(value) + 1);
const int offset = total_digits - num_digits;
std::to_chars(std::data(result) + offset, std::data(result) + std::size(result), value);
return result;
}
[[nodiscard]] consteval auto to_string(auto value) {
std::array<char, 4> arr;
for(int i=0, d=1000; i<4; i++, d/=10) {
arr[i] = value/d + '0';
value -= (arr[i]-'0') * d;
}
return arr;
}
[[nodiscard]] consteval auto to_string(auto value){
constexpr auto size = 4;
std::array<char, size> chars{};
for(auto i=size-1; i>=0; --i){
chars[i] = value%10 +'0';
value = value /10;
}
return chars;
}
[[nodiscard]] consteval auto to_string(const auto value) {
std::array<char, 4> out;
const auto end_num = std::to_chars(out.begin(), out.end(), value).ptr;
const auto end_pad =
std::copy(std::reverse_iterator{end_num}, out.rend(), out.rbegin());
std::fill(end_pad, out.rend(), '0');
return out;
}
[[nodiscard]] consteval auto to_string(const auto value) {
auto out = std::array{'0', '0', '0', '0'};
auto ec = std::errc::value_too_large;
for (auto first = out.end(), last = out.end();
ec == std::errc::value_too_large; --first) {
ec = std::to_chars(first, last, value).ec;
}
return out;
}
[[nodiscard]] consteval auto to_string(auto value){
const size_t digits = floor( log( value ) / log(10) ) + 1;
std::array<char,4> v{'0','0','0','0'};
auto [ptr, ec] = std::to_chars(v.data()+v.size()-digits, v.data()+v.size(), value);
return v;
}