C++20(三路比较运算符)

目录

[一 三路比较运算符](#一 三路比较运算符)

[二 类重载运算符](#二 类重载运算符)

[三 比较类别](#三 比较类别)


一 三路比较运算符

在 C++ 20 之前要求自定义类型支持比较,就要重载 operator < > == != >= <= 这些比较符,而 C++ 20 提供了 <=> 三路比较运算符,又称 宇宙飞船运算符,他同时兼具了上述的所有比较符的逻辑,统一了接口,不必写冗余的代码。

示例:

cpp 复制代码
auto result = 1 <=> 2;
if (result < 0)
{
	std::cout << "<" << std::endl;
}
else if (result > 0)
{
	std::cout << "<" << std::endl;
}
else
{
	std::cout << "<" << std::endl;
}

这里拿内置类型做比较,内置类型天然的满足 <=> 进行比较,结果用 0 判断 和 返回值用 auto 接收这里后面讲。

二 类重载运算符

类重载三路比较运算符,语法:

cpp 复制代码
class Point
{ ... };

auto operator<=>(const Point& rhs)const
{
    ....
}

强制生成生成默认的 <=> :

cpp 复制代码
auto operator<=>(const Point& rhs)const = default;

如果自己写了 <=> 或者强制编译器生成默认的 <=> ,该类就可以使用传统的比较方式了,但 <=> 生成默认的要求所有的成员变量都支持 <=>,并按声明顺序进行比较,既可写成类成员函数也可写成非成员函数。

三 比较类别

前面所讲的比较结果用 auto 接收和用 0 进行比较:

用 auto 接收:<=> 比较后的结果有 3 种类型,并不是返回一个 int 类型。

用 0 判断:这 3 种类型都重载了 operator < > <= >= != 运算符。

3 种比较类别:

strong_ordering:强序比较,严格的比较,如 内置类型比较,string 逐个按字符比较等。

|---------------------------------------------------------|-------------------------------------------------------------------|
| inline constexpr std::strong_ordering less 静态 | 一个有效值,表示小于(排在前面)关系 (public static 成员常量) |
| inline constexpr std::strong_ordering equivalent 静态 | 一个有效值,表示等价(既不排在前面也不排在后面)关系,与 equal 相同 (public static 成员常量) |
| inline constexpr std::strong_ordering equal 静态 | 一个有效值,表示等价(既不排在前面也不排在后面)关系,与 equivalent 相同 (public static 成员常量) |
| inline constexpr std::strong_ordering greater 静态 | 一个有效值,表示大于(排在后面)关系 (public static 成员常量 |

less:小于。

equivallent == equal:严格等于。

greater:大于。

weak_ordering:弱序比较,不严格的比较,如按自己的规则进行比较,string 忽略大小写比较等。

|-------------------------------------------------------|-----------------------------------------------|
| inline constexpr std::weak_ordering less 静态 | 一个有效值,表示小于(排在前面)关系 (public static 成员常量) |
| inline constexpr std::weak_ordering equivalent 静态 | 一个表示等价的有效值(既不排在前面也不排在后面) (public static 成员常量) |
| inline constexpr std::weak_ordering greater 静态 | 一个有效值,表示大于(排在后面)关系 (public static 成员常量) |

less:小于。

equivallent :等价 - 约等于。

greater:大于。

partial_ordering:相交与前 2 个,多了一个不可比较的状态。

|----------------------------------------------------------|-----------------------------------------------|
| inline constexpr std::partial_ordering less 静态 | 一个有效值,表示小于(排在前面)关系 (public static 成员常量) |
| inline constexpr std::partial_ordering equivalent 静态 | 一个表示等价的有效值(既不排在前面也不排在后面) (public static 成员常量) |
| inline constexpr std::partial_ordering greater 静态 | 一个有效值,表示大于(排在后面)关系 (public static 成员常量) |
| inline constexpr std::partial_ordering unordered 静态 | 一个表示与不可比较值之间关系的有效值 (public static 成员常量) |

less:小于。

equivallent :等价 - 约等于。

greater:大于。

unordered:不可比较。

这些静态对象都在这些比较类别里面定义好了,其值在 MSVC 下是 signed char 表示。

cpp 复制代码
using _Compare_t = signed char;

enum class _Compare_eq : _Compare_t { equal = 0, equivalent = equal };
enum class _Compare_ord : _Compare_t { less = -1, greater = 1 };
enum class _Compare_ncmp : _Compare_t { unordered = -128 };

右操作数的比较结果会放到左操作数对象的 _Value 里,当进行 < > != >= <= 会转换成:

cpp 复制代码
void _Literal_zero_is_expected();

struct _Literal_zero {
    template <class _Ty>
        requires is_same_v<_Ty, int>
    consteval _Literal_zero(_Ty _Zero) noexcept {
        // Can't use _STL_VERIFY because this is a core header
        if (_Zero != 0) {
            _Literal_zero_is_expected();
        }
    }
};

_NODISCARD friend constexpr bool operator<(const strong_ordering _Val,
                                           _Literal_zero) noexcept 
{
    return _Val._Value < 0;
}

如果没有传 int 则会被 _Literal_zero 里的 requries 约束限制,is_same_v 作为构造的参数进行限制类型必须和 int 先等,consteval 立即函数里必须等于 0 ,否则调用只有声明没有定义的函数。

当然除了上述的常规的运算符比较,也可以写成:

cpp 复制代码
std::strong_ordering s1 = 1 <=> 1;
if (s1 == std::strong_ordering::equal)
{
	std::cout << "==" << std::endl;
}
else if (s1 == std::strong_ordering::less)
{
    std::cout << "<" << std::endl;
}
else
{
    std::cout << ">" << std::endl;
}


_NODISCARD friend constexpr bool operator==(strong_ordering, 
                            strong_ordering) noexcept = default;

这里直接让编译器强制生成并比较里面的有符号 _Value 对象。

相关推荐
Lucis__1 天前
C++20概念约束—现代C++模板约束的演进与重构
c++20·程序·κzy
SunkingYang11 天前
C++20 vs C++17:新特性对比与用法指南
c++·c++20·特性·版本·新特性·对比·c++17
前进吧-程序员11 天前
C++20 协程入门实战:从 co_await 到一个 100 行的异步任务调度器
网络·c++·c++20
前进吧-程序员11 天前
实战:C++20 协程 + io_uring 写一个 400 行的 echo server
网络·c++·c++20
骑着蜗牛撵大象32712 天前
C++20 协程 × 屏障:手写一个 co_await 版 Barrier,让等待不再钉死线程
android·c++20·协程·并发编程·co_await·屏障同步
闻缺陷则喜何志丹13 天前
【c++20】协程与屏障
c++·算法·c++20·携程·屏障
努力努力再努力wz14 天前
【C++高阶系列】C++20 协程底层原理:函数为什么能暂停?从状态机到 Task,彻底串起挂起、恢复与协程调度
开发语言·c++·c++20·1024程序员节
fpcc25 天前
c++20新功能—std::osyncstream
c++·c++20
啦啦啦啦啦zzzz1 个月前
一致性哈希
服务器·算法·哈希算法·c++20·分布式存储
keep intensify1 个月前
C++20线程池
c++·算法·c++20