How to automatically set the default stream mode

C ++ steam objects have state. If you write a piece of code, for example

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

forget to set the flow state back. This will cause problems in some other unrelated codes. It is satisfactory to pair the “set” and “cancel” pairs. In addition, it seems to me that this is also against the convention for RAII.

My question is: is it possible, only with a thin layer of wrapping, to make these manipulations with the RAII-like mode. That is, immediately after the expression ends with a semicolon, the state of the stream automatically returns to default.

Update: via the link provided by @ 0x499602D2, one of the ways could 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 you can use the macro as

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

By the way, it might be a good idea to add a lock field to that class saver boost :: io :: ios_state, in case funny things happen in a multi-threaded program. Or have they already done this?

+5
source share
2 answers

I am going to suggest an alternative approach. Manipulators apply to the std::[i|o]stream instance, but they do nothing with respect to the std::[i|o]streambuf that this std::[i|o]stream controls.

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

In this case, only functions from the standard library are used, and since the original stream is not touched, the use of manipulators is a trivially safe stream (since each stream works with a different stream). Now the actual write and read of "thread safety" depends on the thread safety of the managed thread buffer.

+3
source

I once wrote a utility class for personal use. (I don’t know how perfect it is, like the promotion code, but it worked for me, so I dare to share.)

 #include <iostream> #include <iomanip> /** provides a helper class to work with streams. * * It stores current format states of a stream in constructor and * recovers these settings in destructor. * * Example: * <pre> * { // backup states of std::cout * IOSFmtBackup stateCOut(std::cout); * // do some formatted output * std::cout * << "dec: " << std::dec << 123 << std::endl * << "hex: " << std::hex << std::setw(8) << std::setfill('0') * << 0xdeadbeef << std::endl; * } // destruction of stateCOut recovers former states of std::cout * </pre> */ class IOSFmtBackup { // variables: private: /// the concerning stream std::ios &_stream; /// the backup of formatter states std::ios _fmt; // methods: public: /// @name Construction & Destruction //@{ /** constructor. * * @param stream the stream for backup */ explicit IOSFmtBackup(std::ios &stream): _stream(stream), _fmt(0) { _fmt.copyfmt(_stream); } /// destructor. ~IOSFmtBackup() { _stream.copyfmt(_fmt); } // disabled: IOSFmtBackup(const IOSFmtBackup&) = delete; IOSFmtBackup& operator=(const IOSFmtBackup&) = delete; //@} }; int main() { { // backup states of std::cout IOSFmtBackup stateCOut(std::cout); // do some formatted output std::cout << "dec: " << std::dec << 123 << std::endl << "hex: " << std::hex << std::setw(8) << std::setfill('0') << 0xdeadbeef << std::endl << "123 in current: " << 123 << std::endl; } // destruction of stateCOut recovers former states of std::cout // check whether formatting is recovered std::cout << "123 after recovered: " << 123 << std::endl; return 0; } 

Compiled and tested on ideone (demo version of life) .

Output:

 dec: 123 hex: deadbeef 123 in current: 7b 123 after recovered: 123 
+2
source

Source: https://habr.com/ru/post/1275228/


All Articles