overloading operators for I/O

Don Clugston dac at nospam.com.au
Wed Feb 14 23:38:34 PST 2007


Walter Bright wrote:
> Michiel wrote:
>  >> And we should keep on frowning on attempts to use overloaded << for I/O
>  >> purposes <g>.
>  >
>  > Why? I think it's intuitive. The arrows point from the source of the 
> message to
>  > the destination. Should the operator only be used for shifting 
> because that
>  > happens to have been its first purpose?
>  >
>  > I also like how you can send a message to an abstract object. And 
> that can be a
>  > cout, a cerr, an error console in a GUI, or something else. Same 
> thing the other
>  > way around.
> 
> Good question. C++ conventional wisdom is that's great, because it's 
> always been done that way in C++. Few question it.
> 
> Let's step back a bit. Suppose I overload '+' to be "launch nuclear 
> missiles." You see some code:
> 
>     x = a + b;
> 
> and what do you think? I think "add a and b, assign the result to x", 
> but instead, nuclear missiles are launched. It is completely unexpected 
> and unintuitive for '+' to mean anything other than 'add'. To do 
> something completely unrelated to 'add', one should instead write:
> 
>     x = launchNuclearMissiles(a, b);
> 
> where the meaning is plain, or at least, one isn't assuming it's adding 
> a and b.
> 
> So why overload operators at all? For the purposes of implementing UDTs 
> (User Defined Types) that have legitimate arithmetic operations on them, 
> such as matrices, extended precision numbers, etc.
> 
> Now back to '<<' and '>>'. To me, they are arithmetic operators, and 
> mean shift left and shift right. Shift is not an I/O operation. To say 
> they are intuitive is not because they are, but because C++ users are 
> simply accustomed to it.
> 
>     a << b << c << d;
> 
> That doesn't scream I/O to me. 

I agree. There's another problem -- it really doesn't scale well. With 
printf, you can do "%3.5f" to print a floating point number with a given 
precision. With <<, that same operation is really horrible.

I'd like to see a couple more clarifications in the spec, wrt operator 
overloading:
* If both opAddAssign and opAdd are provided, the compiler is permitted 
to replace expressions of the form a = a+b; with a+=b; (that is, a+=b 
_must_ mean a=a+b). And similarly for the other operators.

It's just insanity to make a+=b mean anything other that a = a + b.
Incidentally, this would make my 'operator overloading without 
temporaries' proposal a non-breaking change.



And if a, b, etc. are non-trivial
> expressions, they wind up:
> 
> 1) interacting with the operator precedence of << in unfortunate ways
> 
> 2) suppose you want to print a variable shifted left by a few bits:
> 
>     a << (b << 3) << c << d;
> 
> blech.
> 
> 3) Suppose you've got some relational operators and templates thrown in:
> 
>     a << b<c<3>> << c < d << e;
> 
> and things just go downhill from there.
> 
> 4) Operators aren't very greppable, meaning it's hard to go grepping 
> through source code looking to see if << has been overloaded.
> 
> 5) The Spirit library for C++ uses operator overloading to create a 
> specialized DSL for specifying grammar. The trouble is, the code looks 
> exactly like regular C++ expressions (since new operators cannot be 
> defined, nor can operator precedence be changed), and there are some big 
> warning boxes that the resulting appearance may LOOK like C++ but is 
> about as far removed from it as one can get. This doesn't enhance 
> readability.
> 
> And to sum up:
> 
>     writefln(a, b, c, d);
> 
> seems pretty intuitive to me. There's just no advantage to overloading <<.



More information about the Digitalmars-d mailing list