C++20中的三向比较运算符(three-way comparison operator)

      在C++20中,引入了一个新的特性,即"三向比较运算符(three-way comparison operator)",由于其外观,也被称为"宇宙飞船运算符(spaceship operator)",其符号为<=>。目的是简化比较对象的过程。这个运算符允许用户定义的对象之间进行全序比较,返回一个表示比较结果的枚举值,这个枚举值可以被用来决定两个对象是否相等、小于或大于另一个对象。使用<=>,需include头文件<compare>。

      当你为自定义类型定义<=>运算符时,编译器会自动为你生成==、<、>这三个比较运算符的默认实现。这大大减少了编写比较逻辑的工作量,并提高了代码的可读性和可维护性。

      <=>运算符确定两个对象A和B是A<B、A=B还是A>B:

      (1).<=>运算符是其它比较运算符的通用泛化(common generalization):>、==、<。使用<=>,在用户定义数据类型(如struct)的情况下,每个操作都可以以完全通用的方式实现;若不使用<=>,则必须逐一定义每个比较运算符。

      (2).对于字符串,它相当于C标准库中的std::strcmp函数。

      <=>运算符三种可能的结果类型支持所有六种关系运算符(==, !=, <, <=, >, >=)

      (1).类std::strong_ordering:有4种有效值:less、equal、equivalent、greater。

      (2).类std::weak_ordering:有3种有效值:less、equivalent、greater。

      (3).类std::partial_ordering:有4种有效值:less、equivalent、greater、unordered。

      注意:

      (1).试图将std::strong_ordering、std::weak_ordering、std::partial_ordering与整数字面值常量(integer literal)0以外的任何值进行比较的程序的行为是未定义的

      (2).std::strong_ordering可以隐式转换(implicitly-convertible)为std::weak_ordering;std::weak_ordering可以隐式转换为std::partial_ordering。

      以下为测试代码:

namespace {

template<typename T>
void compare(T x, T y)
{
    auto ret = x <=> y;
    std::cout << "name: " << typeid(ret).name() << std::endl;
    if (ret < 0)
        std::cout << "x < y:" << x << "," << y << std::endl;
    else if (ret == 0)
        std::cout << "x == y:" << x << "," << y << std::endl;
    else
        std::cout << "x > y:" << x << "," << y << std::endl;
}

struct Person {
    std::string name_{""};
    int age_{0};

    auto operator<=>(const Person& other) const noexcept
    {
        if (age_ != other.age_)
            return age_ <=> other.age_;
        
        if (name_ != other.name_)
            return name_ <=> other.name_;

        if (age_ == other.age_ && name_ == other.name_) {
            //return name_ <=> other.name_;
            return std::strong_ordering::equal;
        }
    }
};

} // namespace

int test_comparison_three_way()
{
    // numerical comparison
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dist(0, 1000);

    auto x = dist(gen);
    auto y = dist(gen);
    compare(x, y);
    compare(y, x);
    compare(5, 5);

    // vector comparison
    const std::vector<int> a{ 1,2,3 }, b{ 1,2,4 };
    auto ret = a <=> b;
    if (ret < 0)
        std::cout << "a < b" << std::endl;
    else if (ret == 0)
        std::cout << "a == b" << std::endl;
    else
        std::cout << "a > b" << std::endl;

    // std::string comparison
    const std::string str1{ "Hello" }, str2{ "hello" };
    compare(str1, str2);
    compare(str2, str1);
    compare(std::string("hello"), std::string("hello"));

    // struct/class comparison
    const Person tom{ "Tom", 20 }, lisy{ "Lisy", 21 }, bob{ "Bob", 20 };

    ret = tom <=> bob;
    if (ret > 0) std::cout << "tom > bob" << std::endl;
    if (ret >= 0) std::cout << "tom >= bob" << std::endl;
    if (ret != 0) std::cout << "tom != bob" << std::endl;

    ret = tom <=> lisy;
    if (ret < 0) std::cout << "tom < lisy" << std::endl;
    if (ret <= 0) std::cout << "tom <= lisy" << std::endl;
    if (ret != 0) std::cout << "tom != lisy" << std::endl;
    if (ret == 0) std::cout << "tom == lisy" << std::endl;

    ret = tom <=> tom;
    if (ret == 0) std::cout << "tom == tom" << std::endl;

	return 0;
}

      执行结果如下图所示:

      C++20中的默认比较运算符函数(defaulted comparison operator function):可以显式请求编译器为类生成相应的默认比较

      类C的默认比较运算符函数是满足以下所有条件的非模板比较运算符函数(即<=>、==、!=、<、>、<=或>=):

      (1).它是某个类C的非静态成员或友元。

      (2).它在C中或在C完整的上下文中被定义为默认值。

      (3).它有两个const C&类型的参数或两个C类型的参数,其中隐式对象参数(如果有)被视为第一个参数。

      给定类C,默认比较顺序:按声明顺序排列

      (1).类C的直接基类子对象,按声明顺序排列。

      (2).类C的非静态数据成员,按声明顺序排列。如果任何成员子对象是数组类型,则按下标递增的顺序将其扩展为其元素的序列。扩展是递归的:数组类型的数组元素将再次扩展,直到没有数组类型的子对象为止。

      以下为测试代码:

namespace {

struct Person2 {
    // 注意: age_和name_定义的顺序不同,会产生不同的比较结果
    int age_{ 0 };
    std::string name_{ "" };
    //int age_{ 0 };

    auto operator<=>(const Person2&) const = default;
    //bool operator==(const Person2&) const = default;
};

} // namespace

int test_comparison_default()
{
    const Person2 tom{ 20, "Tom" }, lisy{ 21, "Lisy" }, bob{ 20, "Bob" };

    auto ret = tom <=> bob;
    if (ret > 0) std::cout << "tom > bob" << std::endl;
    if (ret >= 0) std::cout << "tom >= bob" << std::endl;
    if (ret != 0) std::cout << "tom != bob" << std::endl;

    ret = tom <=> lisy;
    if (ret < 0) std::cout << "tom < lisy" << std::endl;
    if (ret <= 0) std::cout << "tom <= lisy" << std::endl;
    if (ret != 0) std::cout << "tom != lisy" << std::endl;
    if (ret == 0) std::cout << "tom == lisy" << std::endl;

    ret = tom <=> tom;
    if (ret == 0) std::cout << "tom == tom" << std::endl;

    if (tom == tom) std::cout << "tom == tom" << std::endl;
    if (tom > bob) std::cout << "tom > bob" << std::endl;
    if (tom >= bob) std::cout << "tom >= bob" << std::endl;
    if (tom != lisy) std::cout << "tom != lisy" << std::endl;
    if (tom < lisy) std::cout << "tom < lisy" << std::endl;
    if (tom <= lisy) std::cout << "tom <= lisy" << std::endl;

    return 0;
}

      执行结果如下图所示:

      GitHub:https://github.com/fengbingchun/Messy_Test

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/760832.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

八爪鱼现金流-032,给用户发邮件提示功能

每个月的 5 号、15 号、25 号的 17:30 工资日&#xff0c;给用户发送邮件&#xff0c;提示记账月报。 您也来记账一笔吧。 然后首页能看到趋势图。 八爪鱼现金流 八爪鱼

使用Petalinux设计linux系统

文章目录 1.通过 Vivado 创建硬件平台&#xff0c;得到 hdf 硬件描述文件2.设置 Petalinux 环境变量3.创建 Petalinux 工程4.配置Petalinux 工程5.配置Linux内核6.配置Linux根文件系统7.配置设备树文件8.编译 Petalinux 工程9.制作BOOT.BIN启动文件10.制作SD启动卡 1.通过 Viva…

智能旅行规划的未来:大模型与形式化验证的融合

我们在做旅行规划时面对众多的目的地选择、复杂的交通连接、预算限制以及个人偏好等多重因素&#xff0c;即使是最有经验的旅行者也可能会陷入选择困境。传统的旅行规划方法往往依赖于人工操作&#xff0c;这不仅耗时耗力&#xff0c;而且难以保证计划的最优性和可执行性。 本…

C++学习笔记---POCO库

在Windows系统中安装POCO 1&#xff09;安装OpenSSL POCO编译安装依赖OpenSSL&#xff0c;如果未安装OpenSSL则应该先安装OpenSSL。 假设将OpenSSL安装在C:\OpenSSL-Win64&#xff0c;将C:\OpenSSL-Win64、C:\OpenSSL-Win64\lib添加到PATH环境变量中2&#xff09;安装POCO 将p…

Java代码生成器(开源版本)

一、在线地址 Java在线代码生成器&#xff1a;在线访问 二、页面截图 三、核心功能 支持Mybatis、MybatisPlus、Jpa代码生成使用 antlr4 解析SQL语句&#xff0c;保证了SQL解析的成功率支持自定义包名、作者名信息支持自定义方法名、接口地址支持自定义选择是否生成某个方法…

前端面试题(基础篇十四)

一、DOMContentLoaded 事件和 Load 事件的区别&#xff1f; 当初始的 HTML 文档被完全加载和解析完成之后&#xff0c;DOMContentLoaded 事件被触发&#xff0c;而无需等待样式表、图像和子框架的加载完成。 Load 事件是当所有资源加载完成后触发的。 二、简述一下你对 HTML 语…

解析桥式整流电路

下面这个桥式整流电路出场率很高&#xff0c;看着一定眼熟。 事实证明&#xff0c;强行灌输的东西总是难以下咽。记得读书那会&#xff0c;第一次看到这个电路时被吓到了&#xff0c;以至于直到这门课结束了也没搞清楚。 本文就来分析一下此电路中电流的走向&#xff0c;进而理…

【初阶数据结构】深入解析队列:探索底层逻辑

&#x1f525;引言 本篇将深入解析队列:探索底层逻辑&#xff0c;理解底层是如何实现并了解该接口实现的优缺点&#xff0c;以便于我们在编写程序灵活地使用该数据结构。 &#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#…

Android经典面试题之Glide的缓存大揭秘

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 Glide缓存 关联类&#xff1a;Engine、LruResourceCache、LruCache、ActiveResources ActiveResources&#xff1a;弱引用缓存池 VisibleForTe…

Chapter8 透明效果——Shader入门精要学习笔记

一、基本概念 在Unity中通常使用两种方法来实现透明效果 透明度测试&#xff08;无法达到真正的半透明效果&#xff09;透明度混合&#xff08;关闭了深度写入&#xff09; 透明度测试 基本原理&#xff1a;设置一个阈值&#xff0c;只要片元的透明度小于阈值&#xff0c;就…

VMware--创建Ubuntu虚拟机

原文网址&#xff1a;VMware--创建Ubuntu虚拟机-CSDN博客 简介 本文介绍VMware创建Ubuntu虚拟机的方法。 VMware是最好用的虚拟机软件&#xff0c;安装方法见&#xff1a; 本文安装当前最新的Ubuntu的LTS镜像&#xff1a;ubuntu2022.04.4LTS。 1.下载Ubuntu镜像 下载地址…

电脑技巧:告别卡顿,迎接流畅——Wintune系统优化软件功能详解

目录 一、Wintune介绍 二、Wintune核心功能介绍 2.1 系统优化 2.2 隐私功能 2.3 文件管理模块 2.4 可选选项 2.5 UWP app服务 2.6 startup Manager 2.7、主机编辑 三、总结 电脑是大家目前日常办公娱乐必不可小的工具&#xff0c;软件市场上的系统优化软件层出不穷&a…

一二三应用开发平台应用开发示例(5)——列表视图、树视图、树表视图、树参照视图配置

列表视图 接下来进入列表视图配置&#xff0c;创建的操作方式跟前面相同&#xff0c;如下图所示&#xff1a; 保存后回到列表&#xff0c;点击行记录的配置按钮&#xff0c;进入如下配置页面 可以看到该配置界面相比新增、修改、查看那三个视图要复杂得多&#xff0c;配置项…

帕金森患者的福音,这些食物竟有神奇疗效!

在忙碌的现代生活中&#xff0c;健康问题越来越受到大家的关注。而帕金森病作为一种常见的老年神经系统疾病&#xff0c;更是让许多患者和家庭倍感压力。但是&#xff0c;你知道吗&#xff1f;除了药物治疗和手术干预&#xff0c;日常饮食也能对帕金森病产生积极的影响。今天&a…

开源分享:一套完整的直播购物系统源码

直播购物已经成为一种炙手可热的电商模式&#xff0c;吸引了无数商家和消费者的目光。对于开发者来说&#xff0c;构建一个功能齐全、用户体验优良的直播购物系统是一项复杂的任务。本文将分享一套完整的直播购物系统源码&#xff0c;帮助开发者快速搭建自己的直播购物平台。 …

基于springboot+vue+uniapp的语言课学习系统小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

在Centos上安装Lua不要用什么curl指令,这样获取到的压缩包不是gzip格式的

Lua 环境安装 | 菜鸟教程 (runoob.com) 在这一篇里&#xff0c;把这一行 换成 wget http://www.lua.org/ftp/lua-5.3.0.tar.gz 再去解压编译安装就对了。

ue5导航网格设置

AI使用导航网格进行移动&#xff0c;所以&#xff0c;先设置导航网格边界体积 2&#xff0c;使导航网格边界体积覆盖AI所需要的场景&#xff08;绿色区域&#xff09;&#xff0c;x,y&#xff0c;z在这里都扩大到原来的10倍 3&#xff0c;打开actor的“启用tick并开始” 4&…

No module named ‘MySQLdb‘

python 运行代码的时候遇到No module named ‘MySQLdb’报错如何解决&#xff1f; 解决办法 如果没有安装可以先安装以下依赖库 pip install PyMySQL如果已经安装了PyMySQL&#xff0c;仍然报MySQLdb模块找不到&#xff0c;可以尝试安装以下依赖库。 pip install mysqlclient

二轴机器人装箱机:重塑物流效率,精准灵活,引领未来装箱新潮流

在现代化物流领域&#xff0c;高效、精准与灵活性无疑是各大企业追求的核心目标。而在这个日益追求自动化的时代&#xff0c;二轴机器人装箱机凭借其较佳的性能和出色的表现&#xff0c;正逐渐成为装箱作业的得力助手&#xff0c;引领着未来装箱新潮流。 一、高效&#xff1a;重…