5

When overloading the "==" operator in c++, is there a standard definition as to what equality explicitly means, or a set of guidelines as how "==" should behave?

I currently have a class that does not store its entire self in memory. It basically uses a priority queue to determine how often an object inside itself is being used and when objects are popped from the end of the queue they are removed from memory and written to disk.

So now the problem occurs with equality, what does it mean for two of these objects to be equal. Because we could start with objects A and B which are the same in every way, they have loaded the same data into memory and they have the same data on disk. But then after calling a series of functions on A and B they could now be different. A and B still have the same data on disk but they they have different data loaded into memory. So the question is should A == B resolve to true or false?

Are there a set of rules or guidelines that define how this should work? Or is this just a situation where I decide what makes the most sense for the program and document what "==" does?

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
David Saxon
  • 1,406
  • 1
  • 12
  • 23
  • 2
    It depends on your data structure, its semantics, and its invariants. There is no one-size-fits-all answer. – ildjarn Dec 20 '12 at 22:35
  • 1
    If the meaning you want it to have is not intuitively clear, you are better off implementing a member function with an appropriate name and not overload ==. – Svalorzen Dec 20 '12 at 22:37

3 Answers3

16

Any operator== overload should respect the axioms of an equivalence relation, that is

  • x == x, for all objects x
  • if x == y, then y == x
  • if x == y and y == z, then x == z.

Many algorithms using == rely on it implementing an equivalence relation, formalized in §17.6.3.1 as the EqualityComparable concept.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • 1
    the Container Requirements 23.2.5 for unordered associative containers do require that a key equality predicate (which defaults to `std::equal_to`, i.e. `operator==`) induces an equivalence relation. – TemplateRex Feb 14 '13 at 11:29
  • @rhalbersma Thanks, I guess I missed that bit. – Fred Foo Feb 14 '13 at 11:35
  • Just rechecked the Standard: table 17 in 17.6.3.1 describes Template argument requirements and defines the concept `EqualityComparable` in terms of an equivalence relations using your 3 conditions. The EqualityComparable concept applies to all containers as a whole, to their allocators, to all iterators, and to predicates for algorithms such as `unique` and the unordered containers. So basically users can do whatever they want with an `operator==` but if they want to correctly interact with the Standard Library, they better conform to the equivalence relation defined by `EqualityComparable`. – TemplateRex Feb 14 '13 at 13:38
11

There's no definition in the standard on how an overloaded operator == should behave.

But a good enough guideline is this - if you have to think about it for as long as you have, you probably shouldn't even be overloading operator ==. If it's not intuitive, it does more harm than good.

So the question is should A == B resolve to true or false?

IMO, it should result in a compiler error. :)

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • 1
    I agree. Operator overloading is only good when the meaning of the overloads is extremely intuitive. The only places I think it's useful are numerical types, smart pointers, and `operator[]` on containers. Use something like `containsSameData()`. – japreiss Dec 20 '12 at 22:39
  • Thanks, now that you say it makes a lot more sense to have two different member functions that test the different types of equality I mentioned, that way I'm not limiting the user. – David Saxon Dec 20 '12 at 22:51
  • @larsmans: Luchian said "if you have to think about it for as long as you have..." I doubt he'd think that long about it for containers or numeric types. – Mooing Duck Dec 20 '12 at 22:51
  • @larsmans I'm not saying C++ is perfect. Smart pointers have overloaded `operator ==`? What does it do? I honestly don't know. Does it compare the inner pointers? The objects they point to? IMO, that's not a very good example... – Luchian Grigore Dec 20 '12 at 22:53
  • @larsmans: I think if you have to think a long time about what `operator==` should do, then it isn't intuitive, and should therefore be designed so that any attempt to use `operator==` results in a compiler error. I agree with what Luchian said 100%. (Or, I did until he mentioned smart pointer `==`. That makes sense to me. They're equal if they point to the same object.) – Mooing Duck Dec 20 '12 at 22:55
  • @MooingDuck that doesn't count, it's a comment :P. – Luchian Grigore Dec 20 '12 at 22:56
  • @larsmans my class does not overload the < operator. The class uses a priority queue but is not contained within one. – David Saxon Dec 20 '12 at 22:56
  • Undid the -1 (after a trivial edit, hope @LuchianGrigore doesn't mind). Sorry about that. – Fred Foo Dec 20 '12 at 22:58
  • @larsmans no need, I see your point. I do stick to mine though :) – Luchian Grigore Dec 20 '12 at 23:00
2

ALL operator overloading should do "what you expect". There is no point in having an operator == that returns true if the objects aren't substantially the same. How you define "the same" is of course potentially something we could argue about. One could implement a "nocasestring" where it behaves like a string, but if you have a string "HELLO" and one "hello", they are considered equal, because case doesn't matter. Or if you implemented your own "Float" class, where == does some math to avoid the fragile comparison of regular floating point. So yes, there are cases where == doesn't do EXACTLY "for all elements is a. == b.", but it should really be the exception.

Likewise, if an operator doesn't make totally sense, don't make it do something "surprising" (e.g. - for strings - what does it do? Or multiply one string by another string - multiply by integer may have a meaning).

Surprises in programming is a bad idea. If things don't work the way you EXPECT, you get bad experiences from reading/modifying the code.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227