|
Boost : |
Subject: [boost] [optional_io] InputStreamable refinement
From: Andrew Troschinetz (ast_at_[hidden])
Date: 2009-02-05 11:51:18
This is a spin off from the thread "[lexical_cast] A suggestion"
While trying to get lexical_cast and optional to play nice I've run up
against some problems with the InputStreamable solution for optional
types in optional_io.hpp.
The crux of the problem is that I think any given optional type should
behave as much like the type it wraps as possible.
For example I think this:
stringstream sin ("1.2.3.4.5");
optional<double> token;
while (sin >> token) cout << token << endl;
Should have the same output as this:
stringstream sin ("1.2.3.4.5");
double token;
while (sin >> token) cout << token << endl;
And that this shouldn't fail:
stringstream sin ("test");
optional<string> token;
sin >> token; // token shouldn't be empty
The current InputStreamable solution for optional does not pass these
tests.
But that's not all, I also believe that there is room for even more
improvement here! Since it's semantically valid to have an un-
initialized optional type, I think failure to extract something off a
stream should return an empty optional type _without_ setting the
failbit on the stream.
Here's a usage example that demonstrates what I mean by that:
// output is "1 nan nan nan nan 5.5 nan nan nan nan nan nan nan
-3.2 nan "
istringstream sin (" 1 this 5.5 is a test -3.2 a");
optional<double> token;
const double nan = numeric_limits<double>::quiet_NaN ();
while (sin >> token) cout << token.get_value_or (nan) << " ";
// output is "1 "
istringstream sin (" 1 this 5.5 is a test -3.2 a");
double token;
while (sin >> token) cout << token << " ";
I did submit a ticket with the final comment proposing code that is
(maybe?) a solution to this refinement. ( https://svn.boost.org/trac/boost/ticket/2659
) Please pardon any guffaws I made in replies to that ticket, I'm
still learning about the nuts and bolts of streams and boost as I go.
However there is still one problem, and this brings us back to
lexical_cast. Consider this example:
int an_invalid_uint = -1;
unsigned i = lexical_cast<optional<unsigned> >
(an_invalid_uint).get_value_or (0);
I believe we should expect this to store 0 in i, but instead it will
throw a bad_lexical_cast exception even with my proposed revision to
optional_io.hpp. A possible solution is a specialization for
optional<Target> somewhere in lexical_cast.hpp that would replace code
that looks something like this (pseudocode):
do lexical_cast
if failed to cast: throw exception
With something like this:
do lexical_cast
if failed to cast: return optional<Target>()
So is there any interest in this sort of refinement of optional's
InputStreamable implementation or lexical_cast?
-- Andrew Troschinetz Applied Research Laboratories
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk