重写比较运算符会导致哪些重大更改? [英] What are the breaking changes caused by rewritten comparison operators?

查看:52
本文介绍了重写比较运算符会导致哪些重大更改?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++ 20中有一些关于重写比较运算符的新规则,我正在尝试了解它们的工作方式.我遇到了以下程序:

There are some new rules about rewritten comparison operators in C++20, and I'm trying to understand how they work. I've run into the following program:

struct B {};

struct A
{
    bool operator==(B const&);  // #1
};

bool operator==(B const&, A const&);  // #2

int main()
{
  B{} == A{};  // C++17: calls #2
               // C++20: calls #1
}

实际上破坏了现有代码.我对此感到有些惊讶;#2 实际上对我来说仍然看起来更好:p

which actually breaks existing code. I'm a little surprised by this; #2 actually still looks better to me :p

那么这些新规则如何改变现有代码的含义?

So how do these new rules change the meaning of existing code?

推荐答案

该特定方面是一种简单的重写形式,即反转操作数.主要运算符 == < => 可以颠倒,辅助运算符!= < > < = > = ,可以根据原语进行重写.

That particular aspect is a simple form of rewriting, reversing the operands. The primary operators == and <=> can be reversed, the secondaries !=, <, >, <=, and >=, can be rewritten in terms of the primaries.

可通过一个相对简单的示例来说明倒车方面.

The reversing aspect can be illustrated with a relatively simple example.

如果没有特定的 B :: operator ==(A)来处理 b == a ,则可以使用相反的方法来代替: A :: operator ==(B).这是有道理的,因为相等是双向关系:(b == a).

If you don't have a specific B::operator==(A) to handle b == a, you can use the reverse to do it instead: A::operator==(B). This makes sense because equality is a bi-directional relationship: (a == b) => (b == a).

次要运算符的重写涉及使用不同运算符.考虑 a>b .如果找不到直接执行此功能的函数,例如 A :: operator>(B),则该语言将查找诸如 A :: operator&==((B),然后简单地从中计算结果.

Rewriting for secondary operators, on the other hand, involves using different operators. Consider a > b. If you cannot locate a function to do that directly, such as A::operator>(B), the language will go looking for things like A::operator<=>(B) then simply calculating the result from that.

这是一个简单的过程视图,但是我的大多数学生似乎都知道.如果需要更多详细信息,请参见C ++ 20的 [over.match.oper] 部分,这是重载分辨率的一部分( @ 是操作符的占位符):

That's a simplistic view of the process but it's one that most of my students seem to understand. If you want more details, it's covered in the [over.match.oper] section of C++20, part of overload resolution (@ is a placeholder for the operator):

对于关系和相等运算符,重写的候选包括运算符< ==> 的所有成员,非成员和内置候选,其表达式为(x< => y)@ 0 使用该 operator< => 格式正确.

For the relational and equality operators, the rewritten candidates include all member, non-member, and built-in candidates for the operator <=> for which the rewritten expression (x <=> y) @ 0 is well-formed using that operator<=>.

对于关系,相等和三向比较运算符,重写的候选还包括一个合成的候选,对于两个成员,非成员和内置候选,两个参数的顺序颠倒了.运算符< => ,使用该 operator< =>格式的重写表达式 0 @(y< => x)格式正确..

For the relational, equality, and three-way comparison operators, the rewritten candidates also include a synthesized candidate, with the order of the two parameters reversed, for each member, non-member, and built-in candidate for the operator <=> for which the rewritten expression 0 @ (y <=> x) is well-formed using that operator<=>.


因此不得不提供真正的 operator == operator< 然后进行电镀的日子已经过去了:


Hence gone are the days of having to provide a real operator== and operator<, then boiler-plating:

operator!=      as      !  operator==
operator>       as      ! (operator== || operator<)
operator<=      as         operator== || operator<
operator>=      as      !  operator<

如果我弄错了一个或多个错误,请不要抱怨,这只说明了我对C ++ 20更好的看法,因为您现在只需要提供最小的设置(很可能只是 operator< => 以及您想要提高效率的任何其他功能),然后让编译器来照顾它:-)

Don't complain if I've gotten one or more of those wrong, that just illustrates my point on how much better C++20 is, since you now only have to provide a minimal set (most likely just operator<=> plus whatever else you want for efficiency) and let the compiler look after it :-)

可以通过以下代码辨别为什么一个人比另一个人被选中的问题:

The question as to why one is being selected over the other can be discerned with this code:

#include <iostream>

struct B {};
struct A {
    bool operator==(B const&) { std::cout << "1\n"; return true; }
};
bool operator==(B const&, A const&) { std::cout << "2\n"; return true; }

int main() {
  auto b = B{}; auto a = A{};

           b ==          a;  // outputs: 1
  (const B)b ==          a;  //          1
           b == (const A)a;  //          2
  (const B)b == (const A)a;  //          2
}

那的输出表明是 a const -ness决定哪个是更好的候选者.

The output of that indicates that it's the const-ness of a deciding which is the better candidate.

顺便说一句,您可能想看看这篇文章,它提供了更深入的了解.

As an aside, you may want to have a look at this article, which offers a more in-depth look.

这篇关于重写比较运算符会导致哪些重大更改?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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