1

When the free operator function and the member operator function are both defined, which one is used for comparison?

#include <iostream>

class A;
class B;

bool operator==(const A &a, const B &b){ return true; };

class A
{
  public:
      bool operator==( const B &rhs ){ return false; };
};

class B
{
};

int main( int argc, char **argv )
{
  A a;
  B b;
  if( a == b )
  { 
      std::cout << "a==b" << std::endl;
  }
};

I ran the code a couple times and it seems that the member operator wins out. Is this always the case?

megamonium
  • 463
  • 3
  • 7

2 Answers2

6

I ran the code a couple times and it seems that the member operator wins out.

Yes, the member wins in your example. But not for the reason you think.

Member functions have an implicit object parameter (what this points to), and the type of the object parameter is determined by the cv-qualifiers at the end of the member function. In this case, your member operator has no cv-qualifiers, so the type of the implicit object is simply A.

Basically, we have two candidates:

bool operator==(A const&, B const&); // your non-member operator
bool operator==(A&,       B const&); // your member operator

The member operator is a better match because the first parameter is a better match - we don't have to take a more const-qualified reference to a.

If you had made your operator const (as you generally should), then we'd have these two candidates:

bool operator==(A const&, B const&); // your non-member operator
bool operator==(A const&, B const&); // better member operator

Which are identical, there is no reason to prefer one to the other, and we'd get an ambiguity. There is no rule to prefer a member to a non-member function (or vice versa).

Barry
  • 286,269
  • 29
  • 621
  • 977
2

You're declaring the 1st parameter type as const & in the non-member operator. Then given a == b, for the non-member operator to be called a needs to be converted to const. On the other hand the member operator is declared as non-const, then its operand is a non-const A then it's an exact match and wins in overload resolution.

If you change the 1st parameter type of the non-member operator to A& you'll get an ambiguity error. LIVE

Or qualify the member operator as const you'll get the ambiguity error too. LIVE

songyuanyao
  • 169,198
  • 16
  • 310
  • 405