double atof(string_view str);
int atoi(string_view str);
long atol(string_view str);
long long atoll(string_view str);
long strtol(string_view str, string_view& tail, int base);
long strtol(string_view str, int base);
long long strtoll(string_view str, string_view& tail, int base);
long long strtoll(string_view str, int base);
long strtoul(string_view str, string_view& tail, int base);
long strtoul(string_view str, int base);
long long strtoull(string_view str, string_view& tail, int base);
long long strtoull(string_view str, int base);
std::intmax_t strtoimax(string_view str, string_view& tail, int base);
std::intmax_t strtoimax(string_view str, int base);
std::uintmax_t strtoumax(string_view str, string_view& tail, int base);
std::uintmax_t strtoumax(string_view str, int base);
float strtof(string_view str, string_view& tail);
float strtof(string_view str);
double strtof(string_view str);
double strtof(string_view str, string_view& tail);
long double strtof(string_view str);
long double strtof(string_view str, string_view& tail);
The alternative is redesigning a completely new str to number API and there was a big discussion about this a while ago with debates about return values, out parameters, optional, expected, and exceptions. That's probably the best solution in the long run but it might take a long time to get it right. In the meantime, we could at least maintain status quo and have some way of doing str to number conversions using string_view.
These could also be built on top of lower level primitives like this:
float atof_l(const char* str, size_t len);The above could also be added to the C standard, allowing anyone building a higher level language ontop of C to use non-null terminated strings.
--
--- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
Now that we have string_view, it might be a good idea to have overloads of atoX and strtoX which take string_view arguments.
string_view s = /*something */
auto i = strto<int>(s);
auto f = strto<float>(s);
//Parses str as a base base integer and stores the result in target.
//tail will point to the tail of the string after the last character
//If successful, returns a default constructed error_code.
//If an error occurs, the error will be stored in the error code (Specification TBD) and target will be left unmodified.
template <typename Integral>
error_code to_number(Integral& target, string_view& tail, string_view str, int base);
template <typename Integral>
error_code to_number(Integral& target, string_view str, int base) {
string_view tail;
return to_number(target, tail, str, base);
}
template <typename Integral>
Integral to_number(error_code& ec, string_view& tail, string_view str, int base, Integral ret_on_error = Integral{}) {
Integral val = ret_on_error;
ec = to_number(val, tail, str, base);
return val;
}
template <typename Integral>
Integral to_number(string_view& tail, string_view str, int base, Integral ret_on_error = Integral{}) {
error_code ec; return to_number(ec, tail, str, base, ret_on_error);
}
template <typename Integral>
Integral to_number(error_code& ec, string_view str, int base, Integral ret_on_error = Integral{}) {
string_view tail; return to_number(ec, tail, str, base, ret_on_error);
}
template <typename Integral>
Integral to_number(string_view str, int base, Integral ret_on_error = Integral{}) {
string_view tail;
error_code ec;
return to_number(ec, tail, str, base, ret_on_error);
}
string_view s = "1234,5678";
int x, y;
if(auto ec = to_number(x, s, s, 10)) {
//handle error
}
s.remove_prefix(1); //skip the ,
if(auto ec = to_number(y, s, s, 10)) {
//handle error
}
assert(s.empty());
//x is set to the parsed integer on success, or -1 on failure
auto x = to_number<int>(s, 10, -1);
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
Then why not go the whole route and make it to_string/from_string and not limit it just to numbers?
On Tue, Sep 30, 2014 at 3:03 PM, Miro Knejp <miro....@gmail.com> wrote:Then why not go the whole route and make it to_string/from_string and not limit it just to numbers?
`to_string` is not really an efficient interface to me. Writing to an output iteratorshould be the generic interface for formatting individual objects to strings.
template <typename N>
optional<N> to_integral(string_view str, int base = 10,
const char **endptr = nullptr);
template <typename N>
optional<N> to_floating_point(string_view str, const char **endptr = nullptr);
The conversion can fail and bases don't make sense for floating-point.
Then why not go the whole route and make it to_string/from_string and not limit it just to numbers?
I have a few issues with optional:
- You lose the ability to check specific error conditions like ERANGE. I'm not sure how useful this is as I've never done an ERANGE check on a number parse but that functionality is available with the legacy functions.
- If you want to enable a throwing interface by just calling optional::value() and letting it throw on error, you'll be throwing a std::bad_optional_access. It would be better to throw an exception class which is more specifically related to parsing numbers and has information on what went wrong.
On Tuesday 30 September 2014 19:13:40 Matthew Fioravante wrote:
> 1. You lose the ability to check specific error conditions like ERANGE.
> I'm not sure how useful this is as I've never done an ERANGE check on a
> number parse but that functionality is available with the legacy
> functions.
I don't see how that relates to the optional. In fact, I don't see how you
came to this conclusion.
If the parsing failed, the function will return a disengaged optional and set
errno to ERANGE or EINVAL. If it worked, it will return an engaged optional
and errno is unspecified.
That's much better than strtoul, which returns zero when it fails and that's
undistinguishable from a successful parsing of a number zero.
> 2. If you want to enable a throwing interface by just calling
> optional::value() and letting it throw on error, you'll be throwing a
> std::bad_optional_access. It would be better to throw an exception class
> which is more specifically related to parsing numbers and has information
> on what went wrong.
I again don't understand why that is a problem. What's stopping you from
throwing an exception if the returned optional is disengaged?
try {
auto x = string_to<int>(s);
foo(x.value());
}
catch(std::range_error& e) { /* do something */ }
catch(std::invalid_argument& e) { /*do something else*/ }
try {
auto x = string_to<int>(s);
foo(x.value());
}
catch(std::system_error& e) {
if(e.code() == ERANGE) { /* do something */ }
else if(e.code() == EINVAL) { /* do something else */ }
}
> Also I think its better to use a string_view& for the tail instead of a
> char**. The tail string itself is not null terminated so using a character
> pointer with which we usually associate null termination is a big
> misleading. Also converting the char** endptr back into a string_view is
> clumsy and error prone as it will call strlen() on the non-null terminated
> buffer unless the programmer carefully computes and specifies the new
> length.
Yeah, that makes sense. I was pondering that when I wrote the suggestion, but
didn't go through with it.
> I'd also like to try to make the integer conversions constexpr so setting
> errno is out.
Forget it. Non-inline functions can't be constexpr and those functions
shouldn't be inline.
On Tuesday, September 30, 2014 10:40:50 PM UTC-4, Thiago Macieira wrote:
Forget it. Non-inline functions can't be constexpr and those functions
shouldn't be inline.I agree about the floating point conversions. But does it really have to be this way for integer conversions? Parsing ints is not that complex.
> Are we sure we want to continue using global errno in new interfaces? Is
> this still a good way to specify errors? Maybe its ok for checking return
> codes, but definitely not for exceptions.
Why not? I don't see the problem with errno (which is actually thread-specific,
not global).
error_code string_to(int& i, string_view& tail, string_view s);
int string_to(error_code& ec, string_view& tail, string_view s);
expected<int,error_code> string_to(string_view& tail, string_view s);
bool string_to(int& i, string_view& tail, string_view s); //sets errno on failure
int string_to(string_view& tail, string_view s); //sets errno on failure
optional<int> string_to(string_view& tail, string_view s); //sets errno on failure
> If the optional object throws an exception, and then during the unwinding
> process something resets errno you lose the error information. The error
> code must be embedded in the exception object itself.
If something threw an exception, whether it was by consumption of the
disengaged optional or something else, the number conversion is long
forgotten. How useful is the "number out of range" information three frames up
the stack?
No, if there was a failure in converting, the code that may want to throw
needs to inspect errno and decide which meaningful exception it will throw.
> Why impose the boilerplate of throwing onto the user?
Simple: so that people who don't use exceptions can still use this function.
Despite the direction the standard committee wants to go in, practice is that
there are large and well-known C++ projects that don't use exceptions (see the
Google coding guidelines, applying to Chrome/Chromium, Blink, V8, the Mozilla
coding guidelines, Qt, etc.).
You can easily turn code that uses errno into one that throws in case of
failure, but you can't compile code reporting errors via exceptions with -fno-
exceptions and still report the errors.
I think that trying to make them constexpr is optimising for the corner-case
to the detriment of the vast majority of the common-case.
On Wednesday 01 October 2014 06:22:08 Matthew Fioravante wrote:
> > Why not? I don't see the problem with errno (which is actually
> > thread-specific,
> > not global).
>
> The alternative to errno is to use std::error_code and return it somehow
> either via an out parameter, return value (using out param for the int), or
> packaged as part of something like optional / expected / pair / tuple.
Does this std::error_code exist already?
Though I think that having a class enum so we can properly separate errors
from other uses of integers would be nice. Just as long as the error codes
remain 1:1 with errno.
> error_code string_to(int& i, string_view& tail, string_view s);
> int string_to(error_code& ec, string_view& tail, string_view s);
> expected<int,error_code> string_to(string_view& tail, string_view s);
>
> bool string_to(int& i, string_view& tail, string_view s); //sets errno on
> failure
> int string_to(string_view& tail, string_view s); //sets errno on failure
> optional<int> string_to(string_view& tail, string_view s); //sets errno on
> failure
The tail should be optional. Therefore, it can't be a reference. All those
options are out in my book.
int string_to<int>(string_view& tail, string_view s);
int string_to<int>(string_view s) { string_view tail; return string_to<int>(tail, s); }
> > If something threw an exception, whether it was by consumption of the
> > disengaged optional or something else, the number conversion is long
> > forgotten. How useful is the "number out of range" information three
> > frames up
> > the stack?
>
> If my program crashes due to an uncaught exception, "Number of out range"
> is a lot more useful to me than "disengaged optional".
That assumes that you did not attempt to correct the error. That is, your code
has a bug: either you did not validate your input prior to the parsing or you
failed to handle the parser errors.
I was thinking of normal error conditions, when you did catch the possible
errors and report them properly. If the input is allowed to fail parsing to
integral value, then you need to report that in the right way to your caller.
optional<T> either has a value of type T or it doesn't have anything.
expected<T, E> either has a value of type T or a value of type E to describe why the former isn't there (and it happens that E defaults to std::exception_ptr).
Maybe the details have changed again, I don't remember how long it's been that I read a proposal/draft/whatever.
template <typename T, typename Error, typename Exception>
struct expected {
public:
T& value() { if(has_error()) throw Exception(_error); return _val;}
T value_or(T def) return has_error() ? def : _val; }
//...
private:
T _val;
Error _err;
};
class conversion_error : public exception {};
template <typename T> using stoiret = expected<T,error_code,conversion_error>;
template <typename T>
stoiret<T> string_to(string_view& tail, string_view s);
My suggestion is to *carefully anticipate* the existence of expected and optional in 3 years. If it turns out not to be the case halfway down the road one can still design a helper type for the return values.
Doesn't std::(i)strstream already handle these conversions quite nicely? How about just un-deprecating that and maybe adding a (c)string_view constructor?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.