Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

weird compilation failure with overloaded const function and compiling with -pedantic

Tags:

c++

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

like image 373
user2717954 Avatar asked Sep 30 '21 08:09

user2717954


1 Answers

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.

like image 125
Possseidon Avatar answered Oct 13 '22 11:10

Possseidon