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

use*_*954 5 c++

下面的代码无法编译。
\n如果我删除bool foo(bool)重载,则a.foo(&b);调用将编译。
\n如果我const从中删除限定符,bool foo(bool*) const;a.foo(&b);调用将编译。
\n在写问题时我发现,如果没有-pedanticgcc,它也可以编译
\n我不明白为什么......

\n
struct A {   \n\n  bool foo(bool){\n    return true;\n  }\n  bool foo(bool*) const {\n    return false;\n  }\n\n};\n\n\nint main() {\n  A a;\n  a.foo(true);\n  bool b;\n  a.foo(b);\n  a.foo(&b); // does not compile\n  const_cast<const A&>(a).foo(&b); // does compile\n}\n
Run Code Online (Sandbox Code Playgroud)\n

和编译错误:

\n
error: call of overloaded \xe2\x80\x98foo(bool*)\xe2\x80\x99 is ambiguous\n   a.foo(&b);\n           ^\n/tmp/asdasd.cpp:4:8: note: candidate: bool A::foo(bool)\n   bool foo(bool){\n        ^~~\n/tmp/asdasd.cpp:7:8: note: candidate: bool A::foo(bool*) const\n   bool foo(bool*) const {\n
Run Code Online (Sandbox Code Playgroud)\n

谢谢

\n

Pos*_*don 4

首先,指针可以隐式转换为bool. 因此,指针和 a 之间的重载集bool将是不明确的,除非其中一个重载表示所有参数的完美匹配。

为了更好地形象化问题,我将成员函数提取为自由函数,这基本上是相同的事情:

struct A {};

void foo(A&, bool) {}
void foo(const A&, bool*) {}

int main() {
    A a;
    bool x;
    foo(a, &x);
}
Run Code Online (Sandbox Code Playgroud)

这两个函数都不是 的完美匹配foo,因为第一个函数需要将 转换bool*为 a bool,第二个函数需要转换Aconst

从技术上讲,添加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);
      |     ~~~~^~~~~~~
Run Code Online (Sandbox Code Playgroud)

另外,const_cast添加时有点大锤子,const因为它也可以删除const,这可能非常危险。std::as_const如果您还不能使用 C++17,最好使用或实现您自己的。