Boost logo

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 ("");
     optional<double> token;
     while (sin >> token) cout << token << endl;

Should have the same output as this:
     stringstream sin ("");
     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

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. (
  ) 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, gregod at, cpdaniel at, john at