What blocks implementation of std::to_chars and std::from_chars
Asked Answered
V

2

19

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.

Vase answered 6/9, 2019 at 16:9 Comment(3)
STL will actually give a talk at CppCon this year about (in part) how hard this ended up being: cppcon2019.sched.com/event/Sft8Satin
VC++ supports it, and has done so for a year or so..Headwaters
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. AFAIK these functions were proposed to move away from how we've done it in the past and move to a more efficient and lighter weight conversion utility.Sulfapyrazine
H
16

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.

Headwaters answered 6/9, 2019 at 16:28 Comment(5)
"requires that all implementations provide round-tripping guarantees" - according to cppreference: "The guarantee that std::from_chars can recover every floating-point value formatted by to_chars exactly is only provided if both functions are from the same implementation.". So at least an implementation only has to be able to roundtrip with itself.Triable
@NicolBolas Well, that is interesting. Isn't existence of implementation one of the main requirements for a feature to get into C++? Maybe the wording should have been "implementors are encouraged to make these functions roundtrip" for C++17, and then planned to change that wording to C++23. For my purposes, it would have been sufficient to get rid of the locale stuff, and also to specify the correct number of digits.Vase
@user877329: "Isn't existence of implementation one of the main requirements for a feature to get into C++?" You say that as though nobody has implemented it correctly. Which they have, as previously pointed out. Furthermore, a proposal has to be implementable, which those round trip guarantees very much are. Highly complex proposals generally need to have implementations before approval, but this isn't particularly complicated. It's hard to code, yes, but it is doable.Headwaters
@NicolBolas "You say that as though nobody has implemented it correctly." But you say that existing functions in C and C++ does not do it correctly, so you have to look somewhere else to find that implementation.Vase
@user877329: I said that because you said "if you refactor the C library to depend on common low-level routines that does the actual conversion base conversion into some intermediate format", which can't be done because of those guarantees. That fact doesn't mean that nobody has implemented these functions, just not in "the C library" or wherever.Headwaters
V
-1

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?

Vase answered 6/9, 2019 at 19:43 Comment(1)
"Am I correct here?" ... isn't that something you should answer yourself? The "Add An Answer" button is for answers, not questions. Prove that that will actually round-trip, and state what the input function it round-trips with will be. Also show how you would implement the other possible formatting parameters.Headwaters

© 2022 - 2024 — McMap. All rights reserved.