C++ 语言特性22 - 三向比较
一:概述
C++20 引入了“三向比较运算符”(<=>),也称为“spaceship 运算符”,用来简化比较操作。这个运算符可以同时处理小于、大于和等于的比较,提供一个统一的接口来完成各种比较操作。
1. 基本语法
auto result = lhs <=> rhs;/*
如果 lhs 小于 rhs,则返回负值(如 std::strong_ordering::less)。
如果 lhs 等于 rhs,则返回零值(如 std::strong_ordering::equal)。
如果 lhs 大于 rhs,则返回正值(如 std::strong_ordering::greater)
*/
2. 返回结果
三向比较运算符 <=>
生成一个比较结果对象,可以是以下三种类型之一:
std::strong_ordering
std::weak_ordering
std::partial_ordering
它将比较结果封装为一个状态,可以是小于、等于或大于,简化了需要手动编写的多个比较运算符的实现。
3. 三种返回结果类型的比较
-
std::strong_ordering
- 强排序,严格遵循“弱序关系”,即如果
a == b
,那么它们在其他比较中也应视为相等。 - 默认适用于大多数内置类型,如
int
、double
等。
- 强排序,严格遵循“弱序关系”,即如果
#include <compare>
#include <iostream>struct Point {int x, y;// 使用强排序std::strong_ordering operator<=>(const Point&) const = default;
};int main() {Point p1{1, 2};Point p2{1, 2};if (p1 == p2) {std::cout << "p1 is equal to p2\n";}
}
-
std::weak_ordering
- 弱排序允许某些比较操作认为相等,但不一定意味着所有方面都相等。
- 例如,浮点数中的
-0.0
和0.0
被认为是相等的,尽管它们的二进制表示不同。
#include <compare>
#include <iostream>struct WeakFloat {float value;std::weak_ordering operator<=>(const WeakFloat& other) const {if (value == other.value) {return std::weak_ordering::equivalent; // 等价但不完全相等}return value <=> other.value;}
};int main() {WeakFloat f1{0.0f};WeakFloat f2{-0.0f};if (f1 == f2) {std::cout << "f1 is equivalent to f2\n";}
}
-
std::partial_ordering
- 部分排序适用于无法定义严格顺序的情况,比如浮点数中的 NaN 值(非数字),NaN 与任何数比较的结果都是无序的。
#include <compare>
#include <iostream>
#include <cmath> // 为了使用 std::isnanstruct PartialFloat {float value;std::partial_ordering operator<=>(const PartialFloat& other) const {if (std::isnan(value) || std::isnan(other.value)) {return std::partial_ordering::unordered; // 无法比较}return value <=> other.value;}
};int main() {PartialFloat f1{NAN};PartialFloat f2{1.0};if ((f1 <=> f2) == std::partial_ordering::unordered) {std::cout << "f1 and f2 are unordered\n";}
}
二:三向比较与布尔值
三向比较运算符的返回值可以用于布尔逻辑中,配合 ==
, !=
, <
, <=
, >
, >=
使用。C++20 自动为你定义这些运算符,具体实现的逻辑依赖于三向比较的返回类型。
#include <compare>
#include <iostream>int main() {int a = 5, b = 10;// 使用三向比较运算符的结果进行布尔判断if ((a <=> b) < 0) {std::cout << "a is less than b\n";}
}//在这个示例中,a <=> b 的结果为 std::strong_ordering::less,因此条件 (a <=> b) < 0 为真,表示 a < b。
三:自定义三向比较
虽然 default
的三向比较运算符适合大多数情况,但你也可以自定义它来实现复杂的比较逻辑。
#include <compare>
#include <iostream>class Point {
public:int x, y;// 自定义三向比较运算符std::strong_ordering operator<=>(const Point& other) const {if (auto cmp = x <=> other.x; cmp != 0) {return cmp;}return y <=> other.y;}
};int main() {Point p1{1, 2};Point p2{1, 3};if (p1 < p2) std::cout << "p1 is less than p2\n";if (p1 == p2) std::cout << "p1 is equal to p2\n";if (p1 > p2) std::cout << "p1 is greater than p2\n";
}