Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++17 Purpose of std::from_chars and std::to_chars?

Before C++17, there existed a variety of methods to convert integers, floats, and doubles to and from strings. For example, std::stringstream, std::to_string, std::atoi, std::stoi, and others could have been used to accomplish these tasks. To which, there exists plenty of posts discussing the differences between those methods.

However, C++ 17 has now introduced std::from_chars and std::to_chars. To which, I'd like to know the reasons for introducing another means of converting to and from strings.

For one, what advantages and functionality do these new functions provide over the previous methods?

Not only that, but are there any notable disadvantages for this new method of string conversion?

like image 910
Rabster Avatar asked Apr 26 '19 23:04

Rabster


People also ask

Why do we use std :: string?

std::string class in C++ C++ has in its definition a way to represent a sequence of characters as an object of the class. This class is called std:: string. String class stores the characters as a sequence of bytes with the functionality of allowing access to the single-byte character.

What is std :: STOF?

std::stof in C++ idx : Pointer to an object of type size_t, whose value is set by the function to position of the next character in str after the numerical value. This parameter can also be a null pointer, in which case it is not used.

How do I convert a string to an int in C++?

One effective way to convert a string object into a numeral int is to use the stoi() function. This method is commonly used for newer versions of C++, with is being introduced with C++11. It takes as input a string value and returns as output the integer version of it.

Why do we need from_chars in C++17?

And with C++17 you get another option: std::from_chars! Wasn’t the old stuff good enough? Why do we need new methods? In short: because from_chars is low-level, and offers the best possible performance. The new conversion routines are: The API might not be the most friendly to use, but it’s easy enough to wrap it into some facade.

Why do we need from_chars() function in C++?

This is intended to allow the fastest possible implementation that is useful in common high-throughput contexts such as text-based interchange (JSON or XML). The guarantee that std::from_chars can recover every floating-point value formatted by std::to_chars exactly is only provided if both functions are from the same implementation.

What's new in C++ 17 for converting to and from strings?

However, C++ 17 has now introduced std::from_chars and std::to_chars. To which, I'd like to know the reasons for introducing another means of converting to and from strings. For one, what advantages and functionality do these new functions provide over the previous methods?

What is from_chars_result in C++?

from_chars_result holds valuable information about the conversion process. ptr points at the first character not matching the pattern, or has the value equal to last if all characters match and ec is value-initialized. ptr equals first and ec equals std::errc::invalid_argument. value is unmodified.


Video Answer


3 Answers

std::stringstream is the heavyweight champion. It takes into consideration things like the the stream's imbued locale, and its functionality involves things like constructing a sentry object for the duration of the formatted operation, in order to deal with exception-related issues. Formatted input and output operations in the C++ libraries have some reputation for being heavyweight, and slow.

std::to_string is less intensive than std::istringstream but it still returns a std::string, whose construction likely involves dynamic allocation (less likely with modern short string optimization techniques, but still likely). And, in most cases the compiler still needs to generate all the verbiage, at the call site, to support a std::string object, including its destructor.

std::to_chars are designed to have as little footprint as possible. You provide the buffer, and std::to_chars does very little beyond actually formatting the numeric value into the buffer, in a specific format, without any locale-specific considerations, with the only overhead of making sure that the buffer is big enough. Code that uses std::to_chars does not need to do any dynamic allocation.

std::to_chars is also a bit more flexible in terms of formatting options, especially with floating point values. std::to_string has no formatting options.

std::from_chars is, similarly, a lightweight parser, that does not need to do any dynamic allocation, and does not need to sacrifice any electrons to deal with locale issues, or overhead of stream operations.

like image 68
Sam Varshavchik Avatar answered Oct 21 '22 23:10

Sam Varshavchik


to/from_chars are designed to be elementary string conversion functions. They have two basic advantages over the alternatives.

  1. They are much lighter weight. They never allocate memory (you allocate memory for them). They never throw exceptions. They also never look at the locale, which also improves performance.

    Basically, they are designed such that it is impossible to have faster conversion functions at an API level.

    These functions could even be constexpr (they aren't, though I'm not sure why), while the more heavyweight allocating and/or throwing versions can't.

  2. They have explicit round-trip guarantees. If you convert a float/double to a string (without a specified precision), the implementation is required to make it so that taking that exact sequence of characters and converting it back into a float/double will produce a binary-identical value. You won't get that guarantee from snprintf, stringstream or to_string/stof.

    This guarantee is only good however if the to_chars and from_chars calls are using the same implementation. So you can't expect to send the string across the Internet to some other computer that may be compiled with a different standard library implementation and get the same float. But it does give you on-computer serialization guarantees.

like image 41
Nicol Bolas Avatar answered Oct 21 '22 23:10

Nicol Bolas


All these pre-existing methods were bound to work based on a so-called locale. A locale is basically a set of formatting options that specify, e.g., what characters count as digits, what symbol to use for the decimal point, what thousand's separator to use, and so on. Very often, however, you don't really need that. If you're just, e.g., reading a JSON file, you know the data is formatted in a particular way, there is no reason to be looking up whether a '.' should be a decimal point or not every time you see one. The new functions introduced in <charconv> are basically hardcoded to read and write numbers based on the formatting laid out for the default C locale. There is no way to change the formatting, but since the formatting doesn't have to be flexible, they can be very fast…

like image 4
Michael Kenzel Avatar answered Oct 21 '22 22:10

Michael Kenzel