| 123 | /// and might also be faster. |
| 124 | template <typename T, typename... Args> |
| 125 | std::string ToChars(T value, Args&&... args) { |
| 126 | if constexpr (!have_to_chars<T>) { |
| 127 | // Some C++ standard libraries do not yet implement std::to_chars for all types, |
| 128 | // in which case we have to fallback to std::string. |
| 129 | return std::to_string(value); |
| 130 | } else { |
| 131 | // According to various sources, the GNU libstdc++ and Microsoft's C++ STL |
| 132 | // allow up to 15 bytes of small string optimization, while clang's libc++ |
| 133 | // goes up to 22 bytes. Choose the pessimistic value. |
| 134 | std::string out(15, 0); |
| 135 | auto res = std::to_chars(&out.front(), &out.back(), value, args...); |
| 136 | while (res.ec != std::errc{}) { |
| 137 | assert(res.ec == std::errc::value_too_large); |
| 138 | out.resize(out.capacity() * 2); |
| 139 | res = std::to_chars(&out.front(), &out.back(), value, args...); |
| 140 | } |
| 141 | const auto length = res.ptr - out.data(); |
| 142 | assert(length <= static_cast<int64_t>(out.length())); |
| 143 | out.resize(length); |
| 144 | return out; |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | #else // !__has_include(<charconv>) |
| 149 | |