History: Why we can overload -> and not . operator? Both are member access operator and has same significance.
I have read some reference from
http://www.stroustrup.com/bs_faq2.html#overload-dot
AND
Why can operator-> be overloaded manually?
But still my doubts remains the same why we can overload .operator while not ->?
Is it because -> operator implicitly gets the reference of the returning pointer and thus making the call as the chain calls
struct X {
int foo;
};
struct Y {
X x;
X* operator->() { return &x; }
};
struct Z {
Y y;
Y& operator->() { return y; }
};
Z z;
z->foo = 42; // Works!
z->foo = 42; This call is converted to ((z.operator()).opeartor()).operator() and thus value of foo is set to 42.
Question:- If I take this point I still have two more points,
1) why can't .(dot) operator works this way?
2) What if -> operator do not returns the reference to the class Y? Will it be a compilation error in that case?
I only understood how overloading the operator-> works, after reading this:
The expression E1->E2 is exactly equivalent to (*E1).E2 for built-in types. If a user-defined operator-> is provided, operator-> is called again on the value that it returns, recursively, until an operator-> is reached that returns a plain pointer. After that, built-in semantics are applied to that pointer.
To answer your second question...lets look at your example again:
struct X { int foo; };
struct Y {
X x;
X* operator->() { return &x; } // returns pointer
};
struct Z {
Y y;
Y& operator->() { return y; } // returns reference
};
Z z;
z->foo = 42; // Works!
The call z->
evaluates to z.y
. This is not a pointer, thus the recursion continues: (z.y)->
evalutates to &(z.y.x)
. This is a pointer, and the resulting expression is (&(z.y.x))->
.
If you make Zs operator return a pointer, the recursion stops at &(z.y)
but Y
doesnt have a foo
and the compiler will complain.