156

Operator overloading in C++ is considered by many to be A Bad Thing(tm), and a mistake not to be repeated in newer languages. Certainly, it was one feature specifically dropped when designing Java.

Now that I've started reading up on Scala, I find that it has what looks very much like operator overloading (although technically it doesn't have operator overloading because it doesn't have operators, only functions). However, it wouldn't seem to be qualitatively different to the operator overloading in C++, where as I recall operators are defined as special functions.

So my question is what makes the idea of defining "+" in Scala a better idea than it was in C++?

skaffman
  • 381,978
  • 94
  • 789
  • 754
  • 28
    Neither C++ not Scala was defined by universal consensus among all programmers. I don't think there's any contradiction between the fact that some people whinge about C++, and the fact that some people don't whinge about Scala. – Steve Jessop Jul 08 '09 at 15:15
  • 17
    There's nothing bad about operator overloading in C++. – Puppy Mar 18 '12 at 17:17
  • 5
    This is nothing new but the way I defend C++ when operator overloading and other "advanced" features get called into question is simple: C++ gives us all the power to use/abuse it as we see fit. I've always liked how we're assumed to be competent and autonomous and don't need decisions like this made for us. – Elliott Nov 03 '12 at 02:10
  • Scala was designed like decades after c++. Turns out the person behind it is super savant in terms of programming languages. Nothing bad per se about either, if you stick to c++ or Scala for another 100 years it becomes clear that probably both are bad! Being biased is apparently in our nature but we can fight it, just look at the history of technology, everything becomes obsolete. – Nader Ghanbari Oct 16 '17 at 19:23

14 Answers14

242

C++ inherits true blue operators from C. By that I mean that the "+" in 6 + 4 is very special. You can't, for instance, get a pointer to that + function.

Scala on the other hand doesn't have operators in that way. It just has great flexibility in defining method names plus a bit of built in precedence for non-word symbols. So technically Scala doesn't have operator overloading.

Whatever you want to call it, operator overloading isn't inherently bad, even in C++. The problem is when bad programmers abuse it. But frankly, I'm of the opinion that taking away programmers ability to abuse operator overloading doesn't put a drop in the bucket of fixing all the things that programmers can abuse. The real answer is mentoring. http://james-iry.blogspot.com/2009/03/operator-overloading-ad-absurdum.html

None-the-less, there are differences between C++'s operator overloading and Scala's flexible method naming which, IMHO, make Scala both less abusable and more abusable.

In C++ the only way to get in-fix notation is using operators. Otherwise you must use object.message(argument) or pointer->messsage(argument) or function(argument1, argument2). So if you want a certain DSLish style to your code then there's pressure to use operators.

In Scala you can get infix notation with any message send. "object message argument" is perfectly ok, which means you don't need to use non-word symbols just to get infix notation.

C++ operator overloading is limited to essentially the C operators. Combined with the limitation that only operators may be used infix that puts pressure on people to try to map a wide range of unrelated concepts onto a relatively few symbols like "+" and ">>"

Scala allows a huge range of valid non-word symbols as method names. For instance, I've got an embedded Prolog-ish DSL where you can write

female('jane)!         // jane is female
parent('jane,'john)!   // jane is john's parent
parent('jane, 'wendy)! // jane is wendy's parent

mother('Mother, 'Child) :- parent('Mother, 'Child) & female('Mother) //'// a mother of a child is the child's parent and is female

mother('X, 'john)?  // find john's mother
mother('jane, 'X)?  // find's all of jane's children

The :-, !, ?, and & symbols are defined as ordinary methods. In C++ only & would be valid so an attempt to map this DSL into C++ would require some symbols that already evoke very different concepts.

Of course, this also opens up Scala to another kind of abuse. In Scala you can name a method $!&^% if you want to.

For other languages that, like Scala, are flexible in the use of non-word function and method names see Smalltalk where, like Scala, every "operator" is just another method and Haskell which allows the programmer to define precedence and fixity of flexibly named functions.

EECOLOR
  • 11,034
  • 3
  • 38
  • 72
James Iry
  • 19,231
  • 3
  • 61
  • 56
  • Last I checked, 3.operator+(5) worked. I'm really surprised that &(3.operator+) doesn't. – Joshua Sep 07 '09 at 22:43
  • you could for example do assert(female("jane")) in c++. That would not be confusing at all - nod back to the james-iry post about it not being that operator+ is a Bad Thing, but stupid programmers are. – pm100 Mar 10 '10 at 01:30
  • 1
    @Joshua `int main() {return (3).operator+(5);}` results in `error: request for member ‘operator+’ in ‘3’, which is of non-class type ‘int’` – zildjohn01 Oct 06 '10 at 16:17
  • That's a bunch of arrogant crap: "operator overloading isn't inherently bad, even in C++. The problem is when bad programmers abuse it." If something is easily abusable with fairly little benefit from using it, the overall result is that the next guy maintaining your code will lose productivity in deciphering the weirder parts of your code. Otherwise: Very informative and well written answer. – Jukka Dahlbom Apr 08 '14 at 06:33
  • @JukkaDahlbom Existence of smart pointers makes the benefit large on its own. And then you have lambdas, user-defined number types, interval types... – Alexey Romanov Jun 17 '18 at 18:41
66

Operator overloading in C++ is considered by many to be A Bad Thing(tm)

Only by the ignorant. It is absolutely required in a language like C++, and it is noticeable that other languages that started off taking a "purist" view, have added it once their designers found out how necessary it is.

  • 30
    I actually agree with Neil. Operator overloading is essential if you want to present variables/constants/objects/instances as algebraic entities... and have people understand their interactions in a mathematical fashion -- which should be how programming works IMHO. – Massa Jul 08 '09 at 14:38
  • 16
    +1, Operator overloading in C++ is good. For example it makes vector math a lot cleaner. Like with many C++ features, you should wield the power carefully. – John Smith Jul 08 '09 at 14:45
  • 3
    For another example, I've become used to how `< – ChrisW Jul 08 '09 at 14:53
  • 1
    I agree that operator overloading can be very useful, but why is it "absolutely required" in C++? – Michael Kristofik Jul 08 '09 at 14:55
  • 7
    @Kristo Because C++ uses values that must be assigned and copied. It is necessary to have control over that, so you must be able to specify the assignment operator for a given type, at a minimum. –  Jul 08 '09 at 15:01
  • 7
    @Kristo: because one intention of C++ is to allow user-defined types to do everything that builtin types do (albeit they're treated differently in some contexts such as implicit conversions). If you want to implement a 27-bit integer, then you can, and using it will be just like using int. Without operator overloading, it would not be possible to use UDTs with the same the syntax as builtin types, and hence the resulting language would not be "like C++" in this sense. – Steve Jessop Jul 08 '09 at 15:03
  • 4
    Neil's example being an important example: consider "int a(0); a = a + 1;". As C++ stands, I can do, "MyInt27 a(0); a = a + 1;". In C++ without operator overloading, that would have to be "MyInt27 a(0); a.set(a.plus(1));". Not exactly a drop-in replacement. So it would not be possible to write a template that works with either int or MyInt27, as required by the user. – Steve Jessop Jul 08 '09 at 15:08
  • 1
    @onebyone & Neil - Not that I'm not a proponent of operator overloading, i'm not convinced that it's truly absolutely necessary - there are always workarounds (in your MyInt27 vs int example, asides from defining a set function, you can always specialize templates appropriately to deal with type-specific behavior) - but having operator overloading does make C++ a much more expressive choice for certain domains - and that's a big advantage. – Faisal Vali Jul 08 '09 at 15:47
  • @Faisal How would you implement std::string, as a class that can be used in a std::vector, without operator overloading, and without major changes to underlying C++ language semantics? –  Jul 08 '09 at 15:50
  • @Neil - Well, to solve the issue with string, as an initial attempt, I would specialize vector for primitive (using operators) vs non-primitive (using appropriately named functions for assignment, ala C) types, keeping vector's interface consistent - but i agree that it would be ugly and unnecessary - i would curse the lack of operator overloading on a daily basis ;) – Faisal Vali Jul 08 '09 at 18:48
  • 1
    @faisal Oh come on now, you are not allowed to specialise a container for the contained! that way lies madness. –  Jul 08 '09 at 19:08
  • @Neil well, I mostly agree with you - even with the use of adapters and just one specialization for non-primitive types, time is being spent very inefficiently. – Faisal Vali Jul 08 '09 at 19:22
  • 8
    "that way lies madness" - even worse, that way lies std::vector! – Steve Jessop Jul 09 '09 at 09:51
  • Here's a thought, though. You wouldn't have to specialise every container. Instead, all containers could wrap their contents in a class template Box. Box has methods "set", "compare", etc, which by default it just delegates to its contents. But Box (only) is specialised for arithmetic types to implement "set" with = and "compare" with <. already="" can="" downside="" i="" is="" of="" one="" that="" think="" vector=""> wouldn't be an array of T, it would be an array of Box. But you could non-portably ensure Box is storage-compatible with T, and that the reinterpret_cast to T* "just works". – Steve Jessop Jul 09 '09 at 09:58
  • 2
    But I think the fact that Java had to remove operator overloading; realise that they'd messed things up for generics; invent auto-boxing to fix the problem; is a clear indication that C++ is doing something right. The one clear argument I know against operator overloading is that if you don't have it, then a certain set of "simple" expressions just "do the obvious thing". Except that a / b still might call out-of-line into a 64bit or float emulation library, so personally I think although clear, that argument is fallacious. ;-) – Steve Jessop Jul 09 '09 at 10:05
  • 3
    I highly agree with this answer. One of the reasons I much prefer C++ over Java is because it *lets* you overload operators. It just allows for so much more flexibility in an OO environment. I'm not new to programming, and I'm not an idiot... I don't need my programming language holding my hand, and forcing me to code in a certain way. Typing out long function names *every single time* I want to do something is not my idea of "fun". – Tim Leaf Apr 20 '10 at 19:58
  • 1
    Could you provide some rationale / justification to help us understand your answer? It reads as a blanket value judgement, relating to a subject area being contended. – Glen Best Jul 10 '13 at 06:49
  • "Only by the ignorant" - that's a bit of an ad hominem isn't it? – Adam Parkin Feb 23 '17 at 18:36
42

Operator overloading was never universally thought to be a bad idea in C++ - just the abuse of operator overloading was thought to be a bad idea. One doesn't really need operator overloading in a language since they can be simulated with more verbose function calls anyway. Avoiding operator overloading in Java made the implementation and specification of Java a little simpler and it forced programmers to not abuse operators. There has been some debate in the Java community about introducing operator overloading.

The advantages and disadvantages of operator overloading in Scala are the same as in C++ - you can write more natural code if you use operator overloading appropriately - and more cryptic, obfuscated code if you don't.

FYI: Operators are not defined as special functions in C++, they behave just like any other function - although there are some differences in name lookup, whether they need to be member functions, and the fact that they can be called in two ways: 1) operator syntax, and 2) operator-function-id syntax.

Faisal Vali
  • 29,823
  • 8
  • 40
  • 45
  • "One doesn't really need operator overloading in a language since they can be simulated with more verbose function calls anyway." One doesn't even really need *operators* under that logic. Why not just use `add(2, multiply(5, 3))`? – Joe Z. Feb 28 '13 at 12:53
  • It's more a case of matching the usual notations used. Consider mathematicians and physicists, they can understand and use a C++ library that provides overloads of the operators much more easily. They'd rather concentrate on the equation than the programming language. – Phil Wright Oct 24 '14 at 07:43
19

This article - "The Positive Legacy of C++ and Java" - answers your question directly.

"C++ has both stack allocation and heap allocation and you must overload your operators to handle all situations and not cause memory leaks. Difficult indeed. Java, however, has a single storage allocation mechanism and a garbage collector, which makes operator overloading trivial" ...

Java mistakenly (according to the author) omitted operator overloading because it was complicated in C++, but forgot why (or didn't realize that it didn't apply to Java).

Thankfully, higher level languages like Scala give developers options, while still running on the same JVM.

jmanning2k
  • 8,769
  • 4
  • 27
  • 23
  • 14
    Eckel is the only source I've ever seen for the idea that operator overloading was ditched from Java because of complications in C++ and he doesn't say what his source is. I would discount it. All the other sources I have say that it was ditched due to potential abuse. See http://www.gotw.ca/publications/c_family_interview.htm and http://www.newt.com/wohler/articles/james-gosling-ramblings-1.html. Just page search them for "operator overloading." – James Iry Jul 09 '09 at 16:28
9

Operator overloading is not something that you really "need" very often, but when using Java, if you hit a point where you genuinely need it, it'll make you want to rip your fingernails out just so you have an excuse to stop typing.

That code which you've just found overflows a long? Yup, you're going to have to retype the whole lot to make it work with BigInteger. There is nothing more frustrating that having to reinvent the wheel just to change the type of a variable.

9

There is nothing wrong with operator overloading. In fact, there's something wrong with not having operator overloading for numeric types. (Take a look at some Java code that uses BigInteger and BigDecimal.)

C++ has a tradition of abusing the feature, though. An often-cited example is that the bitshift operators are overloaded to do I/O.

dan04
  • 77,360
  • 20
  • 153
  • 184
  • << and >> operators are visually indicating way of transfer, they are *meant* to do I/O, it's not abuse, it's from standard library and practical thing. Just look at "cin >> something", what goes where? From cin, to something, obviously. – peenut Sep 21 '12 at 19:55
  • 7
    @peenut: But their original use was bit-shifting. The "standard library" uses the operator in a way that completely messes with the original definition. – Joe Z. Feb 28 '13 at 12:55
  • 1
    I'm sure i've read somewhere that Bjarne Stroustrup (creator of C++) experimented with using `=` instead of `<>` in the early days of C++, but ran into problems as it didn't have the right operator precedence (i.e. does it look for arguments on the left or right first). So his hands were a bit tied about what he could use. – Phil Wright Oct 24 '14 at 07:47
8

In general it is not a bad thing.
New languages such as C# also have operator overloading.

It is the abuse of operator overloading that is a bad thing.

But there are also problems with operator overloading as defined in C++. Because overloaded operators are just syntactic sugar for method calls they behave just like method. On the other hand normal built-in operators do not behave like methods. These inconsistency can be cause problems.

Off the top of my head operators || and &&.
The built in versions of these are short-cut operators. This is not true for overloaded versions and has caused some problems.

The fact that + - * / all return the same type that they operate on (after operator promotion)
The overloaded versions can return anything (This is where the abuse sets in, If your operators start to return some arbitrator type the user was not expecting things go down hill).

Martin York
  • 234,851
  • 74
  • 306
  • 532
6

Guy Steele argued that operator overloading should be in Java as well, in his keynote speech "Growing a language" - there's a video and a transcription of it, and it's really an amazing speech. You will wonder what he is talking about for the first couple of pages, but if you keep on reading, you will see the point and achieve enlightenment. And the very fact that he could do such a speech at all is also amazing.

At the same time, this talk inspired a lot of fundamental research, probably including Scala - it's one of those papers that everybody should read to work in the field.

Back to the point, his examples are mostly about numeric classes (like BigInteger, and some weirder stuff), but that's not essential.

It is true, though, that misuse of operator overloading can lead to terrible results, and that even proper uses can complicate matters, if you try to read code without studying a bit the libraries it uses. But is that a good idea? OTOH, shouldn't such libraries try to include an operator cheat sheet for their operators?

Blaisorblade
  • 6,172
  • 40
  • 69
4

I believe EVERY answer missed this. In C++ you can overload operators all you want, but you can't effect the precedence with which they're evaluated. Scala doesn't have this issue, IIRC.

As for it being a bad idea, besides precedence issues, people come up with really daft meanings for operators, and it rarely aids readability. Scala libraries are especially bad for this, goofy symbols that you must memorize each time, with library maintainers sticking their heads in the sand saying, 'you only need to learn it once'. Great, now I need to learn some 'clever' author's cryptic syntax * the number of libraries I care to use. It wouldn't be so bad if there existed a convention of ALWAYS supplying a literate version of the operators.

Saem
  • 3,313
  • 21
  • 12
  • 1
    Scala has fixed operator precedence as well, doesn't it? – skaffman Jul 14 '09 at 07:02
  • I believe there is, but it's far flatter. More to the point, Scala has less operators period. +, -, * are methods, not operators, IIRC. Which is why 2 + 3 * 2, isn't 8, it's 10. – Saem Jul 14 '09 at 16:29
  • 7
    Scala has a precedence system based on the first character of the symbol. scala> 2 + 3 * 2 res0: Int = 8 – James Iry Apr 20 '10 at 00:14
3

Operator overloading was not a C++ invention - it came from Algol IIRC and even Gosling does not claim it is a bad idea in general.

Nemanja Trifunovic
  • 23,597
  • 3
  • 46
  • 84
  • Sure, but it was in its C++ incarnation that it gained a general air of disreputability. – skaffman Jul 08 '09 at 14:28
  • 5
    What do you mean by "general air of disreputability"? Most people I know use languages that support operator overloading (C++, C#) and I have never heard any complaints. – Nemanja Trifunovic Jul 08 '09 at 14:48
  • I'm speaking from my long-past experience with pre-ANSI C++, and I certainly recall a common dislike of them. Perhaps the situation improved with ANSI C++, or people just learned how not to abuse it. – skaffman Jul 08 '09 at 15:33
  • 1
    Speaking as someone that has been using C++ since cfront days (mid 80s) I can assure you that that the introduction of the ISO standard had no effect on people's prejudices regarding operator overloading. –  Jul 08 '09 at 15:38
3

The only thing known wrong in C++ is the lack of the ability to overload []= as a separate operator. This could be hard to implement in a C++ compiler for what is probably not an obvious reason but plenty worth it.

Joshua
  • 34,237
  • 6
  • 59
  • 120
2

As the other answers have pointed out; operator overloading itself isn't necessarily bad. What is bad it when it is used in ways that make the resulting code un-obvious. Generally when using them you need to make them do the least surprising thing (having operator+ do division would cause trouble for a rational class's usage) or as Scott Meyers says:

Clients already know how types like int behave, so you should strive to have your types behave in the same way whenever reasonable... When in doubt, do as the ints do. (From Effective C++ 3rd Edition item 18)

Now some people have taken operator overloading to the extreme with things like boost::spirit. At this level you have no idea how it is implemented but it makes an interesting syntax to get what you want done. I'm not sure if this is good or bad. It seems nice, but I haven't used it.

Matt Price
  • 38,782
  • 9
  • 34
  • 43
  • I'm not arguing for or against operator overloading here, I'm not looking for people to justify them. – skaffman Jul 08 '09 at 15:34
  • Sprint doesn't come anywhere near the worst example I've come across - you should see what the RogueWave database library gets up to! –  Jul 08 '09 at 15:35
  • I agree that Spirit misuses the operators, but I can't really think of a better way to do it. – Zifre Jul 08 '09 at 15:51
  • 1
    I don't think spirit is quite abusing the operators, but it's pushing it. I agree there's really no other way to do it. It basically creates a DSL within C++'s syntax. Very far off of what C++ was designed to do. Yes, there are far worse examples :) In general I use them where appropriate. Mostly just the streaming operators for easier debugging\logging. And even there it's just sugar that forwards to a method implemented in the class. – Matt Price Jul 08 '09 at 18:25
  • 1
    It's a taste question; but parser combinator libraries, in functional languages, overload operators in a way _very similar_ to Spirit, and nobody argues against that. There's a lot of technical reasons for which they are better - Google for "embedded domain specific languages" to find plenty of papers explaining that from a general point of view, and Google for "scala parser combinator" for practical examples in this case. It is true that in functional languages the resulting syntax is often nicer - for instance, you don't need to change the meaning of >> for concatenating parsers. – Blaisorblade Nov 02 '10 at 15:56
2

I have never seen an article claiming that C++'s operator overloading is bad.

User-definable operators permit an easier higher level of expressivity and usability for users of the language.

Paul Nathan
  • 37,919
  • 28
  • 110
  • 204
1

However, it wouldn't seem to be qualitatively different to the operator overloading in C++, where as I recall operators are defined as special functions.

AFAIK, There is nothing special in operator functions compared to "normal" member functions. Of course you only have a certain set of operators that you can overload, but that doesn't make them very special.

John Smith
  • 4,257
  • 4
  • 29
  • 33