Reputation: 21
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.
Upvotes: 1
Views: 1668
Reputation: 76285
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.
Upvotes: 8
Reputation: 238341
From the other questions I've seen, they are all errors instead of warning.
That might be because punctual programmers tell their compiler to not accept non-standard compliant programs which is something that you may have skipped. For example, they would use -pedantic
or even more strict -pedantic-errors
options when using the GNU compiler.
So I'm not really sure why does it code still work.
If you don't tell your compiler to not accept non-standard code, then it might accept it if they support it as an extension to the language. In this case the standard says that the overloads are equally ambiguous and that the program is ill-formed, but a compiler might be optimistic and guess the overload that you may have meant to use, despite what the standard says.
The code that you show happens to compile with only warnings in g++ when not using any options, but with the -pedantic
option, those warnings become errors. Usually -pedantic
only adds warnings when using language extensions, but in this case it appears to promote a warning into an error.
Upvotes: 3