operator是c++20引入的三向比较运算符,用于一次性定义所有关系比较逻辑;返回std::strong_ordering(推荐默认)、std::weak_ordering或std::partial_ordering之一;需显式声明operator==以支持==运算符。

什么是 operator(C++20 三向比较运算符)
它不是语法糖,也不是宏,而是 C++20 引入的真正运算符——用来**一次性定义所有关系比较逻辑**。你写一次 operator,编译器就能自动生成 ==、!=、、<code>、<code>>、>= 的行为(前提是类型满足条件)。
怎么写一个可用的 operator
核心是返回 std::strong_ordering、std::weak_ordering 或 std::partial_ordering 之一。选哪个取决于你的类型是否支持等价、可交换、甚至允许 NaN 这类未定义序:
-
std::strong_ordering:适用于整数、字符串等“完全可比且无歧义”的类型,推荐默认用这个 -
std::weak_ordering:比如大小写不敏感字符串,"A"和"a"等价但不是同一对象 -
std::partial_ordering:仅用于浮点数(因 NaN 不参与任何比较),其他场景基本不用
示例(简单结构体):
struct Point {
int x, y;
auto operator<=>(const Point& other) const = default;
};
这里 = default 让编译器按成员顺序自动生成;若需自定义逻辑,就手动返回:
立即学习“C++免费学习笔记(深入)”;
auto operator<=>(const Point& other) const {
if (auto cmp = x <=> other.x; cmp != 0) return cmp;
return y <=> other.y;
}
为什么写了 operator 还报错说找不到 ==
因为 operator 默认**不生成 operator==**(C++20 初期设计如此,后来加了补丁但有前提):
- 如果你写了
operator但没写operator==,而代码里又用了==,就会编译失败 - 解决办法只有两个:
default掉operator==,或显式定义它 - 更安全的做法是同时声明:
bool operator==(const Point&) const = default; - 注意:
= default对==有效,但对!=不再需要——C++20 起a != b自动重写为!(a == b)
哪些情况不能靠 operator 省事
它省的是“写一堆重复比较逻辑”,不是“绕过语义设计”:
- 成员含指针或句柄时,
= default会做逐字节比较,大概率不符合业务意图 - 涉及浮点字段,直接
返回std::partial_ordering,但多数业务其实希望把 NaN 当错误处理,而不是参与排序 - 继承体系中,基类没定义
operator,派生类= default会失败——必须基类先支持 - 和旧代码混用时,某些模板(如
std::sort)仍可能依赖operator,而你只提供了 <code>,这时要确保 ADL 或模板实参推导能正确找到它
最常被忽略的一点:三向比较的结果值本身不能直接当 int 用。比如 (a b) > 0 合法,但 (a b) == 1 是错的——得用 std::is_gt(a b) 这类谓词,或者直接跟 0 比较(因为 ordering 类型重载了与 0 的比较)。









