c++ - 模棱两可的重载运算符 C++20

标签 c++ operator-overloading c++20 ambiguous spaceship-operator

我正在尝试在最新的 Visual Studio 和 Clang 版本中测试我的项目。弹出的错误之一与不明确的运算符有关 (with reversed parameter order) .这似乎没有在 C++17 中弹出。
例如:(https://godbolt.org/z/Gazbbo)

struct A {
    bool operator==(const A& other) const { return false; }
};

struct B : private A {
    B(const A&);
    bool operator==(const B& other) const { return false; }
};

bool check(A a, B b) {
    return b == a;
}
我不确定为什么这会是一个问题。在我看来,这里唯一可行的功能是 bool operator==(const B& other) constA可以隐式转换为 B但不是相反。确实,如果我标记 B(const A&)explicit相反,我得到一个错误 B无法转换为 A 的私有(private)基数.
除了使用 explicit 之外,我试图了解我可以做些什么来避免这种情况。或使用 B(a) .想象一下 AB是库代码,如何在不破坏低版本界面的情况下支持 C++20?

最佳答案

在 C++17 中,是的,唯一可行的候选者是 b.operator==(B(a))。 .

但在 C++20 中,比较运算符具有更多功能。平等现在也可以考虑颠倒和重写的候选人。所以当考虑表达式 b == a我们还考虑表达式 a == b .结果,我们有两个候选人:

bool B::operator==(B const&);
bool A::operator==(A const&); // reversed
B成员函数在左侧完全匹配,但需要转换第二个参数。 A成员函数在右侧完全匹配,但需要转换第一个参数。没有一个候选人比另一个更好,所以结果变得模棱两可。
至于怎么修。这是一种奇怪的场景(B 都继承自 A 并且可以从 A 构造?)。如果您放弃继承,则删除 A成员候选人。如果您删除 B(A const&)构造函数,那么您会遇到访问冲突,因为唯一的候选者是比较 A 的候选者。需要转换 b 的到它的A (这表明这是有问题的)。
或者,您可以添加到 B ,直接比较 A定义这实际上意味着什么。由于这里的问题是有两种选择,编译器不知道哪一种是最好的,所以只提供一个更好的:
struct B  : private A {
    B(const A&);
    bool operator==(B const&) const;
    bool operator==(A const&) const; // <== add this one
};
现在,这个新的在两个论点中都是完全匹配的,并且是绝对优越的候选者。

关于c++ - 模棱两可的重载运算符 C++20,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65946930/

相关文章:

c++ - 在 Visual C++ 6.0 中取消标记项目

c++ - 什么时候通过复制/引用?

c++ - 混淆涉及 *this 的 C++ 代码?

c++ - 在类外定义重载的外流运算符

c++ - 为什么我不能在类范围内声明概念?

c++ - 如何在项目编辑期间清除 QTreeView 中的背景?

c++ - 使用 Redis 从 C++ 触发 Celery 任务

c++ - &member 到 const 成员

c++ - 如何将概念应用于成员变量

c++ - 使用类成员函数初始化 std::barrier