
on Sun Feb 08 2009, Andrey Semashev <andrey.semashev-AT-gmail.com> wrote:
David Abrahams wrote:
on Sun Feb 08 2009, Ben Muzal <bmuzal-AT-gmail.com> wrote:
In fact, if we put together all the badly needed functionality that overlaps with lexical_cast, and give it appropriate interfaces, I'm not entirely convinced that there would be much use for lexical_cast anymore.
Really what is with all of the "slippery slope" arguments?
That's not my concern. My concern is that I don't think lexical_cast is a particularly good interface for its main uses, which could be thought of as "to-string" and "from-string."
I disagree. lexical_cast was designed to be simple to use, and I think it does it very well. The "to-string" and "from-string" conversions, in their simple form, are just corner cases.
Eh? What other uses has it got?!
If I want to simply parse an int, I don't want to make up a Spirit grammar for that or even use scanf.
scanf is *way* lighter weight that lexical_cast.
I need a C++-style of strtol, which is safe in terms of buffer allocation and types.
So write that.
This is what lexical_cast tries to achieve and it does, to some degree. I don't know of any other tools that come this close to this goal, neither in Boost, nor outside of it.
So write one (just my opinion). lexical_cast means something very strange and overly-general, and we should write something targeted at the real-world uses people actually have.
People are not asking for the kitchen sink. We just want a nothrow version of the cast and to do that, a default value is needed.
I wouldn't say that. boost::optional is another option. In fact, if boost::optional doesn't already provide the exact streaming operator you need, I'd be a little surprised. If it has no streaming operator, we could consider adding the needed one. If it has the wrong streaming operator, it would be pretty easy to invent template nothrow, such that you can write
optional<Foo> = lexical_cast<nothrow<Foo> >( something )
I've already expressed myself on this. I just want to add that optional does define its streaming operators, and the way they work is no compatible with the goal we're trying to achieve with this extension.
Then it's easy enough to define the derived template that *is* compatible... although as I've said before I don't think lexical_cast is the right tool for this job anyway.
Lots of times there are cases when a default value simply will not be acceptable, but quite often one will. Why can't it be easy to support both models?
I just don't think lexical_cast is the interface we need for most convenient string conversions.
Do you have a better interface in mind?
It would take some thought and discussion to perfect, but just off the top of my head, I'd want something like this: namespace str { template <class T> struct value { operator T() const; // throws iff parse unsuccessful bool parsed() const; // true iff parse succecssful ... }; template <class String, class T> string::value<T> string::as<T>(String const&); template <class String, class T> typename enable_if<is_integral<T>, string::value<T> >::type string::as<T>(String const&, unsigned base); template <class T> std::string to_str(T const& x); template <class String, class T> String to_str(T const& x); }
I had not even heard of the <optional> library until reading this thread. I might update my little boost extension after checking to see how <optional> affects performance and code bloat -- but really, <optional> looks rather more complicated than necessary.
It has exactly the right semantics, and it tells you more than the version with the default does. With the default, you can't tell whether there was any valid input there or not, because the value represented in the input could be the same as the default.
The point is, often I don't care if the default was actually read from the string or taken from the argument.
Yes, but sometimes you will. -- Dave Abrahams BoostPro Computing http://www.boostpro.com