问题是如何乘坐火箭起飞:)
我说的是运营商<=>
。起初在我看来,这将是一些简单的事情,比如strcmp
- 返回小于、大于或等于。
第一个令人失望的是,它们会返回某种“左”类型,您甚至不会直接在if
. 我决定我真的不需要他,他太奇怪了。
但是最近我遇到了一个注释,如果你只为你的类型定义它,那么你不需要编写一个比较运算符。例如,我开始寻找并阅读有关他的信息-但很明显他喝了一点:(没有添加清晰度。
如果我理解正确,有人可以帮助我理解通过定义一个运算符<=>
,我会自动获得所有关系运算符吗?
以及如何正确定义它?
作为奖励:) - 为什么这么复杂?不只是,比如说,返回-1、0、+1?
好吧,或者告诉我在哪里有关于这个主题的一些咀嚼材料,最好是俄语。
<=>
通常不需要手动呼叫。但如果你真的想要,那么它的结果可以与零进行比较,大致类似于 的结果strcmp
。示例:(a <=> b) < 0
表示a < b
(括号可以省略)。关于它的返回类型如下。如果你
<=>
通过编写重载= default
,那么所有 6 个运算符都会自动工作:==
,!=
,<
,<=
,>
,>=
. 将比较所有字段。= default
您只能在类主体中重载 with 。选择:如果手动超载
<=>
,则只有 4 个可以工作:<
,<=
,>
,>=
. 您==
需要单独重新加载,然后它!=
会自动开始工作(不管<=>
)。without
= default
可以在类内部和外部重载。最简单的方法是作弊,这样写:
并且最好以
tie
不写4次的方法取出。重要的是不要屈服于诱惑而没有
operator==
实现a <=> b == 0
。一般来说,这会比使用==
. (例如,要通过 比较两个字符串<=>
,需要遍历字符。或者==
您可以先比较大小,如果它们不同,则不执行其他操作。)operator==
在 C++20 中,您还可以重载为= default
. 它将比较所有字段是否相等,a <=> b == 0
即使您重载了也不会使用<=>
。如果你想
<=>
手写而不用tie
,那么你需要选择返回类型。在下一个答案中,他们建议int
,它甚至似乎有效,但不知何故令人怀疑。有三个标准类可供选择,它们的行为大致类似于枚举:std::strong_ordering
- 更大/更少/等于std::weak_ordering
- 大于/小于/等价 - 基本相同,但表示不同的对象可以被认为是等价的。一个例子是不区分大小写的字符串比较。std::partial_ordering
- 大于/小于/等价/不可比较 - 与 相同weak_ordering
,但添加了第四个值“不可比较”,这会导致所有 6 个运算符返回 false。示例:NaN与任何其他数字“无法比较”,对其自身也是如此。所有三个都可以与零进行比较:
x < 0
均值x == ...::less
等。还有
<compare>
各种方便编写的小工具<=>
,例如std::common_comparison_category
,它为被比较的对象类型选择适当的返回类型。<=>
可用于比较不同类型的对象。显然= default
,在这种情况下它不会有帮助。编译器知道操作数的顺序并不重要,所以重载就足够了
A <=> B
,B <=> A
它会自己工作,所有 4 个运算符也可以处理任何参数的顺序。同样,如果您重载
A == B
,它将B == A
自行工作,并且也!=
可以使用任何顺序的参数。详细信息:实际上没有其他语句生成
<=>
.==
相反,当您尝试调用另一个运算符时,编译器会将其替换为 call<=>
or==
,可能会更改参数的顺序。不同之处在于,例如,您不能获取这样一个不存在的运算符 (a la
&MyClass::operator<
) 的地址,并且可能还有其他东西。作为一个实际的人:),我将给出一个重新定义运算符的实际示例。
如果您对按字段进行比较(例如在元组中)感兴趣,那么在类中(为了确定性
Test
)编写就足够了如果你想要一些奇怪的东西,那么你需要定义这个 operator 和 operator
==
。例如,这是这样一个类和比较,其中偶数小于奇数。
在 VC++2019 输出中
好吧,你可以在程序中使用火箭,例如,像这样:
PS 同时,没有人打扰您定义自己的关系运算符,在这种情况下,当然会使用它们,而不是生成的。
PPS 编程是一门实验科学 :),所以请尝试深入研究代码...