operator->()

Hi, I have was doing one exercise where I have to implement some kind of interface so Container with some stuff but I stopped here!

I got a bit confused what would be the best way to overload operator->() and operator*() and I started to test how things are looking when I overloaded them the way I did. And this was really confusing to me.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <vector>
#include <iostream>

template<typename Container>
class Interface
{
public:
	explicit Interface(Container& cont) : ptr{ &cont } {}

	Container& operator*() { return *ptr; }
	Container* operator->() { return ptr; }

private:
	Container* ptr;
};


int main()
{
	std::vector<int> vec{ 1,2,3,4,5,6,7,8,9 };

	Interface<std::vector<int>> p{ vec };

        //BOTH LINES OF CODE ARE GETTING ME THE CORRECT SIZE OF VECTOR

	int x = p->size();    //why is this accessing vector just with one operation?
	int y = p.operator->()->size(); //this actually makes sence, 1st access pointer to vector and 2nd its member function

	std::cout << x << std::endl;
	std::cout << y << std::endl;

	system("pause");
}

By what language rules is the 1st line actually working? (int x = p->size();)
Are your question aiming at the ISO standard?

Apart from this it is a (useful) matter of design that you can write it like on line 26. Or
why is this accessing vector just with one operation?
Why not?
Tnx for reply. Question is about thats its weird that if i overload these operatos like this so that they do the same thing
1
2
3
//both returning exactly the same thing : Container*
Container* operator*() { return ptr;  }
Container* operator->() { return ptr; }


Doesn't make sence to me that
1
2
3
4
5
6
7
8
/*method one has to use 
1. operator*() to access pointer to container
2. now use operator->() to get the desired member function*/
std::cout << " size = " << (*p)->size() << std::endl;
/*method 2 has to use 
1. operator->() to access pointer to container
2. there are no step 2 coz access of Container* and its member function size() happens with one step */
std::cout << " size = " << p->size() << std::endl;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>

template < typename T > struct ptr_1
{
    T* p ;
    T* operator->() { std::cout << "ptr_1<T>::operator->() => " ; return p ; }
};

template < typename T > struct ptr_2
{
    ptr_1<T> sp ;
    ptr_1<T> operator->() { std::cout << "ptr_2<T>::operator->() => " ; return sp ; }
};

int main()
{
    struct A { const void* foo() const { std::cout << "A::foo()\n" ; return this ; } };
    A a ;
    A* pa = std::addressof(a) ;

    ptr_1<A> p1 = { pa } ;

    p1.operator->()->foo() ; // ptr_1<T>::operator->() => A::foo()

    // p1 is not a pointer; resolve overload; p1->foo() == p1.operator->()->foo()
    p1->foo() ;              // ptr_1<T>::operator->() => A::foo()

   std::cout << "\n ----------------------------------------------------------------------\n\n" ;

    ptr_2<A> p2 = { p1 } ;

    p2.operator->().operator->()->foo() ; // ptr_2<T>::operator->() => ptr_1<T>::operator->() => A::foo()

    p2.operator->()->foo() ;              // ptr_2<T>::operator->() => ptr_1<T>::operator->() => A::foo()


    // p2 is not a pointer; resolve overload; p2->foo() == p2.operator->()->foo()
    // p2.operator->() yields p1; p1 is not a pointer; resolve overload; p1->foo() == p1.operator->()->foo()
    // ie. p2.operator->().operator->()->foo()
    p2->foo() ;                           // ptr_2<T>::operator->() => ptr_1<T>::operator->() => A::foo()
}

http://coliru.stacked-crooked.com/a/7e615715dc952696
Doesn't make sence to me that
Well, I can't seem to figure out the problem.
It is so because you made it so?
Tnx for replies. Ill try to explain the problem more clearly. This example was very cool, tnx a lot man! However I saw that it was working but didnt really understand why.

Maybe someone could explain a bit more this part
1
2
3
// p2 is not a pointer; resolve overload; p2->foo() == p2.operator->()->foo()
// p2.operator->() yields p1; p1 is not a pointer; resolve overload; p1->foo() == p1.operator->()->foo()
// ie. p2.operator->().operator->()->foo() 


I see that p2->foo() == p2.operator->().operator->()->foo()
but exactly why that is happening. If I was compiler writer I would give the following error
error : ptr_1<T> doesnt have member function foo() 

Better yet - when I'm actually creating function foo() for ptr_1<T> and im not modifying anything else in the JLBorges program
1
2
3
4
5
6
template < typename T > struct ptr_1
{
    T* p ;
    void foo(){std::cout << "CALLED FOO INSIDE PTR1\n";}
    T* operator->() { std::cout << "ptr_1<T>::operator->() => " ; return p ; }
};

still only call to A::foo() is happening.

I'm just ultra confused about this. What book or internet resource I can read to understand more about this?
An expression x->m is interpreted as (x.operator->())->m for a class object x ... - IS


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>

template < typename T > struct ptr_1
{
    T* p ;
    T* operator->() { std::cout << "ptr_1<T>::operator->() => " ; return p ; }
    void foo() { std::cout << "CALLED FOO INSIDE PTR1\n"; }
};

int main()
{
    struct A { const void* foo() const { std::cout << "A::foo()\n" ; return this ; } };
    A a ;
    A* pa = std::addressof(a) ;

    ptr_1<A> p1 = { pa } ;

    p1->foo() ; // ptr_1<T>::operator->() => A::foo() ( note: p1-> )

    p1.foo() ; // CALLED FOO INSIDE PTR1 ( note: p1. )
}

http://coliru.stacked-crooked.com/a/9810f92d0a6c55f5
Tnx for an answer man. This is my bad that I didn't see it actually :)
Topic archived. No new replies allowed.