RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1364882
Accepted
Mikhailo
Mikhailo
Asked:2022-05-22 23:36:23 +0000 UTC2022-05-22 23:36:23 +0000 UTC 2022-05-22 23:36:23 +0000 UTC

关于火箭操作 <=>

  • 772

问题是如何乘坐火箭起飞:)

我说的是运营商<=>。起初在我看来,这将是一些简单的事情,比如strcmp- 返回小于、大于或等于。

第一个令人失望的是,它们会返回某种“左”类型,您甚至不会直接在if. 我决定我真的不需要他,他太奇怪了。

但是最近我遇到了一个注释,如果你只为你的类型定义它,那么你不需要编写一个比较运算符。例如,我开始寻找并阅读有关他的信息-但很明显他喝了一点:(没有添加清晰度。

如果我理解正确,有人可以帮助我理解通过定义一个运算符<=>,我会自动获得所有关系运算符吗?

以及如何正确定义它?

作为奖励:) - 为什么这么复杂?不只是,比如说,返回-1、0、+1?

好吧,或者告诉我在哪里有关于这个主题的一些咀嚼材料,最好是俄语。

c++
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    HolyBlackCat
    2022-05-23T06:09:46Z2022-05-23T06:09:46Z

    <=>通常不需要手动呼叫。但如果你真的想要,那么它的结果可以与零进行比较,大致类似于 的结果strcmp。示例:(a <=> b) < 0表示a < b(括号可以省略)。关于它的返回类型如下。

    如果你<=>通过编写重载= default,那么所有 6 个运算符都会自动工作:==, !=, <, <=, >, >=. 将比较所有字段。

    = default您只能在类主体中重载 with 。选择:

    auto operator<=>(const MyClass &) const = default;
    
    friend auto operator<=>(const MyClass &, const MyClass &) = default;
    

    如果手动超载<=>,则只有 4 个可以工作:<, <=, >, >=. 您==需要单独重新加载,然后它!=会自动开始工作(不管<=>)。

    without= default可以在类内部和外部重载。

    最简单的方法是作弊,这样写:

    friend auto operator<=>(const MyClass &a, const MyClass &b)
    {
        return std::tie(a.x, a.y, a.z) <=> std::tie(b.x, b.y, b.z);
    };
    
    friend bool operator==(const MyClass &a, const MyClass &b)
    {
        return std::tie(a.x, a.y, a.z) == std::tie(b.x, b.y, b.z);
    };
    

    并且最好以tie不写4次的方法取出。

    重要的是不要屈服于诱惑而没有operator==实现a <=> b == 0。一般来说,这会比使用==. (例如,要通过 比较两个字符串<=>,需要遍历字符。或者==您可以先比较大小,如果它们不同,则不执行其他操作。)

    operator==在 C++20 中,您还可以重载为= default. 它将比较所有字段是否相等,a <=> b == 0即使您重载了也不会使用<=>。

    如果你想<=>手写而不用tie,那么你需要选择返回类型。在下一个答案中,他们建议int,它甚至似乎有效,但不知何故令人怀疑。有三个标准类可供选择,它们的行为大致类似于枚举:

    • std::strong_ordering- 更大/更少/等于

    • std::weak_ordering- 大于/小于/等价 - 基本相同,但表示不同的对象可以被认为是等价的。一个例子是不区分大小写的字符串比较。

    • std::partial_ordering- 大于/小于/等价/不可比较 - 与 相同weak_ordering,但添加了第四个值“不可比较”,这会导致所有 6 个运算符返回 false。示例:NaN与任何其他数字“无法比较”,对其自身也是如此。

    所有三个都可以与零进行比较:x < 0均值x == ...::less等。

    还有<compare>各种方便编写的小工具<=>,例如std::common_comparison_category,它为被比较的对象类型选择适当的返回类型。


    <=>可用于比较不同类型的对象。显然= default,在这种情况下它不会有帮助。

    编译器知道操作数的顺序并不重要,所以重载就足够了A <=> B,B <=> A它会自己工作,所有 4 个运算符也可以处理任何参数的顺序。

    同样,如果您重载A == B,它将B == A自行工作,并且也!=可以使用任何顺序的参数。


    详细信息:实际上没有其他语句生成<=>. ==相反,当您尝试调用另一个运算符时,编译器会将其替换为 call <=>or ==,可能会更改参数的顺序。

    不同之处在于,例如,您不能获取这样一个不存在的运算符 (a la &MyClass::operator<) 的地址,并且可能还有其他东西。

    • 7
  2. Harry
    2022-05-23T02:59:48Z2022-05-23T02:59:48Z

    作为一个实际的人:),我将给出一个重新定义运算符的实际示例。

    如果您对按字段进行比较(例如在元组中)感兴趣,那么在类中(为了确定性Test)编写就足够了

    auto operator<=>(const Test& t) const = default;
    

    如果你想要一些奇怪的东西,那么你需要定义这个 operator 和 operator ==。

    例如,这是这样一个类和比较,其中偶数小于奇数。

    class Test {
    public:
        Test(int x):val_(x){}
    
        auto operator<=>(const Test& t) const
        {
            // Четные меньше нечетных
            if (val_%2 < t.val_%2) return -1;
            else if (val_%2 > t.val_%2) return -1;
            else if (val_ < t.val_) return -1;
            else if (val_ > t.val_) return 1;
            else return 0;
        }
    
        auto operator==(const Test& t) const { return (*this <=> t) == 0; }
    
        int val_ = 0;
    };
    
    int main(int argc, char * argv[])
    {
        Test a(8), b(7);
    
    #define  OUT(a,b) \
        cout << a.val_ << "  <   " << b.val_ << " = " << (a <  b) << endl; \
        cout << a.val_ << "  <=  " << b.val_ << " = " << (a <= b) << endl; \
        cout << a.val_ << "  >   " << b.val_ << " = " << (a >  b) << endl; \
        cout << a.val_ << "  >=  " << b.val_ << " = " << (a >= b) << endl; \
        cout << a.val_ << "  ==  " << b.val_ << " = " << (a == b) << endl; \
        cout << a.val_ << "  !=  " << b.val_ << " = " << (a != b) << endl;
    
        OUT(a,b);
    
        a = 7;
    
        OUT(a,b);
    
        b = 9;
    
        OUT(a,b);
    
    }
    

    在 VC++2019 输出中

    8  <   7 = 1
    8  <=  7 = 1
    8  >   7 = 0
    8  >=  7 = 0
    8  ==  7 = 0
    8  !=  7 = 1
    7  <   7 = 0
    7  <=  7 = 1
    7  >   7 = 0
    7  >=  7 = 1
    7  ==  7 = 1
    7  !=  7 = 0
    7  <   9 = 1
    7  <=  9 = 1
    7  >   9 = 0
    7  >=  9 = 0
    7  ==  9 = 0
    7  !=  9 = 1
    

    好吧,你可以在程序中使用火箭,例如,像这样:

    if (auto cmp = (a<=>b); cmp < 0)
        cout << "less";
    else if (cmp > 0)
        cout << "more";
    else
        cout << "equal";
    

    PS 同时,没有人打扰您定义自己的关系运算符,在这种情况下,当然会使用它们,而不是生成的。

    PPS 编程是一门实验科学 :),所以请尝试深入研究代码...

    • 3

相关问题

  • 编译器和模板处理

  • 指针。找到最小数量

  • C++,关于枚举类对象初始化的问题

  • 函数中的二维数组

  • 无法使用默认构造函数创建类对象

  • C++ 和循环依赖

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5