From: Terje Slettebø (tslettebo_at_[hidden])
Date: 2002-12-28 19:29:02
>From: "Early Ehlinger" <earlye_at_[hidden]>
> On the boost site for lexical_cast, a future direction is listed:
> "Optimize the use of a stream away for identity conversions."
> I recently encountered a situation where this optimization is not only
> from a performance perspective, but is also necessary from a functional
> Deep inside of some nested templates, I had some code that effectively did
> this due to the way the template parameters happened to play out in the
> client code:
> std::string source = "Hello there";
> std::string dest = boost::lexical_cast< std::string >( source );
> Normally, this would be a silly thing to do, but there are valid reasons
> that the template code in place ended up doing this. (Please take my word
> for it. It would likely take a month to go through the details of how I
> there...) Anyway, the surprising result of this was that the space in
> "Hello there" caused the interpreter.eof() check in lexical_cast to fail.
> So if that check were not present, dest would have been assigned the value
> "Hello". Fortunately, the check was there, and instead I got a
> bad_lexical_cast exception.
This issue comes up at regular intervals, since this is one of the known
problems of lexical_cast, but it hasn't yet been fixed. See e.g. this
A proposition has been made to fix this and other things
I'll get to update it properly, and write the docs for it, soon. It should
work correctly as it is, as it's been tested in an extensive unit test (also
found at the same place).
> Is this the way lexical_cast is intended to work?
No, Kevlin has acknowledged that this is a known problem with the current
version of lexical_cast, the handling of whitespace in strings and
> I don't know, but it
> certainly isn't what I found to be behavior that "feels right". So I
> whipped up a modification to lexical cast that uses a template class and
> overloaded static member functions to optimize calls like this.
> I've got the current lexical_cast code inside of
> boost::detail::lexical_caster<>::do_it<>, and provide a form of
> boost::detail::lexical_caster<>::do_it that is not a template and accepts
> the same type as the target of the cast.
> lexical_cast returns the result of boost::detail::lexical_caster< Target
> >::do_it( object ). If object is of the type Target, then the
> overload of ...::do_it is called, otherwise, the behavior is identical to
> the current behavior.
> I don't know if the community wants the new behavior or would prefer to
> the old (and in my humble opinion, surprising) behavior. In either case,
> thought I'd share my efforts. Any feedback is greatly appreciated.
Your solution is quite similar to the one in the other proposition,
actually. Your uses overloading, while the other one uses class template
specialisation. That's done because partial specialisation is also used, for
other special cases.
Your overloading solution is elegant. However, there are yet more cases that
need handling, as well. Source and target types being the same is one case,
but e.g. the following one gives the same problem, not solved with only
checking for if source type equals target type:
std::string str=boost::lexical_cast<std::string>(' '); // Space character,
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk