6

The following code has 2 definitions of operator+ - one is on the class Foo, and the other one is a standalone function.

I feel like the compiler should have complained about this, but it didn't. When I use operator+ in the main function, it picks the one defined in the class. When I delete the one in the class, it starts using the standalone function.

The fact that deleting a class method silently changes the behavior of the C++ program is very concerning. Is there a rationale behind this?

https://ideone.com/rtfEFP

#include <iostream>

class Foo
{
public:
    int operator+(const Foo& b)
    {
        return 5;
    }
};

int operator+(const Foo& a, const Foo& b)
{
    return 6;
}

int main()
{
    Foo a, b;
    int c{ a + b };
    std::wcout << c << std::endl;
    return 0;
}
Shivanshu Goyal
  • 1,374
  • 2
  • 16
  • 22

2 Answers2

7

The two signatures don't really match because the first takes a non-const reference for the first operand. To "fix" this, make it const:

int operator+(const Foo& b) const

or make the first parameter of the non-member non-const (don't do that in real code!)

int operator+(Foo& a, const Foo& b)

That will cause your code to produce an ambiguous overload compiler diagnostic.

With your original code, the member is picked, because the non-const reference matches the operands better.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • It's interesting that when I remove the usage of `operator+` in the `main()` function and add a `const` keyword to the class method, the compiler doesn't complain about the ambiguity. It only complains about the ambiguity when you actually try to use the operator. – Shivanshu Goyal Feb 16 '18 at 06:35
  • @ShivanshuGoyal The signatures are not exactly the same (one is a member function, the other a non-member) which explains why you don't get duplicate symbol errors. And since you don't use the overload, there is no overload resolution to catch the issue. – juanchopanza Feb 16 '18 at 08:06
2

This is analogous to overloads based on const and non-const qualifiers.

int operator+(const Foo& a, const Foo& b)
{
    return 6;
}

is like a const member function.

Given

Foo a;
Foo const b;
Foo c;

a + c; // Resolves to the non-const member function.

b + c; // Resolves to the non-member function since the first argument
       // is of type `const Foo&`.
R Sahu
  • 204,454
  • 14
  • 159
  • 270