Compare

2023-11-19
2分钟阅读时长

Three-way Comparison

三向比较运算符是C++20引入的特性,可用于确定两个值的大小顺序。它返回一个类枚举(enumeration-like)类型,其定义在 <compare>std 名称空间中。

相比原始类型,使用三向比较运算符不会带来太多收益;但是对于比较昂贵的对象来说则很有用。

Strong Ordering

如果操作数是整数类型,则结果是强排序。

  1. strong_ordering::less
  2. strong_ordering::greater
  3. strong_ordering::equal

下面给出了一个操作整数类型的例子。

  int i {11};
  if (std::strong_ordering result { i<=>0 }; result == std::strong_ordering::less) {
      std::cout<<"less"<<"\n"; 
  }
  else if(result == std::strong_ordering::greater){
      std::cout<<"greater"<<"\n"; 
  }
  else {
      std::cout<<"equal"<<"\n";
  }

Partial Ordering

如果操作数是浮点类型,则结果是一个偏序。

  1. partial_ordering::less
  2. partial_ordering::greater
  3. partial_ordering::equivalent
  4. partial_ordering::unordered

下面给出了一个操作浮点数类型的例子。

  #include <cmath>

  float a = std::nan("");
  float b = std::numeric_limits<float>::infinity();
  float c = 3.14;
  if( std::partial_ordering result { a<=>b };
      result == std::partial_ordering::unordered) 
      std::cout << "Error,some number is illegal." << "\n";

Weak Ordering

如果需要针对自己的类型实现三向比较,则选择弱排序。

  1. weak_ordering::less
  2. weak_ordering::greater
  3. weak_ordering::equivalent

下面给出了一个操作类的对象类型的例子。

  module;
  #include <string>

  export module employee;

  export class Employee{
  public:
      std::string name;
      char first_initial;
      char last_initial;
      int employee_number;
      int salary;
      auto operator<=>(const Employee& other) const -> std::weak_ordering;
  };

  auto Employee::operator<=>(const Employee& other) const -> std::weak_ordering{
      // 按照薪水进行比较
      if (salary < other.salary) {
          return std::weak_ordering::less;
      } else if (salary > other.salary) {
          return std::weak_ordering::greater;
      } else {
          return std::weak_ordering::equivalent;
      }
  }

其中:

  1. 一般地,三向比较运算符可以写 auto operator<=>(const Person& other) const = default; 这个默认成员函数
  2. 通过使用 = default ,编译器将使用默认的比较行为来生成该函数的实现。默认比较的逻辑是按照类成员顺序逐个比较,并返回适当的 std::weak_ordering 值。
  3. 在该函数定义中,=const= 关键字表示该成员函数是一个常量成员函数,不修改对象状态。const 关键字必须放在函数参数列表后面,以确保函数签名的一致性。

值得说明的是,如果不指定返回类型,下面的代码将会返回对应数据类型所属的类枚举类型 std::strong_ordering

  auto operator<=>(const Employee& other) const {
      return salary <=> other.salary;
  }
上一页 Modules for CPP