The code below fails to compile.
if I remove the bool foo(bool)
overload, then the a.foo(&b);
call compiles.
if I remove the const
qualifier from bool foo(bool*) const;
then the a.foo(&b);
call compiles.
While writing the question I found out that without -pedantic
to gcc it also compiles
I can't understand why...
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
}
and the compilation error:
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 {
thanks
CodePudding user response:
First of all, pointers are implicitly convertible to bool
. So an overload set between a pointer and a bool
will be ambiguous unless one of the overloads represents a perfect match on all parameters.
To better visualize the issue I extracted the member functions to free functions, which is basically the same thing:
struct A {};
void foo(A&, bool) {}
void foo(const A&, bool*) {}
int main() {
A a;
bool x;
foo(a, &x);
}
Neither of the function is a perfect match for foo
, as the first one needs to convert the bool*
into a bool
and the second one needs to convert A
to const
.
Technically adding const
would be a better match, but ISO C says it's still ambiguous in this case. When you remove -pedantic
from gcc, it tells you exactly that:
<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);
| ~~~~^~~~~~~
Also, const_cast
is a bit of a big hammer for adding const
as it can also remove const
, which can be very dangerous. Better use std::as_const
or implement your own if you can't use C 17 yet.