在 C++20 中,我们迎来了一个全新的特性: spaceship 操作符。它可以快速地对两个对象进行比较,省去了我们手动实现专门的比较函数的麻烦。但是,在某些情况下,我们可能希望在进行比较时忽略某些数据成员,而这就涉及到了 operator<=> 的使用。

在这篇文章中,我们将讨论如何使用 operator<=> 忽略一个数据成员。举个例子,假设我们有一个表示二维平面上点的结构体:

struct Point {

double x;

double y;

};

我们想要进行点的比较,但是在进行比较时想要忽略 y 坐标。我们可以按照以下方式重载 operator<=>:

struct Point {

double x;

double y;

auto operator<=>(const Point&) const = default;

auto operator<=>(const Point& other) const requires std::three_way_comparable {

return std::tie(x) <=> std::tie(other.x);

}

};

注意到我们仍然需要使用 std::tie() 以保证对 x 坐标进行比较,而 y 坐标被忽略。这是因为在进行比较时, operator<=> 会先比较两个对象的所有数据成员,然后根据这些比较结果构造出最终的比较结果。因此,我们需要将要忽略的数据成员置于某个条件之下,避免其被比较。

在进行 operator<=> 的重载时,需要保证所有的数据成员都可以进行比较,否则会出现编译错误。当我们想要忽略某些数据成员时,可以使用 std::common_comparison_category_t 将其置于一类之外。例如:

struct Point {

double x;

double y;

auto operator<=>(const Point&) const = default;

auto operator<=>(const Point& other) const requires std::three_way_comparable {

return std::common_comparison_category_t other.x), std::partial_ordering>{}

<=> std::partial_ordering::equal;

}

};

我们使用 std::common_comparison_category_t 将 x 坐标的比较结果与 std::partial_ordering::equal 合并,以获得一个可以与所有其它比较结果进行比较的值。

总结一下,使用 operator<=> 忽略一个数据成员需要将其置于 std::common_comparison_category_t 的一类之外,并在进行比较时使用 std::tie() 或对比较结果进行适当的修改。这个特性可以极大地简化我们的代码,并使得比较操作更加具有可读性与可维护性。

详情参考

了解更多有趣的事情:https://blog.ds3783.com/