为什么默认的三向运算符 (spaceship <=>) 生成相等运算符 (==) 而用户定义的三向运算符不生成? [英] Why default three-way operator (spaceship &lt;=&gt;) generates equality operator (==) and user define three-way operator not?

查看:54
本文介绍了为什么默认的三向运算符 (spaceship <=>) 生成相等运算符 (==) 而用户定义的三向运算符不生成?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑这个代码:

#include <iostream>
#include <compare>

class A {
public:
  int i = {};

  std::strong_ordering operator<=> (A const& r) const
  {
    return i <=> r.i;
  }
};

void TestA()
{
    A a;
    A b;

    std::cout<< (a<b);    
    std::cout<< (a>b);
    std::cout<< (a<=b);
    std::cout<< (a>=b);
    //std::cout<< (a==b); //ERROR
    std::cout << 'E';
    //std::cout<< (a!=b); //ERROR
    std::cout << 'E';
    std::cout<< std::is_eq(a<=>b);
    std::cout<< std::is_neq(a<=>b) << std::endl;
}

class B {
public:
  int i = {};

  std::strong_ordering operator<=> (B const& r) const = default;

};


void TestB()
{
    B a;
    B b;

    std::cout<< (a<b);    
    std::cout<< (a>b);
    std::cout<< (a<=b);
    std::cout<< (a>=b);
    std::cout<< (a==b);
    std::cout<< (a!=b);
    std::cout<< std::is_eq(a<=>b);
    std::cout<< std::is_neq(a<=>b) << std::endl;
}

class C {
public:
  bool b = {};
  int v1 = {};
  int v2 = {};

  std::strong_ordering operator<=> (C const& r) const
  {
      return (b?v1:v2) <=> (r.b?r.v1:r.v2);
  }

  bool operator== (C const& r) const
  {
      return std::is_eq(*this<=>r);
  }

};

void TestC()
{
    C a;
    C b;

    std::cout<< (a<b);    
    std::cout<< (a>b);
    std::cout<< (a<=b);
    std::cout<< (a>=b);
    std::cout<< (a==b);
    std::cout<< (a!=b);
    std::cout<< std::is_eq(a<=>b);
    std::cout<< std::is_neq(a<=>b) << std::endl;
}


int main()
{    
    TestA();
    TestB();
    TestC();

    return 0;
}

https://wandbox.org/permlink/SLmLZOc18RaJV7Mu

删除评论以获取错误.

首先我想问一下为什么默认的三向运算符的行为与用户定义的运算符不同?

First I want to ask why default three-way operator behaves differently than user define operator?

其次,对于C 类,这个问题的解决方案是否正确,还是应该以不同的方式处理?

And second, is the solution to this problem correct for class C or should it be handled differently?

这只是一个简单的例子,我想到了更复杂的情况,有数十个字段和联合(如果你不明白我的意思,请查看一些英特尔 API ;)).

This is just a simple example and I have more complex situation in mind with tens of fields and unions (If you don't know what I mean, check out some Intel APIs ;) ).

这个问题相等运算符确实没有为 C++20 中的自定义宇宙飞船运算符实现定义 重点是为什么用户定义的三向运算符没有默认的相等运算符,我想知道为什么默认和用户定义有区别行为?

This question Equality operator does not get defined for a custom spaceship operator implementation in C++20 focused on why there is no default equality operator for user defined 3-way operator, I would like to know why there is a difference in default and user define behavior?

编辑 2:

我稍微修改了示例中的 C 类以描绘更多现实生活中的问题(当默认运算符不是有效解决方案时).我还想澄清一下,我想知道这些差异背后的原因(用户定义和默认运算符之间),以便能够像我一样评估我的现实生活中的解决方案是否正确(类似于 C)对于我现在正在工作的部分代码,确实更看重代码的可维护性而不是性能.

I slightly modified class C in the example to picture more of real life problem (when default operators are not valid solution). I also want to clarify that I would like to known the reasons behind those differences (between user define and default operator) to be able to assess if my real life solution is correct (similar to C) as I do value more code maintainability than performance for a part of code that I am working right now.

推荐答案

原理原因 将等式和排序分开的原因是性能.如果您有一个类型的排序操作是用户定义的,那么通常情况下,您可以编写一个用户定义的相等测试操作,它在执行相等测试时更有效.因此,该语言应该鼓励您通过不使用 operator<=> 进行直接相等性测试来编写它.

The principle reason why equality and ordering are separated is performance. If you have a type whose ordering operations are user-defined, then more often than not, you can write a user-defined equality test operation that is more efficient at doing equality tests. And therefore, the language should encourage you to write it by not using operator<=> for direct equality testing.

这仅适用于用户定义排序/相等操作.默认排序是按成员排序的,默认相等操作也是按成员排序的.并且由于排序意味着相等,因此默认排序也默认相等是合理的.

This only really applies to user-defined ordering/equality operations. Default ordering is member-wise, and default equality operations are also member-wise. And since ordering implies equality, it is reasonable that defaulting ordering also defaults equality.

是的,他们可以让人们拼写出来,但是 确实没有充分的理由.operator<=> 旨在使选择默认排序变得容易;让你为其中一个已经暗示的东西写两个声明是没有意义的.

Yes, they could make people spell it out, but there wasn't really a good reason for that. operator<=> was meant to make it easy to opt-in to default ordering; making you write two declarations for something that's already implied by one of them doesn't make sense.

这篇关于为什么默认的三向运算符 (spaceship <=>) 生成相等运算符 (==) 而用户定义的三向运算符不生成?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆