Boost logo

Boost :

Subject: Re: [boost] [optional_io] InputStreamable refinement
From: Andrew Troschinetz (ast_at_[hidden])
Date: 2009-02-26 18:06:04


Just heard back from Robert, I figure it's ok to forward this
information:

On Feb 26, 2009, at 10:00 AM, Robert Ramey wrote:

> The serialization library does no depend up optional or it's
> implementation. If you
> change the implemenation of optional, just make the changes
> are consistent with the requirements of the serialization library.
>
> The fact that the serialization of optional is implemented and tested
> as part of the serialization library is an anomoly. In fact, this
> code and test should be moved into the optional library.

I checked the optional test in the serializable library and it doesn't
seem to even include optional_io.hpp. And given Robert's comments, it
seems like it would be ok to make changes to optional_io.hpp.

With respect to the change I suggested for operator>>() (I think in my
last post I typoed and wrote operator<<(), I always get those silly
things backwards!):

In the case where we fail to extract optional<T>::value_type, I'm not
sure what would be the best thing to do with respect to the position
of the get pointer or other state bits. I had suggested this:

   if (in.fail () && !in.eof ())
   {
     in.clear ();
     in.get ();
   }

The intent of calling get() there is to enable this use case:

   stringstream sin ("one 2 three 4 five 6");
   optional<int> i;
   while (sin >> i)
   {
     if (i) cout << "found int: " << i << endl;
   }
   // which finds 2, 4, and 6

But why move the get pointer up by one? Why one? Does this make sense?
I can't provide a reasoning as to why it does, if it does.

So another possibility is this:

   if (in.fail () && !in.eof ())
   {
     in.clear ();
     in.setstate (std::ios::eofbit);
   }

This has the added benefit of of making the following possible w/o any
code change to lexical_cast:

   // doesn't throw, returns 0
   lexical_cast<optional<unsigned> > ("-1").get_value_or (0);

And if it's well documented that extracting an uninitialized
optional<T> sets the eofbit on the istream, then a prudent user could
(if they really wanted to) reformulate the first use case as:

   stringstream sin ("one 2 three 4 five 6");
   optional<int> i;
   while (sin >> i)
   {
     if (i) cout << "found int: " << i << endl;
     else
     {
       sin.clear ();
       sin.get ();
     }
   }

This leaves the why of moving the get pointer up to the user, where I
think it really belongs. Because I can image some use cases where
you'd want to do something other than just call get(). For example,
maybe you'd want to call getline() and ignore an entire line before
trying to extract another optional<T>. Or maybe you'd want to read
until you found some delimiter before trying again.

--
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