Can you give an example of a "pet construct" (aside from major features like multiple inheritance and exception handling) that could have been left out?
The times that I ran in to examples where it was used properly and elegantly I think it could have been done just as nice with a properly named function call.
I think the way it workd came from the DSL camp arguing that you should be able to make it look as though certain bits where native to the language, even if they weren't, and then the only uses we get are things that have nothing to do with DSLs but everything with children handling power tools (as in: bad idea).
Show me a single example of where operator overloading was necessity to make a function work, and I'll show you a more cleanly coded version using a function call.
The interesting thing is that after the compiler is done with it you'll be calling ::operatorX anyway.
Plenty of times there are naming issues as well, what does it mean to add two items of 'X' together, most times such a statement would be meaningless in the real world, but if you were forced to use a named function instead of an operator that function would have a name that matched what really happens.
Naming stuff is one of the great powers of computer languages, use of operators should be reserved to those situations where the outcome is predictable, and where operator precedence rules are the same as they would be when adding numbers.
So, it's fine to add an instance of a class called 'area' to another instance of that class, but you can't add one instance of 'boat' to another. That one should be done using:
cargospace = add_carcospace(boat1,boat2);
or something to that effect.It's a DSL that is similar to EBNF that generates parsers. It would be considerably more difficult to use without operator overloading.
Unfortunately its use is not quite limited to code like that.
So what's stopping you? That's exactly the way I do it. In my C++ career I've only overloaded math operators for math types, * and -> for smart pointers, [] for container-like types, and () for callable objects. At least in production code... I did some crazy and irresponsible things in college, just like everyone else.
If there's one point I've been wanting to make over and over again in this discussion, it's that misuse of language features is a much smaller problem than people think. (In practice, it is even negligible next to the overhead of reading poor error messages from the STL.) C++ is a very bad programming language for people who fear their coworkers, but so are C, Ruby, and any Lisp with macros. Even Java isn't protection against stupidity: a bad Java programmer on your team can't confuse you, but he can bury you.
Just think of defmacro as implicitly adding an infinite number of infinitely complex language features to Lisp. If you can deal with defmacro in a responsible way, operator overloading shouldn't bother you at all.
Same with language features. If all you have is bicycles then nobody is going to hurt anybody badly. But if we're all driving rocket cars at 1000 MPh then the resulting pile-ups will be spectacular.
You use operator overloading in a disciplined fashion, because you understand fully what the consequences are when you are using them improperly. If a situation is a 'natural' for overloading then you'll use it, otherwise you'll use a function with a descriptive name.
Unfortunately that is not the norm. You'd almost want an '--expert' flag given to the compiler before you are allowed to use those features, and every time you want to use it you get this trick question about some obscure bug that you have to answer :)
The best little C bug I saw in some forum somewhere by the way was this one:
int x,y;
x = 0; /* initialize both x
y = 0; and y to 0 */
domorestuff(x,y);
Of course any C programmer worth his weight will spot that one in a heartbeat, but it is indicative of how easy a language 'feature' (multiline comments) can become a bug.And as the below(above?) poster said - there is syntax highlighting. It's not the greatest example of failure.
So instead of view = projection * model; you would prefer.
view.SetVector(Multiply3x3matrixWith3x1Vector(projection.GetMatrix(),model.GetVector());
Should we allow floats an doubles to be multiplied with a'*' or should that use properly named classes
How does someone looking at the code know which parts of projection and model get multiplied here ?
At least make it:
view.setVector(projection.getMatrix() * model.getVector());
Because '*' applied to a model or a projection could literally mean anything, there might be many elements in those structures that are candidates for multiplication.By making it explicit what gets multiplied the code is less clear than it could be.
If they're simple arrays without further fields attached to them then you could do:
view = matvecmul(projection,model);
And that's pretty close to the overloaded example.Multiplying matrices is no more weird than multiplying a float by an int or a positive and negative number.