In C++ do you need to overload operator== in both directions?

C++Operator Overloading

C++ Problem Overview


Say I am working with a class:

class Foo{
public:
  std:string name;
  /*...*/
}/*end Foo*/

and I provide an overload for operator==

bool operator==(const Foo& fooObj, const std::string& strObj) {
    return (fooObj.name == strObj);
}

Do I also need to re-implement the same logic in reverse?

bool operator==(const std::string& strObj, const Foo& fooObj) {
    return (strObj == fooObj.name);
}

C++ Solutions


Solution 1 - C++

(C++20 onward)

With the acceptance of p1185 into C++20, you don't need to provide more than one overload. The paper made these changes (among others) to the standard:

> [over.match.oper] > > 3.4 - [...] For the != operator ([expr.eq]), the rewritten candidates include all member, non-member, and built-in candidates for the operator == for which the rewritten expression (x == y) is well-formed when contextually converted to bool using that operator ==. For the equality operators, the rewritten candidates also include a synthesized candidate, with the order of the two parameters reversed, for each member, non-member, and built-in candidate for the operator == for which the rewritten expression (y == x) is well-formed when contextually converted to bool using that operator ==. [ Note: A candidate synthesized from a member candidate has its implicit object parameter as the second parameter, thus implicit conversions are considered for the first, but not for the second, parameter. — end note ] [...] > > 8 [...] If a rewritten candidate is selected by overload resolution for a != operator, x != y is interpreted as (y == x) ? false : true if the selected candidate is a synthesized candidate with reversed order of parameters, or (x == y) ? false : true otherwise, using the selected rewritten operator== candidate. If a rewritten candidate is selected by overload resolution for an == operator, x == y is interpreted as (y == x) ? true : false using the selected rewritten operator== candidate.

The above means that not only do you not need to provide the operator with the order of the operands reversed, you also get != for free! Furthermore, the operator== function can be a member if it makes sense. Though as the note in the first paragraph above says, it being a member or free function will affect implicit conversions so you still need to bear that in mind.


(Upto C++17)

You do if you want to support comparisons where the string is on the left and the Foo is on the right. An implementation won't reorder the arguments to an overloaded operator== to make it work.

But you can avoid repeating the implementation's logic, though. Assuming your operator should behave as expected:

inline bool operator==(const std::string& objA, const Foo& objB) {
    return objB == objA; // Reuse previously defined operator
}

Solution 2 - C++

Yes, you do. Just like in lots of other languages, C++ takes sides and comparisons between two objects of different types will lead to calls to two different comparison operators depending on the order.

Of course, you want them to be consistent and not surprising, so the second should be defined in terms of the first.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionhehe3301View Question on Stackoverflow
Solution 1 - C++StoryTeller - Unslander MonicaView Answer on Stackoverflow
Solution 2 - C++Matthieu BrucherView Answer on Stackoverflow