This has perplexed us for D. Experience with C++'s iostream's operator overloading meant running away screaming. Another terrible thing is people would code up DSL's using operator overloading, such as a Regex language. The horror there is the source code looks like ordinary C++ arithmetic, but it is actually doing Regexes.
So, how to allow operator overloading for arithmetic, but not for other porpoises?
1. Only allow overloading of arithmetic operators (i.e. no overloading of unary *) and [ ]
2. Only allow < overloadable, instead of < <= > >=. This enforces symmetry.
3. Don't allow overloading of && || ?:
4. A strong Compile Time Function Execution feature which enables DSLs in the form of string literals
5. Develop a culture of operator overloading is for arithmetic
This has worked well.