Simon Richter: Scary thought

std::cout << (std::stringstream() << "foo" << std::setw(8) << "bar").rdbuf() << std::endl;
which is a WTF in itself.
#include <stdio.h>
#include <iostream>
#include <iomanip>
using namespace std;
main()
printf("%05d\n", -3);
cout << setw(5) << setfill('0') << -3 << endl;
It turns out that it is:
-0003
000-3
To get the numbers where you'd like them to be, you do it this way:
printf("%05d\n", -3);
cout << setw(5) << setfill('0') << internal -3 << endl;
Compare with C to see why C++ iostream is not really that much used. Also,
setfill and internal are persistently changing the state of the stream,
contributing fancy and interesting side effects:
cout << setw(5) << setfill('0') << internal << -3 << endl;
cout << setw(10) << "ciao" << endl;
this prints:
-0003
000000ciao
and I didn't see any sort of
RAII save and
restore of the stream state, nor a particularly obvious way to reset the stream
to factory settings. Suppose that the function foo
throws an exception here:
try
cout << setfill('=');
cout << setw(10) << foo() << endl;
cout << setfill(' ');
catch (MyException& e)
// Catch this hypotetical exception
cerr << setw(3) << e.errCode() << ": " << e.msg() << endl;
Then the state of the stream never gets reset, and the error code ends up being
padded with equals instead of the default space. What would the alternative
be, reset the stream state after each function call in the code? Or am I
missing something?
Update: here are some suggested, but still not optimal, ways of dealing
with it:
From Simon Richter:
std::cout << (std::stringstream() << "foo" << std::setw(8) << "bar").rdbuf() << std::endl;
From Peter De Wachter:
fstream tmp;
tmp.copyfmt(cout);
cout << setw(5) << setfill('0') << internal << -3 << endl;
cout.copyfmt(tmp);
cout << setw(10) << "ciao" << endl;
This is a possible RAII class to save the stream state (based on Peter De
Watcher's approach), but I suspect that creating a fstream for every block that
uses iomanip operators is rather heavyweight:
struct SaveIOState
fstream tmp;
ostream& s;
SaveIOState(ostream& s) : s(s)
tmp.copyfmt(s);
~SaveIOState()
s.copyfmt(tmp);
;
Next.