基于逻辑与的多变量比较:实现匹配原有运算符的<=>运算符
如何为自定义结构体实现符合特定逻辑的<=>运算符
原结构体定义如下,其所有比较运算符均通过逻辑与逐个判断成员条件:
struct point { float x, y; bool operator ==(point p) { return x == p.x && y == p.y; } bool operator <(point p) { return x < p.x && y < p.y; } bool operator <=(point p) { return x <= p.x && y <= p.y; } bool operator >(point p) { return x > p.x && y > p.y; } bool operator >=(point p) { return x >= p.x && y >= p.y; } };
尝试迁移到C++20的<=>运算符时遇到困难,现有接近的实现如下:
std::partial_ordering operator<=>(const point& p) const { std::partial_ordering c = x <=> p.x; if((y <=> p.y) != c) return std::partial_ordering::unordered; return c; }
但该实现仅对<、>运算结果正确,<=、>=运算结果错误。例如point(0, 0) <= point(0, 1)本应返回true,但此实现返回unordered,导致默认生成的<=运算符判断错误。
核心问题
原结构体的比较逻辑不是标准的偏序/全序关系,而是一种「全分量满足」的谓词判断:
a < b要求a.x < b.x且a.y < b.ya <= b要求a.x <= b.x且a.y <= b.y
而<=>运算符的设计目标是表达对象间的排序关系(比如字典序、逐成员优先级比较),它的返回值(strong_ordering/partial_ordering)描述的是两个对象在排序中的相对位置,无法直接对应这种「全与」的逻辑。
可行方案
方案1:保留显式定义的比较运算符(推荐)
由于原有逻辑和<=>的语义不兼容,最直接的方式是继续显式定义所有比较运算符,不需要使用<=>。这种方式逻辑清晰,完全保留原有行为,不会出现语义冲突。
方案2:用<=>配合手动重载冲突运算符
如果一定要使用<=>,需要手动重载<=、>=等运算符,因为默认生成的版本会依赖<=>的结果,而这和原有逻辑不符。示例代码如下:
struct point { float x, y; bool operator ==(const point& p) const { return x == p.x && y == p.y; } std::partial_ordering operator<=>(const point& p) const { // 仅用于支持==、!=、<、>,匹配原有逻辑 if (x < p.x && y < p.y) return std::partial_ordering::less; if (x > p.x && y > p.y) return std::partial_ordering::greater; if (*this == p) return std::partial_ordering::equivalent; return std::partial_ordering::unordered; } // 手动重载<=,保留原有逻辑 bool operator <=(const point& p) const { return x <= p.x && y <= p.y; } // 手动重载>=,保留原有逻辑 bool operator >=(const point& p) const { return x >= p.x && y >= p.y; } };
注意:这种方式需要确保手动重载的运算符完全覆盖原有逻辑,避免依赖<=>生成的默认版本。
内容的提问来源于stack exchange,提问作者vtable
相关产品推荐
相关产品推荐

