I fail to see how it is less maintainable. |
The format character assumes a specific type. This is a major maintainability hit.
This seems harmless, right?
|
printf("%d",myvar); // where myvar is an int
|
What if the needs of the program change and myvar needs to become a long long? Or a double? You now need to go back and change
every single occurance that you printed/formatted it. Good luck finding all of them.
The formatting in cout/cin should apply to the argument, not the stream.
Here' s a fun exercise: write a function that outputs a number in hex, then goes back to exactly the way the stream was before. |
You just pulled a 180 here. You talk about how the format should apply to the argument, then you go on to talk about altering the state of the stream.
I agree with your first comment. The format should apply to the argument. So you can pass whatever format specifiers you want before printing the variable. The state of the stream is irrelevent.
Why not ditch the ugly-as-sin << notation, |
Because it hurts expandibility and maintainability. << Can be overloaded and can have operators defined for it outside of the ostream class. On the other hand, new ostream functions cannot be made.
And do you really think << is uglier than %z? Because I'm pretty sure you'd be in the minority there.
The streams in C++ got it totally mixed - to change the format you have to do it as if you were printing some "special kind of data". This is a nice demonstration of operator overloading abuse - using the same operator for much different purposes (even for the same object!). |
I see your point here. But this is a zero sum game. If cout didn't do it this way, it would be even
more verbose and have even
longer syntax, and you would be giving it even more flack for having to have 4 or 5 lines of code to print a single formatted variable.
Another thing already mentioned rockedboy9000: additionally making formatting a part of the stream's state, although it really belongs to the argument, is a serious design flaw. This can break stream formatting in multithreaded environments (e.g. in logging). |
No, it's a design flaw to assume I/O is threadsafe.
Any kind of logging in a multithreaded environment (with cout or with printf) should be properly protected by mutexes, making this a somewhat moot point.
Or even: cout << number("####.##", 10.45). Still much better, still typesafe and could be easily made threadsafe. |
Go ahead and write such a 'number' formatting option. Nothing is stopping you.
That's the beauty of ostream's system.
With the current STL design it is not possible to make it threadsafe. |
Threadsafety can't be built into such facilities without sacrificing performance. Personally, I feel it's better design to do your own work of making objects threadsafe rather than having the library assume it's running in a multithreaded environment.
There are [admittedly imperfect] ways you can make it threadsafe without changing syntax... something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
class bufferedostream : public ostringstream
{
private:
bufferedostream(const bufferedostream&);
bufferedostream& operator = (const bufferedostream&);
ostream& stream;
mutex& mut;
public:
bufferedostream(ostream& s,mutex& m) : stream(s), mut(m) { }
~bufferedostream()
{
m.lock();
s << this->str();
m.unlock();
}
};
//...
#define tscout bufferedostream(cout,coutmutex)
//...
tscout << whatever << whatever;
|
EDIT:
Another idea for a solution without #define or double-buffering output would be to create a proxy class.
The proxy class could lock/unlock the mutex on construction/destruction and feed all output directly to cout (no double buffering necessary). To prevent misuse the proxy class could be only privately constructed by another class, which has a global instantiation that ties to to the appropriate mutex.
It wouldn't exactly be straightforward, but it would certainly be possible. And the syntax of using the stream wouldn't change.
EDIT 2:
Actually that above approach wouldn't work due to const correctness issues. Interesting.
I'd have to think about it more. I wish I wasn't at work!