Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ const conversion in the case of operators

Tags:

c++

g++

Consider the following code:

struct A {
    void operator++() const {}
};

void operator++(const A&) {}


int main () {
    const A ca;
    ++ca; // g++ Error (as expected): ambiguous overload for ‘operator++’

    A a;
    ++a; // g++ 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"
         // candidate 1: void operator++(const A&)
         // candidate 2: void A::operator++() const
}

Why is g++ only issuing a warning and not an error on ++a? In other words, how is the non-member function a better fit than the member function?

Thank you!

like image 587
bap Avatar asked Mar 20 '14 23:03

bap


2 Answers

If I were to guess, the member function causes a pointer qualification conversion from A * to A const * when initializing this, whereas the non-member binds an A const & reference to a non-const object, which isn't really a conversion at all but is merely a non-preferred case during overload resolution.

That message comes about when the paths leading from the argument type to the respective parameter types involve different kinds of conversions. The standard refuses to compare apples to oranges, e.g. pointer qualification vs. reference binding or integral promotion vs. conversion operator, but GCC is willing.

like image 65
Potatoswatter Avatar answered Oct 10 '22 16:10

Potatoswatter


In c++ you can separate methods (and operators) for const and not const, When you don't do it, the compiler can search for the "best fit". The best fit for the not const is the const.

take a look at this example:

struct S{
  void f(){cout<<"f";}
  void f()const{cout<<"f-const";}
};

int main(){
   const S sc;
   S s;
   s.f();
   sc.f();
   return 0;
}

the output for the 1st print will be "f" but for the 2nd it will be "f-const"

if I remove the not const method from the struct, I'll get the same output for the both objects. and this is because the function is what called "best fit", since it can add the "constiness" to a not const object. (can't remove the const method since it won't fit at all...)

In your code there is no explicit operator for not const so when it look for the "best fit" it can choose from the options, and take what look like the best. you got a warning since there was 2 fits, but still it choose one of them, I don't know why one look better then the other... but for the const it have two explicit functions, the compiler can't choose when have explicit method! that is why you've got an error.

If you want the same behavior add also explicit not const operator, like this:

struct A {
    void operator++() const {}
    void operator++(){};
};

void operator++(const A&) {}
void operator++(A&) {}

Now you'll get the same error for both.

like image 1
SHR Avatar answered Oct 10 '22 17:10

SHR