... 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 int). Same here. I had no choice but to unfortunately put boost::lexical_cast
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
Andrzej, thank you for your input. It's much appreciated. Please find my replies below. On 02/11/2014 05:12 AM, Andrzej Krzemienski wrote: 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 needed/requested. 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 = convertstd::string::from(1, ..); my_str.size(); 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 "expected" behavior.
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 you mention?
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 right first.
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 interface.
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.