Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safely overloading stream operator>>

There's a ton of information available on overloading operator<< to mimic a toString()-style method that converts a complex object to a string. I'm interested in also implementing the inverse, operator>> to deserialize a string into an object.

By inspecting the STL source, I've gathered that:

istream &operator>>(istream &, Object &);

would be the correct function signature for deserializing an object of type Object. Unfortunately, I have been at a loss for how to properly implement this - specifically how to handle errors:

  1. How to indicate invalid data in the stream? Throw an exception?
  2. What state should the stream be in if there is malformed data in the stream?
  3. Should any flags be reset before returning the reference for operator chaining?
like image 765
Michael Koval Avatar asked Aug 15 '09 01:08

Michael Koval


People also ask

Can << operator be overloaded?

Fortunately, by overloading the << operator, you can! Overloading operator<< is similar to overloading operator+ (they are both binary operators), except that the parameter types are different.

What does >> mean in CPP?

>> is a right shift operator. << is a left shift operator. s >> 4 takes the value in 's' and shifts it right 4 bits. example: 1.

What do you call this << stream operator?

In C++ Streams, << is insertion operator. >> is extraction operator.


2 Answers

  1. How to indicate invalid data in the stream? Throw an exception?

You should set the fail bit. If the user of the stream wants exception to be thrown, he can configure the stream (using istream::exceptions), and the stream will throw accordingly. I would do it like this, then

stream.setstate(ios_base::failbit);
  1. What state should the stream be in if there is malformed data in the stream?

For malformed data that doesn't fit the format you want to read, you usually should set the fail bit. For internal stream specific errors, the bad bit is used (such as, if there is no buffer connected to the stream).

  1. Should any flags be reset before returning the reference for operator chaining?

I haven't heard of such a thing.


For checking whether the stream is in a good state, you can use the istream::sentry class. Create an object of it, passing the stream and true (to tell it not to skip whitespace immediately). The sentry will evaluate to false if the eof, fail or bad bit is set.

istream::sentry s(stream, true);
if(!s) return stream;
// now, go on extracting data...
like image 81
Johannes Schaub - litb Avatar answered Oct 10 '22 16:10

Johannes Schaub - litb


Some additional notes:

  • when implementing the operator>>, you probably should consider using the bufstream and not other overloads of operator>>;

  • exceptions occuring during the operation should be translated to the failbit or the badbit (members of streambuf may throw, depending on the class used);

  • setting the state may throw; if you set the state after catching an exception, you should propagate the original exception and not the one throwed by setstate;

  • the width is a field to which you should pay attention. If you are taking it into account, you should reset it to 0. If you are using other operator>> to do basic works, you have to compute the width you are passing from the one you received;

  • consider taking the locale into account.

Lange and Kreft (Standard C++ IOStreams and Locales) conver this in even more details. They give a template code for the error handling which takes about one page.

like image 27
AProgrammer Avatar answered Oct 10 '22 17:10

AProgrammer