不明确的重载运算符 C++20
Ambiguous Overloaded Operator C++20
我正在尝试在最新的 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) const
因为 A
可以隐式转换为 B
但不能反过来。实际上,如果我将 B(const A&)
标记为 explicit
,我会得到一个错误,即 B
无法转换为 A
.
的私有基数
除了使用 explicit
或 B(a)
之外,我正在尝试了解如何避免这种情况。想象一下 A
和 B
是库代码,我如何在不破坏低版本接口的情况下支持 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
};
现在这个新的在两个参数中完全匹配并且是绝对优越的候选者。
我正在尝试在最新的 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) const
因为 A
可以隐式转换为 B
但不能反过来。实际上,如果我将 B(const A&)
标记为 explicit
,我会得到一个错误,即 B
无法转换为 A
.
除了使用 explicit
或 B(a)
之外,我正在尝试了解如何避免这种情况。想象一下 A
和 B
是库代码,我如何在不破坏低版本接口的情况下支持 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
};
现在这个新的在两个参数中完全匹配并且是绝对优越的候选者。