[conversion] try_lexical_cast and 200$
There is a bounty for implementing a `try_lexical_cast` from Facebook: https://www.bountysource.com/issues/1352296-exceptionless-lexical_cast Because of that three questions arise: * Is there some official policy for "feature implementation sponsorship"? * `try_lexical_cast` must be added or not? And if yes, what signature is preffered: bool try_lexical_cast<Out, In>(Out&, const In&) bool try_lexical_cast<Out, In>(const In&, Out&) boost::optional<Out> try_lexical_cast<Out, In>(const In&) * Is there a bank account "for Boost's needs" that is used to do hosting payments, conference room rental payments and other support stuff (to were those 200$ may be transfered)? -- Best regards, Antony Polukhin
AMDG On 12/11/2013 12:36 PM, Antony Polukhin wrote:
There is a bounty for implementing a `try_lexical_cast` from Facebook: https://www.bountysource.com/issues/1352296-exceptionless-lexical_cast
Because of that three questions arise:
* Is there some official policy for "feature implementation sponsorship"?
* `try_lexical_cast` must be added or not?
There's no necessity either way. You're the maintainer, right? Personally, I'm a bit unhappy about this trend of creating parallel API's that throw or report an error in some other way.
And if yes, what signature is preffered:
bool try_lexical_cast<Out, In>(Out&, const In&) bool try_lexical_cast<Out, In>(const In&, Out&) boost::optional<Out> try_lexical_cast<Out, In>(const In&)
* Is there a bank account "for Boost's needs" that is used to do hosting payments, conference room rental payments and other support stuff (to were those 200$ may be transfered)?
It's handled by the Software Freedom Conservancy. (nit: it's $200, not 200$) In Christ, Steven Watanabe
2013/12/12 Steven Watanabe <watanabesj@gmail.com> <...>
Personally, I'm a bit unhappy about this trend of creating parallel API's that throw or report an error in some other way.
I had exactly the same opinion two years ago. Original developer of lexical_cast had the same opinion. But now I have code like this one: // Function that maps to some query language method inline boost::variant<double, error_t> to_double(std::string const& val) { double ret; std::istringstream ss(val); ss >> ret; if (ss.fail() || !ss.eof()) return error_t("'to_double' function called for value '" + val + "'"); return ret; } A lot of people, including me, would prefer to have the following: inline boost::variant<double_t, error_t> to_double(std::string const& val) { double ret; if (!try_lexical_cast(val, ret)) return error_t("'to_double' function called for value '" + val + "'"); return ret; } Such method would also allow to use lexical_cast library for non default constructible types. While I sill dislike the idea of having additional overload. That's why I've asked for comments. -- Best regards, Antony Polukhin
Antony Polukhin wrote:
* `try_lexical_cast` must be added or not?
The motivation given is convincing. "At Facebook we've seen many instances of programs that call lexical_cast in a try/catch. In cases where the parsing is expected to fail (eg, an argument could be an int or a date) we frequently see extremely poor performance in multithreading. GCC is known to have poor multithreaded exception handling gcc.gnu.org/ml/gcc/2013-05/msg00253.html" Even without the performance argument, seeing repeated occurrences of calling a function in a try block is a strong hint that the function perhaps ought to not report the error via an exception.
And if yes, what signature is preffered:
bool try_lexical_cast<Out, In>(Out&, const In&) bool try_lexical_cast<Out, In>(const In&, Out&) boost::optional<Out> try_lexical_cast<Out, In>(const In&)
bool try_lexical_cast<In, Out>(const In&, Out&), I'd say. optional<> is cute because you can use if( auto x = try_lexical_cast<Out>(in) ), but not very convenient for the common case of try_lexical_cast(in1, out1) && try_lexical_cast(in2, out2).
On 12/12/2013 18:41, Quoth Peter Dimov:
"At Facebook we've seen many instances of programs that call lexical_cast in a try/catch. In cases where the parsing is expected to fail (eg, an argument could be an int or a date) we frequently see extremely poor performance in multithreading. GCC is known to have poor multithreaded exception handling gcc.gnu.org/ml/gcc/2013-05/msg00253.html"
+1
And if yes, what signature is preffered:
bool try_lexical_cast<Out, In>(Out&, const In&) bool try_lexical_cast<Out, In>(const In&, Out&) boost::optional<Out> try_lexical_cast<Out, In>(const In&)
bool try_lexical_cast<In, Out>(const In&, Out&), I'd say.
+1
optional<> is cute because you can use if( auto x = try_lexical_cast<Out>(in) ), but not very convenient for the common case of try_lexical_cast(in1, out1) && try_lexical_cast(in2, out2).
Optional would work in that case too, eg: if ((out1 = try_lexical_cast<T1, U1>(in1)) && (out2 = try_lexical_cast<T2, U2>(in2))) { // both casts worked, do something with out1 and out2 } else { // at least one failed, can inspect to determine which } Having said that, I would probably look funny at anyone who wrote that code for real, since inline assignments tend to confuse people and are often accidental. Also having to specify both types is more annoying than in the bool form, where the compiler can infer the parameters. (I'm not really a fan of output parameters either, but c'est la vie.) On the other hand, if it's not going to resemble "result = name<T>(source)" then it's not very cast-like, so the name seems a little odd now. But not enough to bother me much. :)
On 12/11/2013 10:34 PM, Gavin Lambert wrote:
On 12/12/2013 18:41, Quoth Peter Dimov:
<snip>
optional<> is cute because you can use if( auto x = try_lexical_cast<Out>(in) ), but not very convenient for the common case of try_lexical_cast(in1, out1) && try_lexical_cast(in2, out2).
Optional would work in that case too, eg:
if ((out1 = try_lexical_cast<T1, U1>(in1)) && (out2 = try_lexical_cast<T2, U2>(in2))) { // both casts worked, do something with out1 and out2 }
<snip>
Also having to specify both types is more annoying than in the bool form, where the compiler can infer the parameters.
(I'm not really a fan of output parameters either, but c'est la vie.)
On the other hand, if it's not going to resemble "result = name<T>(source)" then it's not very cast-like, so the name seems a little odd now. But not enough to bother me much. :)
You still just write: out1 = try_lexical_cast<T1>(in1) where the type of out1 is optional<T1> and the type of in1 is deduced. -- Michael Caisse ciere consulting ciere.com
On 12/12/2013 19:45, Quoth Michael Caisse:
On 12/11/2013 10:34 PM, Gavin Lambert wrote:
Also having to specify both types is more annoying than in the bool form, where the compiler can infer the parameters.
You still just write:
out1 = try_lexical_cast<T1>(in1)
where the type of out1 is optional<T1> and the type of in1 is deduced.
I thought that ought to work, but I wrote a toy example and it didn't, which is why I phrased it like that. Thinking back on it now I realise what the problem was: On 12/12/2013 18:41, Quoth Peter Dimov:
Antony Polukhin wrote:
And if yes, what signature is preffered:
bool try_lexical_cast<Out, In>(Out&, const In&) bool try_lexical_cast<Out, In>(const In&, Out&) boost::optional<Out> try_lexical_cast<Out, In>(const In&)
bool try_lexical_cast<In, Out>(const In&, Out&), I'd say.
Inference requires the <Out, In> ordering of template parameters (for the optional version; it doesn't matter for the bool version). I had them wrong when testing my toy. My apologies for the noise.
On Thu, Dec 12, 2013 at 9:41 AM, Peter Dimov <lists@pdimov.com> wrote:
Antony Polukhin wrote:
* `try_lexical_cast` must be added or not?
The motivation given is convincing.
"At Facebook we've seen many instances of programs that call lexical_cast in a try/catch. In cases where the parsing is expected to fail (eg, an argument could be an int or a date) we frequently see extremely poor performance in multithreading. GCC is known to have poor multithreaded exception handling gcc.gnu.org/ml/gcc/2013-05/msg00253.html"
Even without the performance argument, seeing repeated occurrences of calling a function in a try block is a strong hint that the function perhaps ought to not report the error via an exception.
And if yes, what signature is preffered:
bool try_lexical_cast<Out, In>(Out&, const In&) bool try_lexical_cast<Out, In>(const In&, Out&) boost::optional<Out> try_lexical_cast<Out, In>(const In&)
bool try_lexical_cast<In, Out>(const In&, Out&), I'd say. optional<> is cute because you can use if( auto x = try_lexical_cast<Out>(in) ), but not very convenient for the common case of try_lexical_cast(in1, out1) && try_lexical_cast(in2, out2).
I have no strong preference, but with optional it's a little easier to provide a default if the cast fails: int n = try_lexical_cast< int >(str).get_value_or(-1); But it adds a dependency on Boost.Optional. This syntax is also closer to casts, while the two-argument version looks like an ordinary function. If the two-argument version is chosen, maybe a better name should be chosen, like: template< typename From, typename To > bool lexical_convert(From&& from, To& to);
On Dec 12, 2013, at 12:41 AM, "Peter Dimov" <lists@pdimov.com> wrote:
Antony Polukhin wrote:
* `try_lexical_cast` must be added or not?
The motivation given is convincing.
"At Facebook we've seen many instances of programs that call lexical_cast in a try/catch. In cases where the parsing is expected to fail (eg, an argument could be an int or a date) we frequently see extremely poor performance in multithreading. GCC is known to have poor multithreaded exception handling gcc.gnu.org/ml/gcc/2013-05/msg00253.html"
Even without the performance argument, seeing repeated occurrences of calling a function in a try block is a strong hint that the function perhaps ought to not report the error via an exception.
That's a reasonable justification for the desired functionality.
And if yes, what signature is preffered:
bool try_lexical_cast<Out, In>(Out&, const In&) bool try_lexical_cast<Out, In>(const In&, Out&) boost::optional<Out> try_lexical_cast<Out, In>(const In&)
If it's to be a cast, optional is not unreasonable, but it is a bit awkward.
bool try_lexical_cast<In, Out>(const In&, Out&), I'd say.
I prefer output parameters to be first. It allows flexibility in adding arguments and even defaulting some. (As noted elsewhere, the template parameter order is wrong.) As others have noted, this function is no longer cast-style, so "cast" ought not to be part of the name. ___ Rob (Sent from my portable computation engine)
Rob Stewart wrote:
bool try_lexical_cast<In, Out>(const In&, Out&), I'd say.
I prefer output parameters to be first. It allows flexibility in adding arguments and even defaulting some.
I myself have put the output parameter of my "parse" example first, because it takes two inputs. So you certainly have a point.
2013/12/11 Antony Polukhin <antoshkka@gmail.com>
There is a bounty for implementing a `try_lexical_cast` from Facebook: https://www.bountysource.com/issues/1352296-exceptionless-lexical_cast
Because of that three questions arise:
* Is there some official policy for "feature implementation sponsorship"?
* `try_lexical_cast` must be added or not? And if yes, what signature is preffered:
bool try_lexical_cast<Out, In>(Out&, const In&) bool try_lexical_cast<Out, In>(const In&, Out&) boost::optional<Out> try_lexical_cast<Out, In>(const In&)
How about: boost::optional<Out> lexical_cast<Out, In>(const In&, std::nothrow_t) Whether this or try_lexical_cast, I prefer the function to return an optional. Regards, Kris
2013/12/12 Krzysztof Czainski <1czajnik@gmail.com> <...>
* `try_lexical_cast` must be added or not? And if yes, what signature is preffered:
bool try_lexical_cast<Out, In>(Out&, const In&) bool try_lexical_cast<Out, In>(const In&, Out&) boost::optional<Out> try_lexical_cast<Out, In>(const In&)
How about: boost::optional<Out> lexical_cast<Out, In>(const In&, std::nothrow_t)
This will break one of the use cases. For example there'll be an ambiguity beacause of function overloads.: std::transform( values.begin(), values.end(), ret.begin(), &boost::lexical_cast<std::string, int> ); -- Best regards, Antony Polukhin
On Thu, Dec 12, 2013 at 6:11 AM, Antony Polukhin <antoshkka@gmail.com>wrote:
2013/12/12 Krzysztof Czainski <1czajnik@gmail.com>
How about: boost::optional<Out> lexical_cast<Out, In>(const In&, std::nothrow_t)
This will break one of the use cases. For example there'll be an ambiguity beacause of function overloads.:
std::transform( values.begin(), values.end(), ret.begin(), &boost::lexical_cast<std::string, int> );
You can still have that interface, not break existing code, and make it easy to do similar stuff with the nothrow version. A little hackish, but: http://codepaste.net/py5ot3 -- -Matt Calabrese
On 12/12/2013 9:35 AM, Matt Calabrese wrote:
A little hackish, but:
template< class T, int = 0, class S > boost::optional<T> lexical_cast( S const&, std::nothrow_t ); Is that even legal?! A non-defaulted template parameter after a defaulted one? <boggle> How will this fare on older compilers, I wonder. -- Eric Niebler Boost.org http://www.boost.org
On Thu, Dec 12, 2013 at 4:12 PM, Eric Niebler <eniebler@boost.org> wrote:
On 12/12/2013 9:35 AM, Matt Calabrese wrote:
A little hackish, but:
template< class T, int = 0, class S > boost::optional<T> lexical_cast( S const&, std::nothrow_t );
Is that even legal?! A non-defaulted template parameter after a defaulted one? <boggle> How will this fare on older compilers, I wonder.
Yeah. I think it's worked on GCC and Clang ever since they've supported defaults for function template parameters, but I could be mistaken. I don't know about other compilers. -- -Matt Calabrese
On 12/12/2013 4:31 PM, Matt Calabrese wrote:
On Thu, Dec 12, 2013 at 4:12 PM, Eric Niebler <eniebler@boost.org> wrote:
On 12/12/2013 9:35 AM, Matt Calabrese wrote:
A little hackish, but:
template< class T, int = 0, class S > boost::optional<T> lexical_cast( S const&, std::nothrow_t );
Is that even legal?! A non-defaulted template parameter after a defaulted one? <boggle> How will this fare on older compilers, I wonder.
Yeah. I think it's worked on GCC and Clang ever since they've supported defaults for function template parameters, but I could be mistaken. I don't know about other compilers.
Then well done. This would be my preferred interface for C++11. But what to do about older compilers? It's certainly a problem. -- Eric Niebler Boost.org http://www.boost.org
On Fri, Dec 13, 2013 at 11:31 AM, Matt Calabrese <rivorus@gmail.com> wrote:
On Thu, Dec 12, 2013 at 4:12 PM, Eric Niebler <eniebler@boost.org> wrote:
On 12/12/2013 9:35 AM, Matt Calabrese wrote:
A little hackish, but:
template< class T, int = 0, class S > boost::optional<T> lexical_cast( S const&, std::nothrow_t );
Is that even legal?! A non-defaulted template parameter after a defaulted one? <boggle> How will this fare on older compilers, I wonder.
Yeah. I think it's worked on GCC and Clang ever since they've supported defaults for function template parameters, but I could be mistaken. I don't know about other compilers.
Works under MSVC 2013 also.
AMDG On 12/12/2013 04:12 PM, Eric Niebler wrote:
On 12/12/2013 9:35 AM, Matt Calabrese wrote:
A little hackish, but:
template< class T, int = 0, class S > boost::optional<T> lexical_cast( S const&, std::nothrow_t );
Is that even legal?!
I believe so. Since S can be deduced, it doesn't have to be specified explicitly, so it doesn't make the default for the second argument useless.
A non-defaulted template parameter after a defaulted one? <boggle> How will this fare on older compilers, I wonder.
Older compilers won't accept default template parameters for function templates at all, since it's a C++11 feature. In Christ, Steven Watanabe
Krzysztof Czainski wrote:
Whether this or try_lexical_cast, I prefer the function to return an optional.
As I said, it's appealing, but I suspect that it will prove much less convenient in practice. struct X { int a; int b; }; bool parse( X& x, std::string a, std::string b ) { return try_lexical_cast( a, x.a ) && try_lexical_cast( b, x.b ); }
2013/12/12 Peter Dimov <lists@pdimov.com>
Krzysztof Czainski wrote:
Whether this or try_lexical_cast, I prefer the function to return an optional.
As I said, it's appealing, but I suspect that it will prove much less convenient in practice.
struct X { int a; int b; };
bool parse( X& x, std::string a, std::string b ) { return try_lexical_cast( a, x.a ) && try_lexical_cast( b, x.b );
}
True, but I don't think you should leave it that simple. When parsing of a succeeds, and parsing of b fails, you get x with new value of a, and old value of b. This may or may not be acceptable, and at the very least deserves a heads-up comment. Regards, Kris
Krzysztof Czainski wrote:
bool parse( X& x, std::string a, std::string b ) { return try_lexical_cast( a, x.a ) && try_lexical_cast( b, x.b ); }
True, but I don't think you should leave it that simple. When parsing of a succeeds, and parsing of b fails, you get x with new value of a, and old value of b.
Actually you get an unspecified value in x.b, I think. Which is mirrored in what parse does - you get an unspecified value in x when it fails. If you want a strong guarantee: bool parse( X& x, std::string a, std::string b ) { X x2; if( try_lexical_cast( a, x2.a ) && try_lexical_cast( b, x2.b ) ) { x = x2; return true; } else { return false; } } Note that try_lexical_cast providing that same strong guarantee of leaving "out" untouched on failure doesn't simplify the implementation of the strong parse.
I have a library under construction called "coerce" which covers this case and many more: http://svn.boost.org/svn/boost/sandbox/coerce/ with (currently somewhat out of date) documentation available at http://vexocide.org/coerce/. It's based on spirit but allows multiple backends and whilst it doesn't yet have an interface which accepts by reference this should be fairly trivial to add and is on the todo list. Unfortunately it's been a while since I had the time to work on it but with my study now out of the way I hope move it back to github and pick it up again. HTH, Jeroen On 11 December 2013 21:36, Antony Polukhin <antoshkka@gmail.com> wrote:
There is a bounty for implementing a `try_lexical_cast` from Facebook: https://www.bountysource.com/issues/1352296-exceptionless-lexical_cast
Because of that three questions arise:
* Is there some official policy for "feature implementation sponsorship"?
* `try_lexical_cast` must be added or not? And if yes, what signature is preffered:
bool try_lexical_cast<Out, In>(Out&, const In&) bool try_lexical_cast<Out, In>(const In&, Out&) boost::optional<Out> try_lexical_cast<Out, In>(const In&)
* Is there a bank account "for Boost's needs" that is used to do hosting payments, conference room rental payments and other support stuff (to were those 200$ may be transfered)?
-- Best regards, Antony Polukhin
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
On 12/11/2013 09:36 PM, Antony Polukhin wrote:
bool try_lexical_cast<Out, In>(Out&, const In&) bool try_lexical_cast<Out, In>(const In&, Out&) boost::optional<Out> try_lexical_cast<Out, In>(const In&)
Another possibility is to provide a parameter that is returned if the conversion fails, something like this: Out lexical_cast<Out, In>(const In& input, const Out& failed_output)
Thank you all for giving comments and ideas! Looks like it'll be `bool try_lexical_convert<Out, In>(const In&, Out&)`: * boost::optional version adds additional dependency + boost::optional does not support move semantics well, so it'll be hard to implement a very efficient try_lexical_convert with current boost::optional * returning bool looks like the simplest solution that can be easily adopted by user * output parameter is at the last position (like it is done in many Standard Library methods) * name contains "convert" instead of "cast", because function does not look like a cast -- Best regards, Antony Polukhin
On Friday 13 December 2013 15:51:20 Antony Polukhin wrote:
Thank you all for giving comments and ideas!
Looks like it'll be `bool try_lexical_convert<Out, In>(const In&, Out&)`:
* boost::optional version adds additional dependency + boost::optional does not support move semantics well, so it'll be hard to implement a very efficient try_lexical_convert with current boost::optional * returning bool looks like the simplest solution that can be easily adopted by user * output parameter is at the last position (like it is done in many Standard Library methods) * name contains "convert" instead of "cast", because function does not look like a cast
May I suggest that the first argument is an rvalue reference, and the function performs perfect forwarding to the operator<<? This is of course when rvalue references are available.
2013/12/13 Andrey Semashev <andrey.semashev@gmail.com>
On Friday 13 December 2013 15:51:20 Antony Polukhin wrote:
Thank you all for giving comments and ideas!
Looks like it'll be `bool try_lexical_convert<Out, In>(const In&, Out&)`:
* boost::optional version adds additional dependency + boost::optional does not support move semantics well, so it'll be hard to implement a very efficient try_lexical_convert with current boost::optional * returning bool looks like the simplest solution that can be easily adopted by user * output parameter is at the last position (like it is done in many Standard Library methods) * name contains "convert" instead of "cast", because function does not look like a cast
May I suggest that the first argument is an rvalue reference, and the function performs perfect forwarding to the operator<<? This is of course when rvalue references are available.
This may be useful for user defined types, but portably getting pointer to function in that case will be difficult. For try_lexical_convert first argument will be rvalue, but lexical_cast continue to accept parameters by const reference. -- Best regards, Antony Polukhin
participants (13)
-
Andrey Semashev
-
Antony Polukhin
-
Bjorn Reese
-
Eric Niebler
-
Gavin Lambert
-
Jeroen Habraken
-
Joshua Boyce
-
Krzysztof Czainski
-
Matt Calabrese
-
Michael Caisse
-
Peter Dimov
-
Rob Stewart
-
Steven Watanabe