C++20 explicitly defaulted equality operator

Viewed 432

I'm trying to understand the new default comparison operators introduced in C++20. My issue is about when an explicitly defaulted comparison operator gets implicitly defined. The following code example illustrates the question:

#include <iostream>

struct B
{
  operator bool() const { return true; }
};

struct D : B
{
  bool operator==(const D&) const = default;
};

bool operator==(B, B) { return false; }

int main ()
{ D d;
  std::cout << (d == d);
}

/* Outputs:
0   in gcc 10.1
1   in msvc 19.26
*/

The output of this program is compiler-dependent. It seems that MSVC defines the operator== for class D when it is encounters the declaration as defaulted, hence it doesn't use the operator== that is defined later for class B. By contrast, gcc waits with the implicit definition of D's operator== until it is actually needed, by which time the operator== defined for B is in scope, and gets used. Which behavior, if either, is correct ?

A related question, is why a defaulted operator== can't be declared for a class with reference members ? I could see that reference members could pose a problem with the MSVC approach, because a reference member might refer to an incomplete type when the defaulting declaration for operator== is encountered. With the gcc approach, the reference's type would always be complete before gcc attempts to define the defaulted operator.

1 Answers

GCC is wrong here (not unsurprisingly considering its results). When creating the definition of a defaulted comparison operator, the standard says:

Name lookups in the defaulted definition of a comparison operator function are performed from a context equivalent to its function-body.

And the function body of a defaulted function is where = default is. Therefore, the bool operator==(B, B) function should not be visible to the function body of the defaulted comparison operator.

Related