Point taken, but small beer IMO; I use parens in boolean expressions because I can never remember the precedence of && vs ||, so would naturally use them here too.
And I don't buy the fact that << is somehow off limits because it's used for bitshift; the domain of usage is usually disjoint, although one would have to squint to grok the outputting of a bitshifted value to a stream - but how frequent is that?
Yes the << notation isn't perfect, but it is much nicer than named functions (and certainly superior to < (which Stroustrup initially considered)!). Adding arbitrary operators to the language would have required mechanisms to define associativity and precedence, which would have added a weight of complexity disproportionate to the reward.
I don't really see the big advantage to << over named functions here. Compare:
cout << string << " and " << otherstring << endl;
cout.write(string).write(" and ").write(otherstring).write(endl);
It's about as readable to me. To me, operator overloading is good when the meaning is already obvious because of shared context that everybody has. That's not the case when co-opting << for stream operators.
And I don't buy the fact that << is somehow off limits because it's used for bitshift; the domain of usage is usually disjoint, although one would have to squint to grok the outputting of a bitshifted value to a stream - but how frequent is that?
Yes the << notation isn't perfect, but it is much nicer than named functions (and certainly superior to < (which Stroustrup initially considered)!). Adding arbitrary operators to the language would have required mechanisms to define associativity and precedence, which would have added a weight of complexity disproportionate to the reward.