跳转至

三路比较运算符<=>

  • 作用:三路比较可以看做== 、 != 、 < 、 <= 、 > 、 >=的集合,实现一个三路比较运算符可以替代其它六个比较运算

1 三路比较的使用

  1. 三路比较返回值有三种
  2. partial_ordering
  3. strong_ordering
  4. weak_ordering
  5. 三路比较结果只能与 0、NULL 和 nullptr 做比较
  6. 示例
#include<compare>
int main(){
  auto comp=1 <=> 2;
  comp<NULL;
  comp<0;
  comp<nullptr;
}

2 重写三路比较运算符

在类中,可以指示编译器默认生成,也可以由用户定义

2.1 默认三路比较

要使用默认的三路比较,只需要假设 =default,编译器会安装类成员出现顺序依次去做三路比较

#include<compare>
class Point {
    int y;
    int x;
public:
    Point() :x(0), y(0) {}
    Point(int x,int y):x(x),y(y){}
    auto operator<=>(const Point&) const = default;
};

因此类中成员顺序会影响到最终比较结果

#include <iostream>
#include<compare>
#include<set>
class Point1 {
    int y;
    int x;
public:
    Point() :x(0), y(0) {}
    Point(int x,int y):x(x),y(y){}
    auto operator<=>(const Point&) const = default;
};
class Point2 {
    int x;
    int y;
public:
    Point() :x(0), y(0) {}
    Point(int x,int y):x(x),y(y){}
    auto operator<=>(const Point&) const = default;
};
int main() {
    Point1 pt1(1,2), pt2(2,1);
    //因为y在x前声明,首先比较y,pt1.y>pt2.y,所以是false
    if (pt1 < pt2)
    {
        std::cout << "true";
    }
    else {
        std::cout << "false" << std::endl;
    }
    Point2 pt3(1,2), pt4(2,1);
    //因为x在y前声明,首先比较x,pt3.x<pt4.x,所以是true
    if (pt3 < pt4)
    {
        std::cout << "true";
    }
    else {
        std::cout << "false" << std::endl;
    }
}

2.2 自定义三路比较

自定义三路比较需要遍历所有成员,且父类也需要比较

class TotallyOrdered : Base {
 string tax_id;
 string first_name;
 string last_name;
public:
 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;
 }
 // ... non-comparison functions ...
};