Subject: Re: [boost] Boost.Convert. Take 2.
From: Vladimir Batov (Vladimir.Batov_at_[hidden])
Date: 2014-02-10 16:22:56
Andrzej, thank you for your input. It's much appreciated. Please find my
On 02/11/2014 05:12 AM, Andrzej Krzemienski wrote:
> There are at least two reasons why I would prefer your library to
> lexical_cast. First, it lets me customize the locale, which I was always
> missing. Second, it doesn't force me to throw exceptions (and make the
> program go slower, if I just want to test if my string is convertible to
Same here. I had no choice but to unfortunately put boost::lexical_cast
aside as my classes did not have DefaultConstructibility, I needed
formatting and our conversion failures were not exceptional to warrant
exceptions. Back then I tried hard to persuade boost::lexical_cast
extended. I guess its original designers and maintainers had their
reasons not to extend the class to provide the functionality I
> But there are two reasons, that discourage me from using the library: first
> that it "pretends" it returns my T, whereas in fact it returns a wrapper
> convertible to T.
Well, with all due respect I have to disagree here. convert<T> does not
pretend to return T, it returns convert<T>::result. Yes, indeed, to this
day convert<T>::result still has an implicit converter to T. However,
it's a mere convenience -- I only have it because I use it all the time
for simple conversions:
int a = convert<int>::from(not_int_str, -1, ccnv);
If there is a strong feeling that it needs to be disabled, then so be
it. I'll be just fine with explicit
int a = convert<int>::from(not_int_str, -1, ccnv).value();
Still, I think I do understand where your "that it pretends it returns
my T" actually comes from. IMO the user has been spoiled (and misled) by
boost::lexical_cast, by its seeming simplicity -- give it a string, get
a converted T back. Yes, the only problem is that boost::lexical_cast
was/is able to do that because it by-design casts out *many*
conversion-related use-cases -- the reason I had to stop using it in the
first place. convert<T> takes a different -- all-inclusive -- approach
and, therefore, can only return something that might have a converted
value or it might not, i.e. something like Alexandrescu's Expected<T>,
boost::optional, tr1::optional, convert<T>::result. I hope after A.
Alexandrescu presentation on Expected<T> our programming community is
more open to and more mature to *accept* that sometimes a conversion
*request* cannot return T... even though boost::lexical_cast does it. :-)
> Users will get a lot of surprise, when they try to write:
> auto my_str = convert<std::string>::from(1, ..);
Yes... if they choose not to read the documentation. :-) ... and that's
relevant to any library, isn't it? Again, IMO the actual source or
(perceived) potential confusion here is the false expectation that
convert<T> must return T... like lexical_cast does. I do not believe
it's possible. I hope with people getting accustomed with A.
Alexandrescu's Expected<T> they'll be more open for return classes with
> Also, I am likely to select an incorrect function overload, if I pass the
> result to the function template.
Again, if there is enough conviction behind the implicit conversion
causing havoc, it's no drama to take it out. Will it solve the problem
> Second thing that bothers me is that for the result type to be able to
> offer all these checks an otherwise unnecessary runtime overhead is
> imposed. 'result' stores both optional<T> and a flag indicating how to deal
> with the lack of value. since, in order to write into T you need to
> default-construct it anyway (or move construct it), it looks it should be
> enough to have 'result' contain a non-optional T and more sophisticated
> flag that also stores the information about having a real T.
Well, I have to disagree about "unnecessary checks". If one does not
need checks, then boost::lexical_cast will suffice. As for the current
implementation, then I consider it a rough draft and an implementation
detail which I am not focusing on right now. Your suggestion might well
be the ultimate way to go. I think, we need to get the fundamentals
> I would like to suggest two things:
> 1. Would it not be possible to have an overload that does not take the
> stream object? It would mean we want to use some default char-based stream
> with any locale. The newbies would not have to bother with what it is, when
> they only want to convert an int to a string?
In the code I used/required explicit converter. In actual code the
converter is defaulted to the one I listed explicitly. Will it suffice?
> 2. Would it be possible to consider returning tr2::optional instead of
> 'result'? It is different than boost::optional in a couple of aspects.
> After a lots of changes, the
> final shape of it is here:
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3793.html and the
> reference implementation is here: https://github.com/akrzemi1/Optional
I am very much looking forward to optional being standardized and I'll
re-read the proposal. I started using optional more in my code and I
can't stop now. :-) Managing without it was a real pain with
cut-n-pasted half-baked solutions in relevant classes. Currently I am
using boost::optional as in production we are quite behind -- still
supporting gcc-3.3! So, some things are not available to me right now. I
am sure, if there is enough interest generated in convert<T>, we'll have
to think of a much better implementation.
> tr2::optional offers 4 ways of dealing with the missing (unset) value:
> First: if (rslt) use (*rslt); // check it manually
> Second: use (rslt.value_or(1)); // use default value
> Third: use (rslt.value()); // throw if no value
> Fourth: use (*rslt); // use without checks
> the fourth result is not to be underestimated. Sometimes I am sure my int
> will successfully convert to a string, and I do not want to pay the price
> for an extra check.
> Returning an optional would somehow separate responsibilities: conversion
> function only converts, and optional is a well-understood general-purpose
> wrapper for dealing with a potentially missing value.
> I am pretty sure we could adapt boost::optional to tr2::optional's
> Or are there reasons not to use optional?
Well, I personally do not see any reasons *not* to use optional... in
fact, I use it inside convert<T>::result... well, not tr1::optional yet.
If I see that tr1::optional can do all convert<T>::result does, I'll
switch without hesitation.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk