"Roll-Back" or Undo Any Manipulators Applied To A Stream Without Knowing What The Manipulators Were [duplicate]

If I apply an arbitrary number of manipulators to a stream, is there a way to undo the application of those manipulators in a generic way?

For example, consider the following:

#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
    cout << "Hello" << hex << 42 << "\n";
    // now i want to "roll-back" cout to whatever state it was in
    // before the code above, *without* having to know 
    // what modifiers I added to it

    // ... MAGIC HAPPENS! ...

    cout << "This should not be in hex: " << 42 << "\n";
}

Suppose I want to add code at MAGIC HAPPENS that will revert the state of the stream manipulators to whatever it was before I did cout << hex. But I don't know what manipulators I added. How can I accomplish this?

In other words, I'd like to be able to write something like this (psudocode/fantasy code):

std::something old_state = cout.current_manip_state();
cout << hex;
cout.restore_manip_state(old_state);

Is this possible?

EDIT:

In case you're curious, I'm interested in doing this in a custom operator<<() I'm writing for a complex type. The type is a kind of discriminated union, and different value types will have different manips applied to the stream.

EDIT2:

Restriction: I cannot use Boost or any other 3rd party libraries. Solution must be in standard C++.


Solution 1:

Yes.

You can save the state and restore it:

#include <iostream>
#include <iomanip>

using namespace std;

int main()
{

    std::ios  state(NULL);
    state.copyfmt(std::cout);

    cout << "Hello" << hex << 42 << "\n";
    // now i want to "roll-back" cout to whatever state it was in
    // before the code above, *without* having to know what modifiers I added to it

  // ... MAGIC HAPPENS! ...

    std::cout.copyfmt(state);
    cout << "This should not be in hex: " << 42 << "\n";
}

If you want to get back to the default state you don't even need to save the state you can extract it from a temporary object.

std::cout.copyfmt(std::ios(NULL));

Solution 2:

The standard manipulators all manipulate a stream's format flags, precision and width settings. The width setting is reset by most formatted output operations anyway. These can all be retrieved like this:

std::ios_base::fmtflags saveflags = std::cout.flags();
std::streamsize prec = std::cout.precision();
std::streamsize width = std::cout.width();

and restored:

std::cout.flags( saveflags );
std::cout.precision( prec );
std::cout.width( width );

Turning this into an RAII class is an exercise for the reader...

Solution 3:

Saving and restoring state is not exception-safe. I would propose to shuffle everything into a stringstream, and finally you put that on the real stream (which has never changed its flags at all).

#include <iostream>
#include <iomanip>
#include <sstream>

int main()
{
    std::ostringstream out;
    out << "Hello" << std::hex << 42 << "\n";
    std::cout << out.str();

    // no magic necessary!

    std::cout << "This should not be in hex: " << 42 << "\n";
}

Of course this is a little less performant. The perfect solutions depends on your specific needs.

Solution 4:

Boost IO State saver might be of help.

http://www.boost.org/doc/libs/1_40_0/libs/io/doc/ios_state.html