Connecting Tech Pros Worldwide Forums | Help | Site Map

Overloading -> and ->*

maths_fan
Guest
 
Posts: n/a
#1: Jul 22 '05
Can't understand how to overload these operations and for what reason?

Thomas Tutone
Guest
 
Posts: n/a
#2: Jul 22 '05

re: Overloading -> and ->*



"maths_fan" <maths_fan@mail.ru> wrote:
[color=blue]
> Can't understand how to overload these operations and for what reason?[/color]

Can't understand your question real well either. Do you think you could
write it a little more clearly?

You overload these operators like any other operator. operator->() is
typically overloaded to implement smart pointers. A good example of a
reference-counting smart pointer, which demonstrates how to overload
operator->(), appears in the FAQ:

http://www.parashift.com/c++-faq-lit...html#faq-16.21

Of course, I'm sure you consulted the FAQ before posting any questions here,
right?

Overloading the pointer to member operator (->*) is done a lot less
frequently, but again is used to implement smart pointers.

Best regards,

Tom


Nick Hounsome
Guest
 
Posts: n/a
#3: Jul 22 '05

re: Overloading -> and ->*



"maths_fan" <maths_fan@mail.ru> wrote in message
news:c13b5d9.0402280407.7943e365@posting.google.co m...[color=blue]
> Can't understand how to overload these operations and for what reason?[/color]

1.
struct X
{
Y* operator->();
}

2. (the not obvious bit)
Because the compiler will reapply -> to the result.
This allows smart pointers, lazy construction, locking and much more.

2a. I've never come across a reason to overload ->*


Tom Plunket
Guest
 
Posts: n/a
#4: Jul 22 '05

re: Overloading -> and ->*


Nick Hounsome wrote:
[color=blue]
> 1.
> struct X
> {
> Y* operator->();
> }
>
> 2. (the not obvious bit)
> Because the compiler will reapply -> to the result.
> This allows smart pointers, lazy construction, locking and much more.[/color]

I've had some problems with this in the past.

My compiler was Codewarrior, and the fix was to do
(*myIterator)->MethodCall();

This was with not-std:: containers, but is this basically telling
me that I *should* be able to have a container of pointers to
objects, and do iterator->call() and have it bounce through
operator->() implementations 'til it gets to the end? Are there
any gotchas that I may not have been aware of that would prevent
this from happening correctly?

thx,
-tom!
Rob Williscroft
Guest
 
Posts: n/a
#5: Jul 22 '05

re: Overloading -> and ->*


Tom Plunket wrote in news:e2d4409hgqe4s1jll2mvtucl4ogmvanu3l@4ax.com:
[color=blue]
> Nick Hounsome wrote:
>[color=green]
>> 1.
>> struct X
>> {
>> Y* operator->();
>> }
>>
>> 2. (the not obvious bit)
>> Because the compiler will reapply -> to the result.
>> This allows smart pointers, lazy construction, locking and much more.[/color]
>
> I've had some problems with this in the past.
>
> My compiler was Codewarrior, and the fix was to do
> (*myIterator)->MethodCall();
>
> This was with not-std:: containers, but is this basically telling
> me that I *should* be able to have a container of pointers to
> objects, and do iterator->call() and have it bounce through
> operator->() implementations 'til it gets to the end? Are there
> any gotchas that I may not have been aware of that would prevent
> this from happening correctly?
>[/color]

Yes, if you have:

#include <vector>

struct X
{
int x;
};

int main()
{
X x;
std::vector< X * > xpv( 10, &x );
std::vector< X * >::iterator ptr = xpv.begin();
}

Then ptr.operator -> () will return an X**, not an X*.

If you try ptr->x, the compiler will call ptr.operator -> () and
then try to apply the inbult (X**)->x, however there is no such
operator, inbult opertor -> *only* applies to pointers to struct's (*)
and X** is a pointer to a pointer not a pointer to a struct.

*) by 'struct' I mean aggragate i.e, struct, class or union.

So the Gotcha would be "there is no inbuilt operator -> for T**".

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Tom Plunket
Guest
 
Posts: n/a
#6: Jul 22 '05

re: Overloading -> and ->*


Rob Williscroft wrote:
[color=blue]
> struct X
> {
> int x;
> };
>
> int main()
> {
> X x;
> std::vector< X * > xpv( 10, &x );
> std::vector< X * >::iterator ptr = xpv.begin();
> }
>
> Then ptr.operator -> () will return an X**, not an X*.
>
> If you try ptr->x, the compiler will call ptr.operator -> () and
> then try to apply the inbult (X**)->x, however there is no such
> operator, inbult opertor -> *only* applies to pointers to struct's (*)
> and X** is a pointer to a pointer not a pointer to a struct.
>
> *) by 'struct' I mean aggragate i.e, struct, class or union.
>
> So the Gotcha would be "there is no inbuilt operator -> for T**".[/color]

So this is to say if I had:

std::vector< boost::shared_ptr<X> >::iterator it;
it->x = 3;

would compile properly?

I think I get it. I was reading previous information on this
topic to suggest that there *was* a built-in operator-> that was
triggered that would "do what you expect," although now that I
think about it it seems obviously wrong since you wouldn't (?)
want:

X** x;
x->x = 5;

to compile.

thanks-
-tom!
Rob Williscroft
Guest
 
Posts: n/a
#7: Jul 22 '05

re: Overloading -> and ->*


Tom Plunket wrote in news:mpj440tgnbje77gti7nhc44oa3gm3rn58b@4ax.com:
[color=blue]
> Rob Williscroft wrote:
>[/color]
[snip][color=blue][color=green]
>>
>> So the Gotcha would be "there is no inbuilt operator -> for T**".[/color]
>
> So this is to say if I had:
>
> std::vector< boost::shared_ptr<X> >::iterator it;
> it->x = 3;
>
> would compile properly?
>[/color]

Alas it doesen't, it.operator ->() returns a boost::shared_ptr<X> *.

it->x would work if the return value was shared_ptr<X> &, but
then std::vector's of simple structs wouldn't work.

Also you couldn't do: it->unique() (*).

*) For those that don't know, unique() is a member of shared_ptr<>:

http://www.boost.org/libs/smart_ptr/shared_ptr.htm.
[color=blue]
> I think I get it. I was reading previous information on this
> topic to suggest that there *was* a built-in operator-> that was
> triggered that would "do what you expect," although now that I
> think about it it seems obviously wrong since you wouldn't (?)
> want:
>
> X** x;
> x->x = 5;
>
> to compile.
>[/color]

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Tom Plunket
Guest
 
Posts: n/a
#8: Jul 22 '05

re: Overloading -> and ->*


Rob Williscroft wrote:
[color=blue][color=green]
> > So this is to say if I had:
> >
> > std::vector< boost::shared_ptr<X> >::iterator it;
> > it->x = 3;
> >
> > would compile properly?
> >[/color]
>
> Alas it doesen't, it.operator ->() returns a boost::shared_ptr<X> *.[/color]

Oh...

I fail to see now, then, where this operator-> does this bouncing
then... When does it, when can it, come up?


-tom!
Rob Williscroft
Guest
 
Posts: n/a
#9: Jul 22 '05

re: Overloading -> and ->*


Tom Plunket wrote in news:sqj5405gh69d4p18lv3r1t6tc7bnvbci9m@4ax.com:
[color=blue]
> Rob Williscroft wrote:
>[color=green][color=darkred]
>> > So this is to say if I had:
>> >
>> > std::vector< boost::shared_ptr<X> >::iterator it;
>> > it->x = 3;
>> >
>> > would compile properly?
>> >[/color]
>>
>> Alas it doesen't, it.operator ->() returns a boost::shared_ptr<X> *.[/color]
>
> Oh...
>
> I fail to see now, then, where this operator-> does this bouncing
> then... When does it, when can it, come up?
>[/color]

#include <iostream>
#include <ostream>

using std::cerr;

//Simple case

struct X
{
int data;
};

struct Y
{
X *xp;
X *operator -> () { return xp; }
};

void simple_example()
{
X x = { 0 };
Y y = { &x };
y->data = 1;

cerr << x.data << '\n';
}

/* y->data calls y.operator ->() which returns X*,
compiler uses inbuilt operator ->.
*/

//Complex case:

struct Z
{
Y array[2];
bool b;

/* Note: operator -> () returns a reference not a pointer
*/
Y & operator -> () { return array[b]; }
};

void complex_example()
{
X x1 = { 0 }, x2 = { 0 };
Z z = { { &x1, &x2 }, false };

z->data = 1;
z.b = true;
z->data = 2;
cerr << x1.data << '\n';
cerr << x2.data << '\n';
}

/* z->data calls x.operator -> () which returns Y &,
compiler calls Y::operator -> (), which returns X *,
compiler uses inbuilt operator ->.
*/


int main()
{
simple_example();
complex_example();
}

In short bouncing as you call it continues until a user defined
operator -> () returns a pointer, and then the language's inbuilt
rules are applied.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Closed Thread


Similar C / C++ bytes