如何为C++自定义类型高效重载operator<=>以仅比较属性子集并实现完整关系操作
你遇到的编译错误是因为std::ranges::sort对元素的比较要求比传统std::sort更严格——它要求元素类型满足std::totally_ordered_with概念,仅手动实现operator<已经不足以满足这个C++20的新规范。
要解决这个问题,我们可以利用C20引入的**三路比较运算符operator<=>**来实现强序关系,同时让编译器自动生成所有需要的比较运算符(<、<=、>、>=、==、!=),还能避免重复比较带来的性能损耗,完全贴合现代C的设计思路。
接下来分两步修改你的代码:
第一步:为basic类实现三路比较
我们需要让basic的比较只关注value和property,忽略synthetized属性:
#include <compare> // 必须包含此头文件以使用std::strong_ordering struct basic { std::string synthetized; // 不参与比较的属性 unsigned value; unsigned property; // 实现三路比较,返回强序关系 friend auto operator<=>(const basic& a, const basic& b) noexcept { // 先比较value,若有差异直接返回结果 if (auto cmp = a.value <=> b.value; cmp != 0) { return cmp; } // value相等时,再比较property return a.property <=> b.property; } // 显式定义==,只比较参与排序的成员(忽略synthetized) friend bool operator==(const basic& a, const basic& b) noexcept { return a.value == b.value && a.property == b.property; } };
operator<=>(...)返回std::strong_ordering(因为unsigned的<=>默认返回强序),完全满足std::ranges::sort对强序的要求- 加上
noexcept是因为标准库的比较操作通常期望 noexcept,这能帮助编译器做更多优化,同时符合概念的严格要求 - 必须显式定义
operator==:当自定义operator<=>时,编译器会删除默认的operator==,而我们需要忽略synthetized,所以不能直接用= default(默认实现会比较所有成员)
第二步:为composed类实现三路比较
composed的比较逻辑很简单,直接委托给内部的basic成员,忽略meta属性:
struct composed { basic value; custom_type meta; // 不参与比较的属性 // 直接复用basic的三路比较结果 friend auto operator<=>(const composed& a, const composed& b) noexcept { return a.value <=> b.value; } // 同样委托给basic的==判断 friend bool operator==(const composed& a, const composed& b) noexcept { return a.value == b.value; } };
这里的逻辑和basic类一致:委托内部成员的比较逻辑,忽略不需要参与的属性,同时显式定义operator==以匹配比较规则。
为什么这样能解决问题?
修改后的代码完全满足std::ranges::sort的要求:
- 两个类都实现了返回
std::strong_ordering的operator<=>,符合强序关系的核心要求 - 显式定义了
operator==,满足std::equality_comparable概念 - 编译器会自动基于
operator<=>和operator==生成所有其他比较运算符(<、<=、>、>=、!=),不需要你手动编写冗余代码
额外的性能优势
三路比较相比传统的operator<实现,能避免重复的比较操作:比如原来的operator<需要先判断a.value < b.value,如果不成立还要再判断a.value == b.value,而三路比较只需要一次操作就能得到value的比较结果,性能更高效。
现在你再调用std::ranges::sort(container)就可以正常编译运行了,同时还获得了完整的关系操作能力。
内容的提问来源于stack exchange,提问作者ABu
相关产品推荐
相关产品推荐

