65

If I manually overload the == operator for a structure, do I get the != operator for free (presumably defined to be the boolean opposite), or do I have to overload it manually (even if to just return !(this == rhs)?

Edit-The question is not whether or not I CAN overload both operators, but whether I must overload inequality if I've already overloaded the equality operator. Regardless, good answers have been given.

prelic
  • 4,450
  • 4
  • 36
  • 46

4 Answers4

76

Overloading operator == does not give you operator !=. You have to do it manually and the canonical way is to implement it in terms of operator == as in !(left == right).

The semantics of the operators are not dictated by the standard. You could very well overload operator == to mean equality yet overload operator != to something different like addition or even equality again (not that this is a good practice, in fact it should be discouraged. When in doubt, do as the ints do...).[Refer (1) Below]

On a side note, Boost.Operators can help you provide canonical implementations for operators. There is also std::rel_ops with a canonical implementation for operator !=.

(1) To know more about it read Three basic rules of operator overloading in C++.

Community
  • 1
  • 1
K-ballo
  • 80,396
  • 20
  • 159
  • 169
  • 1
    Thanks, will accept. I tried using the `==` operator (that I had overloaded) in my definition for `!=`, but got a 'binary operator not found, and no conversion exists' error. Any idea why without posting code? Thanks again – prelic Nov 03 '11 at 19:16
  • @prelic: No way to guess without seeing the code. It does look like you implemented `operator ==` as a member function when it would better be a free function, but I don't think that's the cause of your problem. – K-ballo Nov 03 '11 at 19:19
  • @prelic: It is a very bad practice to implement functionality of `!=` While the operator being called is `==`.Please do your predecessors a favor and **don't do it**. K-ballo, please for the love of god remove that para which advises so or add a note that **never** to do it. – Alok Save Nov 03 '11 at 19:20
  • Why is it okay to overload `==` but not `!=`? Or are you saying not to overload either comparison op? – prelic Nov 03 '11 at 19:22
  • @Als: Its certainly not my intention to suggest that, I just wanted to point out that it could be done. Feel free to edit my answer to add a warning note. – K-ballo Nov 03 '11 at 19:23
  • 1
    @prelic: Perhaps you have done `!(this == rhs)` instead of `!(*this == rhs)`? – K-ballo Nov 03 '11 at 19:23
  • @K-ballo - that's an affirmative. – prelic Nov 03 '11 at 19:25
  • I know this is a little old now, but this comment trail is confusing, and I can't make sense of what is or isn't being suggested. Since `operator!=` can return as soon as anything not equal is found, but `operator==` must check everything, I thought it would make more sense for `operator==` to be implemented with `operator!=`, not vice-versa. – boycy Sep 27 '16 at 16:49
  • @boycy `operator==` can too return as soon as anything not equal is found. It's the exact same question, just phrased differently. – K-ballo Sep 27 '16 at 16:52
  • I'm not convinced: equality requires *all* elements be equal, but non-equality requires *any* element be non-equal so can bail out instantly. Of course, when they *are* equal you must still check every element, but this way avoids forcing comparison of all elements for `operator!=` when the first element could've been enough. – boycy Sep 27 '16 at 17:08
  • @boycy so are you saying that when `operator==` founds that something is not equal, it must continue checking rather than immediately return `false`? You might wanna use your intuition, whenever one returns `true` the other one returns `false` and viceversa, so the logic behind them must be the same. Failing that, you could check out De Morgan's laws. – K-ballo Sep 27 '16 at 17:13
  • Not quite, this is about `operator!=` specifically. Doesn't De Morgan's prove it? `x != y <=> !(x.a == y.a && x.b == y.b) <=> (x.a != y.a || x.b != y.b)`. Implementing `operator!=` with `operator==` means it will check every element even if the first were non-equal. – boycy Sep 27 '16 at 17:22
  • @boycy make all truth tables for both sides, highlight those in which short-circuiting happens, report if you wish... you seem to have missed the part where the expressions are equivalent – K-ballo Sep 27 '16 at 17:24
  • I've probably explained poorly; sorry if so. I'm thinking of comparing objects with `N` sub-objects to compare. `operator==` always requires `N` comparisons, but `operator!=` only requires `N` in the worst case. Why then make it delegate to the other? Or imagine comparing ranges. Would you use `std::all_of` to check all elements for equality, then invert? Or use `std::any_of` to check for inequality and bail-out early? – boycy Sep 27 '16 at 18:12
  • @boycy You are still completely missing it, `operator==` does not always require `N` comparisons, it only requires `N` comparisons in the worst case, which is when at least all but the last subobjects are equal. I'd suggest you open a new question on this site, but on presenting the question itself you would realize it doesn't make sense, so... perhaps give that a try? – K-ballo Sep 27 '16 at 18:29
  • Ok I'll rethink; apologies for diversion and thanks for your patience (especially if I am wrong...). I'm still confused as to what your & prelic's conversation was about and whether there's any general advice in there – boycy Sep 27 '16 at 19:19
18

No nothing is for free. You pay for what you use in C++(in case of Operator Overloading).
You only get the Operator which you overload nothing more.

Also, It is a good practice that if you overload == operator then you should overload != as well because the users of your class will expect that to be available.

Operator Overloading C++ FAQ should be a good read.


Answering the updated Question:

The question is not whether or not I CAN overload both operators, but whether I must overload inequality if I've already overloaded the equality operator.

NO.
There is no such requirement that you Must overload != If you need to overload ==. However,it is a good practice that you Should overload operators related to each other.

Why is it a good practice?
Think it from the perspective of the user of your class. If the user of your class can use ==(equality criteria) to compare objects of your class, naturally they are going to expect that they should be able to use !=(Non-equality criteria) as well, this stems from the fact that these two operators are related closely and supported for all built-in tyes.

What happens if you disregard the should and not overload != when you overload ==?
If the users of your class use != they will get a compile error.
They would frown a bit about not being provided with != when they are provided with == and they will have to realign their logic to use == instead of the !=.

So you can live with it but be ready to expect a few frowns and complaints of inconvinience and not providing user friendly interface.

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • 7
    The C++ motto is "you don't pay for what you don't use". Often you do get functionality automatically, for example, calls to member destructors. – Ben Voigt Nov 03 '11 at 19:13
9

You have to overload each operator. != and == are not linked.

scrappedcola
  • 10,423
  • 1
  • 32
  • 43
1

It doesn't, and thankfully it is the way it is. For example, you might want a structure, where both a!=b and a==a are true. They are not necessary the inverse, they can be anything you want.

Boosts the creativity. :)

For example if you don't know the result of a comparison, or it is generally not known, then it would be reasonable to a==b and a!=b return the same.

Example: http://en.wikipedia.org/wiki/Three-valued_logic

Rok Kralj
  • 46,826
  • 10
  • 71
  • 80
  • 26
    Actually, no, I would never want such a structure. – Nemo Nov 03 '11 at 19:15
  • Ha, I would. :) I do not mean they are always the same, but might be in some cases. Edit. – Rok Kralj Nov 03 '11 at 19:16
  • 1
    I cannot think of an example where I would not want to shoot the developer that wrote such a device. Please give us a valid use case. – John Dibling Nov 03 '11 at 19:17
  • 1
    Why do you think C++ allows such case? The case is where the comparision is undefined - eg you don't know the outcome. – Rok Kralj Nov 03 '11 at 19:19
  • The same reason C++ allows any code that makes me want to shoot developers. Syntax is not an excuse for insane developers. – tenfour Nov 03 '11 at 19:23
  • 1
    Because the C++ standard authors have no interest in limiting what you can & cannot do. To the extend they were allowed, they will let you write any crazy thing you can think of. That doesn't make it a good idea. – John Dibling Nov 03 '11 at 19:25
  • 5
    @John Dibling: `float`, `double`. – JoeG Nov 03 '11 at 19:29
  • @Joe: Elaborate, please. 2.5 == 2.5 both here and in bizarro-world. Besides, you should not be using equality operators with floating points. – John Dibling Nov 03 '11 at 19:31
  • 8
    @JohnDibling: `(NaN == Nan)` evaluates to `false` – Mooing Duck Nov 03 '11 at 19:32
  • @Mooing duck: Yes, that is true if you are on an IEEE-754 platform which pretty much everyone is. That, however, does not provide a use case where you would implement `operator==` and `operator!=` differently for a class. – John Dibling Nov 03 '11 at 19:35
  • @JohnDibling: So a structure with a `NaN` equivilent [say, a custom floating point type] should not respect the established NaN behavior? – Dennis Zickefoose Nov 03 '11 at 19:40
  • @Dennis: I would say no. Instead the floating-like structure should have a `IsPresent()` type function. The reason is because `NaN==NaN` returning `false` is not an 'established' NaN behavior, as such. It is a platform-dependant behavior. This is something that is particular to IEEE floating types; it is not inherit in floating types themselves. – John Dibling Nov 03 '11 at 19:47
  • @John: So you agree, then, that not automatically generating `!=` given a user provided `==` increases your options when writing your code. For instance, you have the option of emulating a particularly popular floating point format [making your type intuitive for people familiar with that format], or of doing things in a way you find more intuitive [for people unfamiliar with it]. – Dennis Zickefoose Nov 03 '11 at 19:55
  • @Dennis: I agree that C++ giving you the freedom to define `==` and `!=` in whatever way you see best is good, sure. One of the things I like best about C++ is how it does not prescribe any particular idiom or style to the people who use it, unlike any other language I know. – John Dibling Nov 03 '11 at 19:59
  • @Dennis: That being said, with great power comes great responsibility. I still have yet to see a use case where a device that returns the same thing for both `operator==` and `operator!=` is a good thing. – John Dibling Nov 03 '11 at 20:01
  • 11
    `(NaN == NaN)` is false, and `(NaN != NaN)` is true. This is not an example where both `(a == b)` and `(a != b)` are true. `==` and `!=` return the opposite even with IEE754 floats. You're confusing this with the reflexive property of `==`. I don't see a reason why I'd want `null!=null` and `null==null` to be both true. – R. Martinho Fernandes Nov 03 '11 at 20:04
  • @John Dibling I could see cases where you can test inequality for sure, but not equality. Like, testing if a blood sample is from the same person using only blood type. – Lee Louviere Nov 03 '11 at 20:04
  • 1
    If the result of the comparison can be undefined, shouldn't `!=` return a class representing "undefined" that overloads `!` to stay undefined, rather than just returning false? i.e. `(null == null)` => null, not false – Random832 Nov 03 '11 at 20:38
  • So can anyone give an actual example where `(a == b) == (a != b)`? This is starting to sound like "This sentence is false". – Scott Rippey Nov 03 '11 at 23:33
  • 1
    Yes, you have the freedom to do so. There is no restriction, because the language is cleaner this way. However, all programmers will expect that `!(a == b) == (a != b)`. If your implementation doesn't obey that law, it violates the principle of least astonishment. –  Nov 04 '11 at 00:34
  • I said **You might want**, I did not say that you actually have to make such structure. Just because you don't see anything else than `!(a == b) == (a != b)`, that doesn't mean it doesn't exsist. – Rok Kralj Nov 04 '11 at 10:14
  • @Random832 But the type must be known at compile time, and it would be very surprising if the return-type of `==` weren't coercible to `bool`. Should this `null` value be treated as "true" or "false"? – Kyle Strand Aug 19 '15 at 17:07
  • @KyleStrand VB.net actually works this way, and treats it as false. SQL works similarly (the result of a comparison operator isn't actually usable in expressions, but all regular comparisons including `NULL = NULL` and `NULL != NULL` will be false when null is involved.) If I wanted to make a type whose semantics include VB/SQL-like treatment of null values, I could overload == and != to both return false (or both return a representation of a null boolean, which may or may not be coercible to bool and may or may not throw an exception when its null value is converted to bool) – Random832 Aug 19 '15 at 17:17
  • And even if the type is coercible to bool, that doesn't mean either `operator !`, or that type's `operator ==`, performs that conversion. – Random832 Aug 19 '15 at 17:25
  • @Random832 I would still consider such a class to be very surprising, because I'm writing C++, not VB or SQL. Yes, this is *possible*, but if I had a coworker who did anything of the sort with the explanation "well, this is how VB.net works," I would respectfully tell their manager that they should be fired. – Kyle Strand Aug 19 '15 at 17:26
  • (I jest, but only a little.) – Kyle Strand Aug 19 '15 at 17:27
  • People use C++ to build whole domain-specific languages from overloading e.g. the comma operator. This is - if you'll forgive a little VB pun - "`Nothing` in comparison". – Random832 Aug 19 '15 at 17:29