Suppose I have a function that takes an ostream &
parameter o
and writes to that ostream. An operator <<
implementation would be a good example.
ostream& operator << (ostream& o, const MyThing& t)
{
// ... interesting code here ...
return o;
}
Within the function, I might want to specify formatting options on the stream. For example, I might want a number to be printed as hex, no matter how the o
is configured when it is passed in to the function.
Secondly, I might want to be able to make assumptions about the current formatting flags. For example, it would be nice to be able to assume that numbers were formatted as decimal unless I request otherwise.
Finally, by the time the function exits I want the formatting options on o
to be the same as they were before the function was called, so as to appear unchanged to the caller. This is simply a matter of politeness to the caller.
Up until now I have achieved this by creating a local ostringstream
within the function, doing all my work on that (including setting formatting options), and sending the .str()
to o
at the end of the function. The StackOverflow question here suggests that people cleverer than me take the same approach. However, it bothers me that I'm keeping so much data in ostringstreams that could perhaps be sent to the output earlier (the strings can get quite large).
I have two questions:
1) Is it legal, idiomatic, good form, etc. to create a temporary (stack based) ostream around o.rdbuf()
and do my work on that ostream? My own tests and the page at cppreference.com appears to suggest that I can.
ostream& operator << (ostream& o_, const MyThing& t)
{
ostream o (o_.rdbuf());
// write stuff to "o",
// setting formatting options as I go.
return o_; // Formatting on the parameter ostream o_ unchanged.
}
2) Is there another, better way that I have not considered?
Boost IO State Savers are built exactly for this purpose.
That's not a bad solution; it's certainly legal. I don't think it's too common, so it's probably a good idea to comment as to why you're doing it.
The most frequent solution I've seen here is to create a state
saver class, which will save all of the state you need
(typically, flags()
, precision()
and fill()
) in the
constructor, and restore it in the destructor, and then to
forceably set all of the options you want. (It may be possible
to use copyfmt
for this, although this also copies things like
the exception mask, which you probably don't want to play with.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With