在 C++20 之前的 C++ 中,有没有更好的方法来定义关系运算符?

Is there any better way to define relational operators in C++ pre C++20?

这样的代码对我来说写起来很乏味
class date {
private: 
    int day, year, month;
    int comp(const date & Other) const;
public:
    date(int D, int Y, int M) : day (D), year (Y), month (M)  {}

    friend bool operator==(const date & L, const date & R) { return L.comp(R) == 0 ; }
    friend bool operator!=(const date & L, const date & R) { return L.comp(R) != 0 ; }
    friend bool operator> (const date & L, const date & R) { return L.comp(R) > 0 ; }
    friend bool operator>=(const date & L, const date & R) { return L.comp(R) >= 0 ; }
    friend bool operator< (const date & L, const date & R) { return L.comp(R) < 0 ; }
    friend bool operator<=(const date & L, const date & R) { return L.comp(R) <= 0 ; }
}

所有关系运算符都是样板文件(每个需要它们的 class 都一样)。 肯定 有更好的方法来完成这一切。我知道 C++ 20 提供了宇宙飞船运算符,但我没有。所以我的问题是:如何避免使用早于 C++ 20 的功能的样板代码?

你可以使用Boost.Operators(或自己实现这样的东西),但你仍然必须编写两个函数:

class date : public totally_ordered<date> {
private: 
    int day, year, month;
    int comp(const date & Other) ;
public:
    date(int D, int Y, int M) : day (D), year (Y), month (M)  {}

    friend bool operator==(const date & L, const date & R) { return L.comp(R) == 0 ; }
    friend bool operator< (const date & L, const date & R) { return L.comp(R) < 0 ; }
}

请注意,您通常不想根据三向排序使用定义 == 的模式,因为 == 通常效率更高(例如,考虑这种情况您知道不同大小的字符串立即不相等的字符串,但您不知道 compare() 的结果是什么,而不实际比较任意多的字符)。

另请注意,此方法的一个普遍问题是决定将 x <= y 定义为 !(y < x) 还是 x < y || x == y。大多数图书馆解决方案选择前者(更少的比较),尽管这在部分订单上给出了错误的答案——这是 <=> 开始的部分动机。 Boost.Operators 通过也有一个 partially_ordered<T> 来解决这个问题,它根据两个操作正确定义 <=


There must surely be a better way to do all this.

正如 所说,这就是我们添加 <=>:

的原因
class date {
private: 
    int year, month, day; // NB: I reordered these
public:
    friend auto operator<=>(const date&, const date&) = default;
};