首页 > 解决方案 > 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
*/

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

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

标签: c++operator-overloadingdefaultc++20comparison-operators

解决方案


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

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

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


推荐阅读