According to https://en.cppreference.com/w/cpp/compiler_support/17, no major vendor yet supports floating point versions of std::to_chars
and std::from_chars
. I understand that correctly formatting a floating point number is nontrivial, yet implementations exists in the C library. However, these are affected by the environment, which is one of the reasons for adding std::to_chars
and std::from_chars
to the standard. Wouldn't then an implementation of these function simply come for free if you refactor the C library to depend on common low-level routines that does the actual conversion base conversion into some intermediate format. Then std::to_chars
and std::from_chars
could use the result more or less directly, and the more high-level API:s in C and C++ (printf
, atof
, strtod
, std::stof
, std::to_string
) can do some more fancy stuff.
The to/from_chars
feature requires that implementations provide round-tripping guarantees (with themselves). Specifically, the following must work:
float f = //get some float
char chars[LOTS_OF_CHARS];
auto result = to_chars(chars, chars + sizeof(chars), f);
float g;
from_chars(chars, result.ptr, g);
assert(f == g);
That guarantee is actually kind of hard to implement, and none of the standard library C or C++ float-to-string-to-float functions have ever provided that guarantee. So you can't just take code from printf/scanf
or stof/to_string
, rip out the locale stuff, and call that a to/from_chars
implementation.
This is half-answer, half-question:
I found a discussion thread about the topic that mentioned the requirement
The string representation consists of the smallest number of characters such that there is at least one digit before the radix point (if present) and parsing the representation using the corresponding std::from_chars function recovers value exactly
But that is not supported by the C library. However, if the wording had been at least the number of characters needed for a correct roundtrip, then I guess
std::lock_guard l{local_mutex};
auto loc = setlocale(LC_ALL, nullptr);
setlocale(LC_ALL, "C");
char buffer[24]{};
sprintf(buffer, "%.17g", val); // change to 9 for float
setlocale(LC_ALL, loc);
should work. Am I correct here?
© 2022 - 2024 — McMap. All rights reserved.