C++20 显式默认相等运算符

use*_*486 7 c++ default operator-overloading comparison-operators c++20

我试图了解 C++20 中引入的新默认比较运算符。我的问题是关于何时隐式定义显式默认的比较运算符。下面的代码示例说明了这个问题:

#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
*/
Run Code Online (Sandbox Code Playgroud)

该程序的输出依赖于编译器。似乎 MSVC 在遇到默认声明时为类 D 定义了 operator==,因此它不使用稍后为类 B 定义的 operator==。相比之下,gcc 等待 D 的隐式定义operator== 直到实际需要它,此时为 B 定义的 operator== 在范围内,并被使用。哪种行为(如果有)是正确的?

一个相关的问题是,为什么不能为具有引用成员的类声明默认的 operator== ?我可以看到引用成员可能会对 MSVC 方法造成问题,因为当遇到 operator== 的默认声明时,引用成员可能会引用不完整的类型。使用 gcc 方法,在 gcc 尝试定义默认运算符之前,引用的类型将始终是完整的。

Nic*_*las 3

GCC 在这里是错误的(考虑到其结果,这并不奇怪)。在创建默认比较运算符的定义时,标准表示

比较运算符函数的默认定义中的名称查找是从与其函数体等效的上下文中执行的。

默认函数的函数体是 where = defaultis。因此,该bool operator==(B, B)函数对于默认比较运算符的函数体不应该是可见的。