使用重载const函数和-pedantic编译时出现奇怪的编译失败



下面的代码无法编译。
如果我删除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或者自己实现。

相关内容

  • 没有找到相关文章

最新更新