[英]Why default three-way operator (spaceship <=>) generates equality operator (==) and user define three-way operator not?
Consider this code:考虑这段代码:
#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 https://wandbox.org/permlink/SLmLZOc18RaJV7Mu
Remove comments to get an error.删除评论以获取错误。
First I want to ask why default three-way operator behaves differently than user define operator?首先我想问一下为什么默认的三路运算符的行为与用户定义的运算符不同?
And second, is the solution to this problem correct for class C
or should it be handled differently?其次,这个问题的解决方案对于 class
C
是否正确,还是应该以不同的方式处理?
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;) ).这只是一个简单的例子,我对数十个字段和联合有更复杂的情况(如果你不明白我的意思,请查看一些英特尔 API;))。
Edit:编辑:
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?这个问题Equality operator does not get defined for a custom spaceship operator implementation in C++20重点是为什么用户定义的 3 路运算符没有默认相等运算符,我想知道为什么默认值和用户存在差异定义行为?
Edit 2:编辑2:
I slightly modified class C
in the example to picture more of real life problem (when default operators are not valid solution).我在示例中稍微修改了 class
C
以描绘更多现实生活中的问题(当默认运算符不是有效的解决方案时)。 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.我还想澄清一下,我想知道这些差异背后的原因(用户定义和默认运算符之间),以便能够评估我的现实生活中的解决方案是否正确(类似于
C
),因为我确实更看重代码可维护性而不是性能对于我现在正在工作的部分代码。
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.因此,该语言应该鼓励您通过不使用
operator<=>
进行直接相等测试来编写它。
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.
并且由于排序意味着相等,因此默认排序也默认相等是合理的。
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; operator<=>
旨在使选择默认排序变得容易; making you write two declarations for something that's already implied by one of them doesn't make sense.让你为其中一个已经暗示的东西写两个声明是没有意义的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.