|
Boost : |
From: Yuval Ronen (ronen_yuval_at_[hidden])
Date: 2005-01-30 03:01:06
>>>2. lexical_cast ignores trailing whitespaces, but not leading
>>>whitespaces. Meaning that
>>>
>>>int a = lexical_cast<int>("3 "); // three-space
>>>
>>>will work and return 3, but
>>>
>>>int a = lexical_cast<int>(" 3"); // space-three
>>>
>>>will throw. Why? There's no rationale here. Both cases should be treated
>>>in the same manner, and IMHO, that manner should be throwing.
>>
>>So what should lexical_cast do; strip or not? Ladies and gentlemen, can we
>>have your votes? ;)
>
>
> I am of the opinion we should follow the standard (ie. STL) in this one.
> The STL would accept both, and since we rely on operator>>, so should we.
> I mean, if you're going to be anal about spaces, be completely anal about
> them, but I don't think we should be, I think accepting whitespace before
> and after is correct, just as the stringstream operator>> does by default.
But lexical_cast is not operator>>, it just uses it.
BTW, I've thought of the following (rare) scenario:
There's a class A which have operator<< that streams a single space,
then its content and then another space at the end. Class A's operator>>
requires these leading and traling spaces, otherwise it falis. In this
case, a "whitespace-loose" lexical_cast should *know* to bypass all
leading spaces in the input string, *except* the last space before the
content, and go on to the class A's operator>>. Can he do that? Is this
even possible?
What I'm saying is that using a "whitespace-loose" lexical_cast, forces
us to write "whitespace-loose" operator>>, which I'm not sure is always
possible.
>>Adding options to lexical_cast is difficult. It's meant to resemble regular
>>casts, and any additional template- or function-arguments makes it no longer
>>look like a cast.
>
>
> Not really, make it a policy - defaulting to one or the other, eg:
>
> myclass a = boost::lexical_cast<myclass>(s); will not care about spaces.
> myclass a = boost::lexical_cast<myclass, noskipws>(s); will care.
>
> Its easy enough to default the argument:
> enum ws_policy { skipws, noskipws };
> template<typename T, ws_policy wsp = skipws>
> class lexical_cast { ... };
>
> Or even better:
> template<typename T, std::ios_base::fmtflags newflags =
> std::ios_base::skipws>
> class lexical_cast { ... };
>
> Then just do:
> std::stringstream ss;
> ss.flags(newflags);
>
> And carry on about our merry way. The latter way gives us great
> flexibility - allowing us to control the IOS flags ourselves, while still
> keeping a simple and backward compatible interface, and most importantly,
> its dead easy to implement :)
Unfortunately, it's not that easy. calling lexical_cast<T, noskipws>
according to your second proposal, will make it not ignore leading
whitespace, but it will still ignore trailing whitespace. Ignoring/not
ignoring trailing whitespace requires some additional code other than
setting ios_base flags.
I'm not saying it's not possible, just that it's not that easy :-(
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk