Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to automatically set stream mode back to default [duplicate]

Tags:

c++

iostream

raii

C++ steam objects have state. If one write a piece of code like

using namespace std; 
cout << hex << setw(8) << setfill('0') << x << endl;

forgetting setting the stream state back. This will cause problems in some other unrelated codes. It's tedious to do "set" and "set back" pair matching. Besides from that, it seems to me it's also against convention behind RAII.

My question is: is it possible, with only a thin layer of wrapping, to make those state manipulations RAII-like. That is, right after the end of an expression by semicolon, stream state is automatically set back to default.

Update: Following the link provided by @0x499602D2, one workaround might be something like

#include <boost/io/ios_state.hpp>
#include <ios>
#include <iostream>
#include <ostream>
#define AUTO_COUT(x) {\
    boost::io::ios_all_saver  ias( cout );\
    x;\
    }while(0)

Then one can use the macro like

AUTO_COUT(cout << hex << setw(8) << setfill('0') << x << endl);

BTW, it might be a good idea to add a lock field to those saver class of boost::io::ios_state, in case funny things occur in a multi-threading program. Or they have already done so?

like image 292
John Z. Li Avatar asked Feb 08 '18 02:02

John Z. Li


1 Answers

I'm going to suggest an alternative approach. The manipulators apply to the std::[i|o]stream instance, but they do nothing with regards to the std::[i|o]streambuf which is managed by that std::[i|o]stream.

Therefore, you can create your own std::[i|o]stream, which will have its own formatting state, but writing to the same buffer std::cout uses:

#include <iostream>
#include <iomanip>

int main()
{
    std::cout << std::hex << 32 << "\n";
    std::ostream os(std::cout.rdbuf());
    os << 32 << "\n" << std::hex;
    std::cout << std::dec;
    os << 32 << "\n";
    std::cout << 32 << "\n";
}

Output:

20
32
20
32

Live on Coliru

This uses only features from standard library, and since the original stream is not touched, applying manipulators is trivially thread safe (because each thread operates on a different stream). Now, the actual writes and reads' thread safety depends on the thread safety of the managed stream buffer.

like image 61
milleniumbug Avatar answered Sep 19 '22 05:09

milleniumbug