1

Stroustrup writes :

Consider a binary operator @. If x is of type X and y is of type Y, x@y is resolved like this:

• If X is a class, look for operator@ as a member of X or as a member of a base of X; and

• look for declarations of operator@ in the context surrounding x@y; and

• if X is defined in namespace N, look for declarations of operator@ in N; and

• if Y is defined in namespace M, look for declarations of operator@ in M.

Declarations for several operator@s may be found and overload resolution rules (§12.3) are used to find the best match, if any. This lookup mechanism is applied only if the operator has at least one operand of a user-defined type. Therefore, user-defined conversions (§18.3.2, §18.4) will be considered. Note that a type alias is just a synonym and not a separate user-defined type (§6.5). Unary operators are resolved analogously.

Note that in operator lookup no preference is given to members over nonmembers. This differs from lookup of named functions

So what means the bold expression. If class has member and in the same time there is non-member function which could be used in the context, then no preference is given to member? For example

class A
{
public:
    bool operator==(const A&)
    {
        return true;
    }
};

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

int main()
{
    A a, b;
    a == b;
}

I think(and compilers agree with me :) ) that member function should be called, but as written above no preference should be given to member operator. So what exactly means Stroustrup by that sentence?

Ekleog
  • 973
  • 5
  • 18

1 Answers1

2

Your code only compiles because your operators are not equivalent in this context. One is better than the other, according to the rules of implicit conversion sequence ranking.

Note that your member operator lacks const-qualification for its first (left) argument. It actually stands for bool operator==(A&, const A&).

Since your a and b in main are not declared as const, the implicit conversion sequence for the left-hand operand is shorter (better) for member operator. It does not require a qualification conversion of a from A to const A. This is what makes it a better candidate. This is why your member function version is selected.

To make both versions equivalent you have to add const to your member operator declaration

class A
{
public:
    bool operator==(const A&) const
    {
        return true;
    }
};

and that will immediately make your a == b comparison ambiguous.

AnT
  • 291,388
  • 39
  • 487
  • 734