c++20的三路比较运算符()有什么用? (简化对象比较)

三路比较运算符operator是C++20引入的“太空船运算符”,用一个函数定义全部比较关系;可default生成或手动返回std::strong_ordering等,但显式定义operator==会阻止==的隐式合成。

)有什么用? (简化对象比较)">

三路比较运算符 operator 是什么

它是 C++20 引入的“太空船运算符”,用一个函数同时定义 ==> 等全部比较关系,避免手写六个比较运算符的重复劳动。

怎么写一个基本的 operator

最常见写法是返回 std::strong_ordering(或 std::weak_orderingstd::partial_ordering),编译器会自动合成其余比较操作符(前提是没显式定义它们)。

struct Point {
    int x, y;
    auto operator<=>(const Point& other) const = default; // 编译器自动生成
};

也可以手动实现:

struct Version {
    int major, minor, patch;
    auto operator<=>(const Version& v) const {
        if (auto cmp = major <=> v.major; cmp != 0) return cmp;
        if (auto cmp = minor <=> v.minor; cmp != 0) return cmp;
        return patch <=> v.patch;
    }
};
  • = default 仅在所有成员都支持 且可平凡比较时安全
  • 手动实现中,用 if (auto cmp = ...; cmp != 0) return cmp 是惯用模式,避免多次计算
  • 返回类型选 std::strong_ordering 表示全序(如整数、字符串),std::partial_ordering 用于可能有 NaN 的浮点场景

为什么不能随便混用 ==

如果类里显式定义了 operator==,即使写了 operator,编译器也不会自动生成 == —— 它会优先用你写的 ==,而 仍只负责大小关系。

  • 若只定义 operator== 会被隐式合成(等价于 a b == 0
  • 但一旦你加了 bool operator==(const T&) const { ... },哪怕逻辑完全一样,== 就不再由 推导
  • 这会导致行为不一致:比如自定义 == 忽略大小写,但 按字节比较,那 a == b 为真时 a b 可能非零

容易被忽略的兼容性细节

operator 不会自动让类支持 std::sortstd::map —— 这些容器仍依赖 operator,而它默认由 合成;但如果你禁用了合成(比如显式删掉 operator),就会编译失败。

  • 检查是否真生成了 operator:用 static_assert(std::is_invocable_v)
  • 模板代码中(如 std::ranges::sort),传入自定义比较器更稳妥,别盲目依赖合

  • 第三方库若用 SFINAE 检测 operator==,而你只靠 合成,可能因未实例化而失败

真正省事的前提是:所有成员类型本身支持三路比较,且你不插手任何一个比较运算符的显式定义 —— 多一动,就得多一分验证。