While I was writing some code regarding basic operator overloading. I came upon this snippet of code,
struct MyInt {
public:
MyInt() : data() { };
MyInt(int val) : data(val) { }
MyInt& operator++() {
++data;
return (*this);
}
MyInt operator++(int) {
MyInt copy = *this;
++data;
return copy;
}
MyInt& operator+=(const MyInt& rhs) {
data += rhs.data;
return *this;
}
MyInt operator+(const MyInt& rhs) const {
MyInt copy = *this;
copy += rhs;
return copy;
}
int data;
};
These are all fine until I added this right after the declaration of the class
MyInt operator+(const MyInt& lhs, const MyInt& rhs)
{
MyInt copy = lhs;
copy.data += rhs.data;
return copy;
}
With this main declartion
int main () {
MyInt mi = 10;
MyInt mi2 = 11;
MyInt mi3 = mi++ + ++mi2;
mi3 += mi2;
}
When I tried compiling, g++ threw this warning at me
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:
MyInt mi3 = mi++ + ++mi2;
^
note: candidate 1: MyInt operator+(const MyInt&, const MyInt&)
MyInt operator+(const MyInt& lhs, const MyInt& rhs)
^
note: candidate 2: MyInt MyInt::operator+(const MyInt&) const
MyInt operator+(const MyInt& rhs) const {
From the other questions I've seen, they are all errors instead of warning. So I'm not really sure why does it code still work. Hope someone can explain to me why does this happen.
Thanks in advance.
There's a member function operator+(const MyInt&) const
which could be called like this:
MyInt m1;
MyInt m2;
m1 + m2;
There's also a free function operator+(const MyInt&, const MyInt&)
, which could be called like this:
MyInt m1;
MyInt m2;
m1 + m2;
That's why the compiler is complaining: the language definition says that there's no way to decide which one to use. Pick one or the other.
The usual convention is to have only the free function, and implement it by calling operator+=
.
The warning is telling you that accepting the code is a gcc extension. Formally, compilers are not required to refuse to compile erroneous code. The only requirement is that they issue a diagnostic, which gcc did. Having done that, it's free to continue to compile the code in some way that the compiler writer thinks is reasonable. Code that relies on such an extension is not portable.