我知道在 C++ 中定义某些运算符可以让编译器为类生成其他运算符。从我读到的在这篇 cppreference 文章中看来以下内容是正确的:
operator==
必须明确定义(可能是默认值)才能使用。operator!=
,则
operator==
是从 operator==
生成的。operator<=>
生成其他四个关系运算符(如果一切按计划进行,即 operator<=>
返回其他四个可以解释的结果,并且对于原始参数顺序和反向参数顺序都有明确定义)operator<=>
,
operator==
也不会生成 std::strong_ordering
,据我所知,当且仅当两个比较对象相同(无法区分)时,应该返回一个与 0
相当的对象。我自己用以下代码测试了这一点#include <iostream>
class Foo
{
public:
int x;
int y;
// Lexicographic ordering but by the y member first, and by x second.
std::strong_ordering operator<=>(const Foo& other)
{
if (std::strong_ordering cmp = y <=> other.y; cmp != 0)
return cmp;
return x <=> other.x;
}
};
int main()
{
Foo f = {1, 1}, g = {1, 0};
std::cout << (f == g);
}
返回错误
no match for ‘operator==’ (operand types are ‘Foo’ and ‘Foo’)
。
我想知道的是,首先,为什么
operator<=>
不生成 operator==
,其次 - 是否存在哪些运算符生成其他运算符(以及哪些运算符)的完整列表,或者 cppreference 文章是否完整在这方面并且没有产生其他运营商?例如,我期望 operator+(Foo)
和 operator-()
生成 operator-(Foo)
,因为减法只不过是加上加法逆元。然而,事实证明这是不正确的,我也测试过。
哪些运算符在 C++ 中隐式定义/生成其他运算符?
只有一种情况是一个运算符定义/生成另一个运算符,即当您default
operator<=>
时,您also获得默认的operator==
。这是完整的列表。
其他一切都不是基于声明运算符,而是基于重写表达式:
operator!=
生成 operator==
,而是表达式 x != y
也尝试计算为 !(x == y)
operator<
生成 operator<=>
,而是表达式 x < y
也尝试计算为 (x <=> y) < 0
在您的情况下,
f == g
根本没有operator==
候选者,所以它的格式不正确。 <=>
的原始设计也会尝试将此表达式重写为 (f <=> g) == 0
(同样,不是生成 operator==
而是重写表达式)。但这被证明存在严重的性能问题,因此它被更改为不这样做。您可以在我的博客上阅读有关 C++20 中的比较的更多信息。
在这种情况下,由于您正在进行按成员比较,您可以简单地:
bool operator==(Foo const&) const = default;
或者如果您愿意的话可以手动编写。不管怎样,你的 operator<=>
缺少
const
- 比较运算符对称很重要。