为什么必须提供 operator==,当 operator<=> 足够了呢?
嗯,主要是因为它
不够 :-)
当 C++ 重写您的语句时,相等和排序是
不同的概念:
| | 相等 | 排序 |
|--------|------|------|
| 主要 | == | <=> |
| 次要 | != | <, >, <=, >= |
主要运算符具有反转的能力,而次要运算符具有在其对应的主要运算符的条件下被重写的能力:
- 反转意味着 a == b 可以是:
- 如果可用:a.operator==(b)
- 如果不可用:b.operator==(a)
- 重写意味着 a != b 可以是:
- 如果可用:! a.operator==(b)
最后一个可能也可以是 ! b.operator==(a) 如果您必须重写并反转它(我不完全确定,因为我的经验大多数是比较相同类型)。
但是,重写不能跨越相等/排序边界,这意味着 <=> 不是 == 的重写候选项。
原因在于分离相等和排序可以在
此 P1185 论文中找到,该论文是讨论此问题的众多标准会议之一。
有许多情况下,自动使用 <=> 实现 == 可能会非常低效。例如字符串、向量、数组或任何其他集合。您可能不想使用 <=> 来检查两个字符串的相等性。
这是因为
<=>
需要处理整个字符串才能确定顺序,然后检查顺序是否相等。但是,一个简单的长度检查可以很快地告诉你它们不相等。这就是O(n)时间复杂度、十亿级别的比较和O(1)几乎立即得出结果之间的区别。
如果你知道它没问题(或者你愿意接受任何可能带来的性能损失),你总是可以默认相等。但最好不要让编译器替你做出这个决定。
更详细地说,考虑以下完整程序:
#include <iostream>
#include <compare>
class xyzzy {
public:
xyzzy(int data) : n(data) { }
auto operator<=>(xyzzy const &other) const {
if (n < other.n) return std::strong_ordering::less;
if (n > other.n) return std::strong_ordering::greater;
return std::strong_ordering::equal;
}
private:
int n;
};
int main() {
xyzzy twisty(3);
xyzzy passages(3);
if (twisty < passages) std::cout << "less\n";
if (twisty == passages) std::cout << "equal\n";
}
它无法直接编译,因为最后一个语句需要一个“operator==”。但是您不必提供一个“真正的”(第一个被注释掉的块),您可以告诉它使用默认值(第二个)。在这种情况下,这可能是正确的决定,因为使用默认值没有实际性能影响。
请记住,只有在您明确提供三向比较运算符(并且当然使用“==”或“!=”)时才需要提供相等运算符。如果两者都不提供,则C ++将为您提供两个默认值。
即使您必须提供两个函数(其中一个可能是默认函数),这仍然比以前好,以前您必须明确提供它们全部,例如:
- a == b。
- a < b。
- a != b,定义为!(a == b)。
- a> b,定义为!(a
= b,定义为!(a