三路比较运算符也是一个c++20新提供的一个功能,网上有的人叫“航天飞机运算符”也有的叫“宇宙飞船运算符”,知道啥意思就行。在以前的c++编程中,实现基本类型的比较功能是由标准语法直接提供的,但在实际的编程中,经常会遇到这样一些问题,封装好的对象(类和结构体对象)也会出现一些比较的要求,这时候儿,一般会通过重载某个运算符来实现特定的对象的比较。而在c++20中提供的这个三路比较运算符,会默认生成一系列的比较运算符,如果默认生成的语义不符合自己的标准,那么可以自定义其并由编译器重新生成符合预期的重载运算语义。生成的默认运算符有六个即:==,!=,<,>,<=,>=。基本的操作如下:
auto operator<=>(const Point&) const = default;
自定义时有三种可用的返回类型:
std::strong_ordering:强比较,严格按照比较的顺序、方式来进行,不能从下面两个转回,特别注意的是它不区分等价值。
std::weak_ordering:弱比较,对比较的大小写,可以对等价的字符串用某种方式区别
std::partial_ordering:偏序比较,其实就是自定义,把直观上不可能比较的对象通过某种方式来进行比较。
更详尽的细节可以看一下官网:
https://zh.cppreference.com/w/cpp/utility
https://zh.cppreference.com/w/cpp/language/default_comparisons
看一下官网修改的例子:
#include
#include
class Point
{
int x = 0;
int y = 0;
public:
void SetData(int x, int y) { this->x = x; this->y = y; };
auto operator<=>(const Point&) const = default;
// ……非比较函数……
};
void TestThreeOprator()
{
// 编译器生成全部四个关系运算符
Point pt1, pt2;
pt1.SetData(0,1);
std::set s; // OK
s.insert(pt1); // OK
if (pt1 <= pt2)
{
/*...*/
std::cout<< "is ok!" << std::endl;
}
else
{
std::cout << "is err!" << std::endl;
}
// OK,只调用一次 <=>
}
再看一个自定义的例子:
class Base {
public:
auto operator<=>(const Base&) const = default;
};
std::strong_ordering operator <=>(const std::string& a, const std::string& b) {
int cmp = a.compare(b);
if (cmp < 0) return std::strong_ordering::less;
else if (cmp > 0) return std::strong_ordering::greater;
else return std::strong_ordering::equivalent;
}
class TotallyOrdered : Base {
std::string tax_id;
std::string first_name;
std::string last_name;
public:
TotallyOrdered(const std::string& id, const std::string& first, const std::string& last)
:tax_id(id), first_name(first), last_name(last) {}
// 定制 operator<=>,因为我们想先比较姓
std::strong_ordering operator<=>(const TotallyOrdered& that) const {
if (auto cmp = (Base&)(*this) <=> (Base&)that; cmp != 0) return cmp;
if (auto cmp = last_name <=> that.last_name; cmp != 0) return cmp;
if (auto cmp = first_name <=> that.first_name; cmp != 0) return cmp;
return tax_id <=> that.tax_id;
}
// ……非比较函数……
};
void test_compare02() {
// 编译器生成全部四个关系运算符
TotallyOrdered to1{ "8", "marding", "taid" }, to2{ "2", "zhuli", "lomb" };
std::set s; // ok
s.insert(to1); // ok
s.insert(to2);
if (to1 <= to2) {
std::cout << "is ok"<
再看一个弱比较的例子:
#include
#include
struct Rational_2 {
int num;
int den; // > 0
};
constexpr std::weak_ordering operator<=>(Rational_2 lhs, Rational_2 rhs)
{
return lhs.num * rhs.den <=> rhs.num * lhs.den;
}
void print(std::weak_ordering value)
{
if (value == 0)
std::cout << "equal\n";
else if (value < 0)
std::cout << "less\n";
else
std::cout << "greater\n";
}
int main()
{
Rational_2 c{6,5};
Rational_2 d{8,7};
print(c <=> d);
print(std::compare_three_way{}(c,d));
}
这个资料在官网还是微软的网站还是在相关的网络上都有大量的资料,这里特别细节的就请大家去看上面的两个网站,内部的跳转会提供更多的细节的代码和说明。
c++20表明c++的标准委员会的人确实没闲着,在进步,但网上对c++20的诟病也是不少,大老外们对它的效率提出了一个又一个质疑,有质疑是好事儿,互相促进,互相提高。如果没人质疑,反倒是说明c++要凉了。