C++20中operator<=>返回类型的隐含排序公理承诺问题
问题解答
是的,当你为类的operator<=>指定std::partial_ordering、std::weak_ordering或std::strong_ordering作为返回类型时,你的类必须遵守对应排序类型的公理约束——C++20标准虽然没有在operator<=>的定义条目下直接罗列这些公理,但在这些排序类别(comparison categories)的语义说明中明确了要求,违反这些约束会导致未定义行为。
下面是每个排序类型对应的核心公理和语义要求:
std::strong_ordering
对应强全序,要求满足:
- 自反性:
a <= a恒为真 - 反对称性:若
a <= b且b <= a,则a == b(此处的==指值完全相等,对象在所有语境下可互换) - 传递性:若
a <= b且b <= c,则a <= c - 全可比性:任意两个对象
a和b,要么a <= b,要么b <= a(不存在不可比较的情况)
典型例子:整数、不含NaN的浮点数的比较。
std::weak_ordering
对应弱全序,和强序的核心区别是:等价的对象不一定值完全相等,但比较结果完全一致。要求满足:
- 自反性、反对称性、传递性(和强序一致)
- 全可比性(无不可比较的对象)
- 等价关系为“比较不可区分”:若
a <=> b == 0,则对于任意c,a <=> c和b <=> c的结果完全相同
典型例子:忽略大小写的字符串比较("Apple"和"apple"等价,但并非同一个对象)。
std::partial_ordering
对应偏序,允许存在不可比较的对象(即a <=> b返回std::partial_ordering::unordered),要求满足:
- 传递性:若
a <= b且b <= c,则a <= c;若a < b且b < c,则a < c,以此类推 - 反对称性:若
a <= b且b <= a,则a == b - 不要求全可比性:允许存在
a和b,既不满足a <= b,也不满足b <= a
典型例子:包含NaN的浮点数比较(NaN和任何数都不可比较)。
为什么标准里看起来没直接提?
这些约束并不是直接写在operator<=>的定义中,而是隐含在排序类别语义和依赖比较逻辑的标准库函数要求里。比如std::sort要求 comparator 满足严格弱序(对应std::weak_ordering的语义),如果你的operator<=>返回weak_ordering但违反了传递性,那么用std::sort排序该类对象时,行为是未定义的。
内容的提问来源于stack exchange,提问作者yugr
相关产品推荐
相关产品推荐

