std::from_chars
should work with std::string_view
Document #: | P2007R0 |
Date: | 2020-01-10 |
Project: | Programming Language C++ Library Evolution Working Group Incubator Library Evolution Working Group |
Reply-to: |
Mateusz Pusz (Epam Systems) <mateusz.pusz@gmail.com> |
std::from_chars
accepts only a pair of raw char
pointers in its overloads to provide a range of characters for conversion. The author proposes to add overloads taking std::string_view
which is the main C++ vocabulary type to denote a range of characters.
Unfortunately, it is common for an average C++ developer to provide the following implementation for converting a std::string_view
to int
via a std::from_chars
.
void foo(std::string_view txt)
{
int result;
auto [ptr, ec] = std::from_chars(txt.begin(), txt.end(), result);
if (ec == std::errc())
// ...
}
The above will work for some implementations and build modes but will fail for others. This is caused by the fact that even though some vendors implement std::string_view::const_iterator
in terms of const char*
, such code is not portable. The C++ standard specifies std::string_view::const_iterator
as implementation defined and only requires that the iterator’s value_type
is char
.
After realizing the portability issue programmers often fix it in the following way which is far from what we want to teach:
A correct approach works on the underlying data rather than on iterators which is counter intuitive as we always taught to use iterators to denote ranges in C++:
Before
|
After
|
---|---|
The proposed changes are relative to the working draft of the standard as of [N4830].
Add the following to the end of synopsis in 20.19.1 [charconv.syn]:
from_chars_result from_chars(string_view txt, see below& value, int base = 10);
from_chars_result from_chars(string_view txt, float& value, chars_format fmt = chars_format::general);
from_chars_result from_chars(string_view txt, double& value, chars_format fmt = chars_format::general);
from_chars_result from_chars(string_view txt, long double& value, chars_format fmt = chars_format::general);
Update the following paragraphs in 20.19.3 [charconv.from.chars]:
1 All functions named from_chars
analyze the provided string for a pattern, where string is either a [first, last)
txt
or [first, last)
denoting a valid range.[first, last)
is required to be
from_chars_result from_chars(const char* first, const char* last, float& value,
chars_format fmt = chars_format::general);
+ from_chars_result from_chars(string_view txt, float& value,
+ chars_format fmt = chars_format::general);
from_chars_result from_chars(const char* first, const char* last, double& value,
chars_format fmt = chars_format::general);
+ from_chars_result from_chars(string_view txt, double& value,
+ chars_format fmt = chars_format::general);
from_chars_result from_chars(const char* first, const char* last, long double& value,
chars_format fmt = chars_format::general);
+ from_chars_result from_chars(string_view txt, long double& value,
+ chars_format fmt = chars_format::general);
Special thanks and recognition goes to Epam Systems for supporting my membership in the ISO C++ Committee and the production of this proposal.
[N4830] Richard Smith. 2019. Committee Draft, Standard for Programming Language C++.
https://wg21.link/n4830