C++17 operator==() and operator!=() code fails with C++20(C++17运算符==()和运算符!=()代码在C++20中失败)
问题描述
我有以下示例代码:
#include <assert.h>
struct Base
{
bool operator==(const Base& rhs) const
{
return this->equalTo(rhs);
}
virtual bool equalTo(const Base& rhs) const = 0;
};
inline bool operator!=(const Base& lhs, const Base& rhs)
{
return !(lhs == rhs);
}
struct A : public Base
{
int value = 0;
bool operator==(const A& rhs) const
{
return (value == rhs.value);
}
virtual bool equalTo(const Base& rhs) const
{
auto a = dynamic_cast<const A*>(&rhs);
return (a != nullptr) ? *this == *a : false;
}
};
class A_1 : public A
{
virtual bool equalTo(const Base& rhs) const
{
auto a_1 = dynamic_cast<const A_1*>(&rhs);
return (a_1 != nullptr) ? *this == *a_1 : false;
}
};
int main()
{
A_1 a_1;
a_1.value = 1;
// Make sure different types aren't equal
A a;
a.value = 1;
assert(a_1 != a);
}
当我用C++17编译时,一切都很好(如所需,没有断言)。使用C++20生成相同的代码会导致触发Assert。
在使用C++20编译时,如何使这些现有代码工作?如果我用C++20放大警告,我会得到'operator !=': unreferenced inline function has been removed
;我怀疑这一切都与operator<=>()
有某种关系。
这真的是从C++17到C++20的已知/所需的重大更改吗?
推荐答案
在C++17中,行
assert(a_1 != a);
调用operator!=(const Base&, const Base&)
,因为它当然是唯一的候选者。然后调用a_1->equalTo(a)
,它试图将a
向下转换为A_1
,这在您的逻辑中会给出FALSE。因此a_1 != a
评估为true
。
在C++20中,我们现在额外考虑根据
==
重写的候选对象。因此,现在我们有三位候选人:
Base::operator==(const Base&) const
(重写)A::operator==(const A&) const
(重写)bool operator!=(const Base&, const Base&)
a_1 != a
计算为!((const A&)a_1 == a)
,这为您提供了不同的答案。
然而,您的操作符从根本上说是失败的。即使在C++17中,我们也有这样的场景:a_1 != a
计算为true
,而a != a_1
计算为false
。这基本上是试图像这样做动态相等的固有问题:this->equalTo(rhs)
和rhs.equalTo(*this)
实际上可能会做不同的事情。因此,这个问题与其说是C++20比较问题,不如说是一个基本的设计问题。
这篇关于C++17运算符==()和运算符!=()代码在C++20中失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:C++17运算符==()和运算符!=()代码在C++20中失败


- 将 hdc 内容复制到位图 2022-09-04
- XML Schema 到 C++ 类 2022-01-01
- GDB 不显示函数名 2022-01-01
- OpenGL 对象的 RAII 包装器 2021-01-01
- 将函数的返回值分配给引用 C++? 2022-01-01
- 从父 CMakeLists.txt 覆盖 CMake 中的默认选项(...)值 2021-01-01
- 哪个更快:if (bool) 或 if(int)? 2022-01-01
- DoEvents 等效于 C++? 2021-01-01
- 如何提取 __VA_ARGS__? 2022-01-01
- 使用 __stdcall & 调用 DLLVS2013 中的 GetProcAddress() 2021-01-01