I am learning C++ concepts and would highly appreciate any help with explanation. Why statement 4 is not compiling but statement 1 is.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
class X {
public:
X& operator= (const X& rhs);
const X& operator+ (const X& rhs) const;
const X& operator+ (int m);
private:
int n;
};
int main() {
X a, b, c;
a = a + 5 + c; //statement 1 - No compiler errors
a = b + 5; //statement 2
a = a = b + c; //statement 3
a = b + c + 5; //statement 4
/*compiler Error thrown - passing 'const X' as 'this' argument of 'const X& X::operator+(int)'
discards qualifiers [-fpermissive]*/
(c = a + a) = b + c; ////statement 5
}
As per my understanding (based on: both + & = are right-associative) above 5 statements are called as-
//statement 1
a.operator=(a.operator+(5.operator+(c))); -->I believe this should have thrown error as no defined constructor supports this
Statement 4 is a.operator=(a.operator+(c).operator+(5));
The problem is that operator+(int) has not been marked as const so it can't be used on the const X& that was returned by a.operator+(c).
You assume right-associativity, but remember this is not the same operator, you have 2 versions of it, and the compiler has to decide which one takes precedence.
Operator overloading is just a convenient syntax for writing certain functions. So you may be using "+" everywhere, but the compiler still has to decide which of your functions to call at any given instance.
Enter overloaded resolution!
There is no int::operator+(X) for doing 5 + c, statement 1 is resolved as "a = (a + 5) + c"
a.operator=((a.operator+(5)).operator+(c) const);
In statement 4, const X& operator+ (const X& rhs) const; is called first, in favour of const X& operator+ (int m); - think of it as being a different operator with higher precedence. So you get a = (b + c) + 5, since operator+(int) is not a const function, it can't be called for a const object (the result of a+b), hence your build error.
a.operator=((b.operator+(c)).operator+(5) -> this won't compile
Ifconst X& operator+ (int m) const; your code would compile.