Skip to content

Latest commit

 

History

History
185 lines (145 loc) · 4.6 KB

301.md

File metadata and controls

185 lines (145 loc) · 4.6 KB
Info

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"}));

https://godbolt.org/z/1fKhGd4Y7

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));

https://godbolt.org/z/cE3crocaK

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;
}

https://godbolt.org/z/7oPKMGnsj

[[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;
}

https://godbolt.org/z/1svYsaMd3

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;
}

https://godbolt.org/z/anffMq6qf

[[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;
};

https://godbolt.org/z/ohsvvaYjf

[[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;
}

https://godbolt.org/z/5cq7vPceT

[[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;
}

https://godbolt.org/z/h9b45fd19

[[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;
}

https://godbolt.org/z/9Pnqq7W6j

[[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;
}

https://godbolt.org/z/MTo14GxE4

[[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;
}

https://godbolt.org/z/x8xGqYW7h

[[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;
}

https://godbolt.org/z/TM87MaPjb