在 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;
};
像
这样的代码对我来说写起来很乏味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;
};