6

As a follow-up to my previous question (Does overriding the operator == for a class automatically override the operator !=),

is there a scenario, where you would override the == and != operators to not be the negation of each other, where the negation would be defined as:

(!(a == b)) == (a != b)

or

(a == b) == (!(a != b))
rabl
  • 119
  • 4
  • 8
    A floating point `NaN` can't be compared, both `==` and `!=` will return false. – Mark Ransom Apr 05 '21 at 22:36
  • 2
    Have a read of `operator<=>` https://en.cppreference.com/w/cpp/language/operator_comparison#Three-way_comparison and https://stackoverflow.com/questions/47466358/what-is-the-spaceship-three-way-comparison-operator-in-c – Richard Critten Apr 05 '21 at 22:37
  • 1
    Depends on your definition of "sensible". If you're implementing a DSL, and `==` shouldn't be read as "equals", then maybe. An example of a DSL where things don't have their usual meanings is Boost Spirit (https://www.boost.org/doc/libs/1_75_0/libs/spirit/doc/html/index.html), although I don't think that overrides `==` or `!=` specifically. – Daniel H Apr 05 '21 at 22:37
  • 4
    @MarkRansom Yes `==` is false, but `!=` is true: https://godbolt.org/z/P45zTTc8Y – Daniel H Apr 05 '21 at 22:43
  • 1
    We could consider a class that manipulates possibly incomplete knowledge and reports true if and only if a comparison is known to be true. For example, we might have some axiomatic arithmetic-logic system and add to the system the premise that `x` is even. Then `x == 4` and `x != 4` would report false (meaning we do not know), while `x != 3` would report true (we know `x` is not equal to 3). – Eric Postpischil Apr 05 '21 at 22:53
  • @EricPostpischil Hmm, very interesting. – rabl Apr 06 '21 at 01:31
  • @EricPostpischil, these ideas usually don't go very far (related www.boost.org/doc/libs/1_75_0/doc/html/tribool.html) If you expect to have incomplete knowledge use a different symbol/word for this (maybeEqual, certainlyEqual, etc) and if there is no "certain" equality just leave `==`/`!=` unimplemented. Even in systems where you can theoretically have complete knowledge it is not advisable to have `==`/`!=` if these operations are too expensive to implement (yes, [in]equality can be expensive). Let alone for systems with *incomplete* knowledge. See https://www.youtube.com/watch?v=0EvSxHxFknM – alfC Apr 13 '21 at 10:28

3 Answers3

4

No, in a broad sense. Stepanov would say that if you don’t follow this rule of logic then you get what you deserve. That is why in C++20 they will be by default defined by each other just like he wanted.

In practice, yes, there are at least two scenarios.

  1. NaN (not-a-number) in IEEE floating point numbers. Two NaN are different and not not equal at the same time.

As noted in the comment. The logical inconsistency is not exactly between == and !=, but it is related: you can do a = b; assert( a != b); or have assert( a != a ).


  1. Expression constructs, aka expression templates, aka DSL. == and != create two independent expressions. Logically, they should be still be opposites but not in the sense that they are simple Boolean values. Take a look at Boost.Phoenix or Boost.Spirit. These libraries wouldn’t be possible if the language forces to return bools for these operations and one as the negation of the other.

In both cases you can reinterpret the situation to "restore" the logical rule. For example 1) you can say that once there is a NaN in your system the program is not in a logical state anymore. 2) you can say that the "expression" a != b should be also generated by !(a == b) even if they are not immediately bools.

So, even if the language lets you, you shouldn’t play with the rules of logic.

There is also the myth that supposedly sometimes checking for inequality should be faster than checking for equality or vise versa, as an excuse to implement them separately which can lead to logical inconsistency. This is nonsense given the short circuiting of logical operations that are fundamental to C++ and should be of any system built on top of C++.

cigien
  • 57,834
  • 11
  • 73
  • 112
alfC
  • 14,261
  • 4
  • 67
  • 118
  • 2
    `==` and `!=` are not both false for two NaN operands. `!=` does not mean “have a different value from”; it means “is not equal to.” A NaN is not equal to anything, not even itself, so `==` is false and `!=` is true. – Eric Postpischil Apr 05 '21 at 23:32
  • @EricPostpischil you are right. I guess I should point that the logic violation is slightly different. Basically, `a = b; assert( !(a == b) );`. – alfC Apr 05 '21 at 23:51
1

This happens all the time when working with databases, where a NULL value fails every comparison.

So, if you're implementing objects that model data that comes from a database, and you have an object that represents a NULL value, comparing something for equality with the NULL value will be false. Comparing it for inequality with a NULL value will also be false. Every kind of comparison will be false. And, the icing on the cake: comparing a NULL value for equality with another NULL value is also false.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • yes, that opens a can of worms. When we try to bring NULL to the level of a value, "Null References: The Billion Dollar Mistake" https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/. – alfC Apr 06 '21 at 00:50
-4

Any scenarios where people decided to use === (triple equal) operator to check for equality indicate that if you assume

(!(a === b)) == (a != b)

then your == is not a negation of !=.

Note that I am not implying that there is a === operator in C++! I am illustrating a scenario, as was asked in the question.

cigien
  • 57,834
  • 11
  • 73
  • 112
Vlad Feinstein
  • 10,960
  • 1
  • 12
  • 27
  • 1
    This isn't even a good C++ joke since there's no unary `=` ... – davidbak Apr 05 '21 at 23:03
  • 2
    @VladFeinstein I'm not sure why you think it would be obvious. Readers of this post may have different backgrounds, and there's no reason to believe *a priori* that `===` doesn't exist (it's in fact used in other languages as you point out). Putting it in an answer *without* making it clear that it's not valid C++ on a post about that language, is needlessly confusing. Your edit is much better, thanks, but you should still remove the meta commentary about downvotes. – cigien Apr 06 '21 at 00:58
  • I think a === b, in C++ would be `&a == &b`. – alfC Apr 06 '21 at 10:44