聊聊C++20的三向比较运算符 `<=>`

C++20标准引入了许多新特性,其中之一是三向比较运算符 <=>,也被称为太空船运算符。这个新运算符为C++程序员提供了一种全新的比较对象的方式,它能有效简化比较逻辑,避免编写多个比较运算符重载的情况。

为什么需要三向比较运算符?

在C++20之前,如果要完整地定义一个类型的比较行为,你需要重载四个运算符:==!=<>,有时还包括 <=>=。这不仅使得代码冗长,而且增加了出错的可能性,因为需要确保所有这些运算符之间的逻辑一致性是一件不容易的事情。

三向比较运算符引入后,开发者就可以用单一的运算符表达相同的意图。这提高了代码的简洁性和可读性,并有助于减少错误。

三向比较运算符的工作原理

三向比较运算符通过比较两个对象,返回一个表示它们比较结果的值。这个值可以告诉我们两个对象是否相等、一个是否小于另一个,或者一个是否大于另一个。

在C++20中,这个运算符返回的不是简单的整数,而是std::strong_orderingstd::weak_orderingstd::partial_ordering中的一个值,这些都是定义在<compare>头文件中的新类型。

认识新的比较类别

运算符<=>返回的比较类别提供了不同级别的比较保证:

在C++20中引入了三向比较运算符<=>,也称为太空船运算符,它允许在单个操作中进行全面的比较。与这个运算符一起引入的还有几种新的比较类别,分别是std::strong_orderingstd::weak_orderingstd::partial_ordering。这些类别定义了比较的结果类型,并提供了不同的比较保证。

std::strong_ordering

std::strong_ordering是指两个值之间存在强序关系,即可以明确地比较它们的大小。它提供了最强的比较保证,即总是可以确定两个值是相等的、第一个值小于第二个值,还是第一个值大于第二个值。

使用std::strong_ordering的情况下,比较操作符(<=>)将返回std::strong_ordering::equalstd::strong_ordering::lessstd::strong_ordering::greater中的一个,分别代表相等、小于和大于。这允许我们对比较结果进行清晰的布尔测试。

例如,基本数据类型(如整型和浮点型)之间的比较通常使用std::strong_ordering

std::weak_ordering

std::weak_ordering提供了较弱的比较保证,它通常用于那些可以比较等价性,但不能总是完全确定排序关系的场合。例如,在某些情况下,两个不同的对象可能被视为等价的,尽管它们并不完全相等。

std::weak_ordering返回std::weak_ordering::equivalentstd::weak_ordering::lessstd::weak_ordering::greater中的一个。std::weak_ordering::equivalent表示两个值在某种意义上是等价的,不一定意味着它们是相等的,但在排序中可以被视为等价。

例如,当比较忽略大小写的字符串时,两个字符串可能具有weak_ordering,因为在不考虑大小写的情况下,它们可以被视为等价的。

std::partial_ordering

std::partial_ordering是最弱的比较保证,它用于那些可能没有完整排序关系的场合。在这种比较中,一些值可能无法相互比较,比如浮点数中的NaN(Not a Number)值。

std::partial_ordering返回std::partial_ordering::lessstd::partial_ordering::equivalentstd::partial_ordering::greaterstd::partial_ordering::unordered中的一个。std::partial_ordering::unordered表示两个值之间没有可定义的顺序。

例如,浮点数比较可能返回partial_ordering,因为如果任意一个操作数是NaN,那么比较结果就是无序的。

这三种比较类别允许C++程序员更准确地指定他们的类或结构体比较操作的语义和行为。通过在operator<=>的实现中返回适当的比较类别,我们可以为使用我们类型的代码提供清晰的比较语义,增加了代码的可读性和健壮性。这些新特性是C++20标准提供的类型系统增强的一部分,让C++程序更加安全、清晰且易于维护。

使用三向比较运算符

在自己的类中使用三向比较运算符很简单。你可以通过在类内声明一个返回三向比较结果的operator<=>来实现。例如:

#include <compare>

class MyValue {
public:
    int value;

    auto operator<=>(const MyValue&) const = default;
};

在这个例子中,MyValue类默认地定义了三向比较运算符。现在,我们可以使用<=>来比较MyValue的实例,并使用结果进行进一步的比较:

MyValue a{5}, b{10};
auto result = a <=> b;
if (result < 0) {
    // a 小于 b
} else if (result > 0) {
    // a 大于 b
} else {
    // a 等于 b
}

结语

与模块(Modules)、协程(Coroutines)、概念(Concepts)等特性相比,三相比较运算符似乎微不足道,但从这一个小小的三相比较运算符的引入,我们可以看到C++的复杂之处与细心之处,因为周边的配套类型(std::strong_ordering、std::weak_ordering和std::partial_ordering)为比较语言提供了严格复杂的抽象,有助于编写出更清晰、更健壮的代码。通过三相比较运算符,我们也能一窥现代C++的发展趋势,提供了一种更为高效和直观的比较方法,也在语言层面上极大地简化了开发者的工作。

  • 36
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值