c++ - 重写比较运算符会带来哪些重大变化?
问题描述
在 C++20 中有一些关于重写比较运算符的新规则,我试图了解它们是如何工作的。我遇到了以下程序:
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
那么这些新规则如何改变现有代码的含义呢?
解决方案
该特定方面是一种简单的重写形式,即反转操作数。主运算符==
和<=>
可以颠倒,辅助运算符!=
, <
, >
, <=
, 和>=
, 可以根据主运算符重写。
倒车方面可以用一个相对简单的例子来说明。
如果您没有B::operator==(A)
要处理的特定b == a
内容,则可以使用相反的方法来代替:A::operator==(B)
. 这是有道理的,因为相等是一种双向关系:(a == b) => (b == a)
.
另一方面,对二级运算符的重写涉及使用不同的运算符。考虑a > b
。如果您无法找到直接执行此操作的函数,例如A::operator>(B)
,该语言将寻找诸如A::operator<=>(B)
然后简单地从中计算结果之类的东西。
这是对过程的简单看法,但我的大多数学生似乎都理解这一点。如果您想了解更多详细信息,请参阅[over.match.oper]
C++20 部分,重载决议的一部分(@
是运算符的占位符):
对于关系和等式运算符,重写的候选包括所有成员、非成员和内置候选,
<=>
其重写表达式(x <=> y) @ 0
使用 that 格式正确operator<=>
。对于关系运算符、相等运算符和三向比较运算符,重写的候选还包括一个合成候选,两个参数的顺序颠倒,对于每个成员、非成员和内置候选的运算符
<=>
,使用 that重写的表达式0 @ (y <=> x)
是格式良好的operator<=>
。
因此,必须提供真正的operator==
and operator<
,然后进行样板化的日子已经一去不复返了:
operator!= as ! operator==
operator> as ! (operator== || operator<)
operator<= as operator== || operator<
operator>= as ! operator<
如果我弄错了其中一个或多个,请不要抱怨,这只是说明了我的观点,即 C++20 有多好,因为您现在只需提供一个最小集合(很可能只是operator<=>
加上您想要的任何其他内容为了效率)并让编译器照顾它:-)
关于为什么选择一个而不是另一个的问题可以通过以下代码来辨别:
#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
}
其输出表明这是决定哪个是更好的候选者的const
-ness 。a
顺便说一句,您可能想看看这篇文章,它提供了更深入的了解。
推荐阅读
- firebase - 云函数中的批量写入或事务?
- laravel - 如何使用 post 方法在 ionViewWillEnter 中显示离子数据?
- kotlin - 如何使用 Kotlin/Native 应用程序将字符串写入剪贴板(Windows 操作系统)?
- python - Django - 如何按注释值过滤
- c - c中字符数组的串联
- react-native - 任务 ':app:processDebugResources' 执行失败。> 安卓资源链接失败可以再构建RN安卓版
- ios - CoreLocation 的 requestLocation 方法的替代方案
- gcc - OpenSSL linking undefined reference to `EVP_MD_CTX_new' and others
- java - SpringExtension 没有显式配置?
- javascript - 在浏览器环境中,如何检测到所有 JavaScript 代码都已终止?