c++operatorsoverloadingdot-operator

What if -> operator do not return the reference like dot . operator? Will this stop overloading -> operator as well?


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?


Solution

  • 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.