下面的代码无法编译。
如果我删除bool foo(bool)
过载,则a.foo(&b);
调用编译。
如果我从bool foo(bool*) const;
中删除const
限定符,则a.foo(&b);
调用编译。
在写问题的时候,我发现没有-pedantic
到gcc它也编译
我不明白为什么…
struct A {
bool foo(bool){
return true;
}
bool foo(bool*) const {
return false;
}
};
int main() {
A a;
a.foo(true);
bool b;
a.foo(b);
a.foo(&b); // does not compile
const_cast<const A&>(a).foo(&b); // does compile
}
和编译错误:
error: call of overloaded ‘foo(bool*)’ is ambiguous
a.foo(&b);
^
/tmp/asdasd.cpp:4:8: note: candidate: bool A::foo(bool)
bool foo(bool){
^~~
/tmp/asdasd.cpp:7:8: note: candidate: bool A::foo(bool*) const
bool foo(bool*) const {
感谢首先,指针可以隐式转换为bool
。所以一个过载之间设置一个指针,bool
将模棱两可,除非其中一个过载代表一个完美的匹配所有参数。
为了更好地可视化问题,我将成员函数提取为自由函数,这基本上是相同的事情:
struct A {};
void foo(A&, bool) {}
void foo(const A&, bool*) {}
int main() {
A a;
bool x;
foo(a, &x);
}
这两个函数都不能完美匹配foo
,因为第一个函数需要将bool*
转换为bool
,第二个函数需要将A
转换为const
。
从技术上讲,添加const
将是更好的匹配,但ISO c++说在这种情况下它仍然是模糊的。当您从gcc中删除-pedantic
时,它确切地告诉您:
<source>:9:9: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:
9 | test(a, &x);
| ~~~~^~~~~~~
此外,const_cast
对于添加const
来说有点大,因为它也可以删除const
,这可能非常危险。如果你还不能使用c++ 17,最好使用std::as_const
或者自己实现。