13

Possible Duplicate:
Overloading operator ->

Hi,

I've seen that operator->() is chained (re-applied) after it is evaluated, for example:

struct Bar
{
  Bar() : m_str("Hello world!") {}
  const string* operator->() const { return &m_str; }
  string m_str;
};

struct Foo
{
  const Bar& operator->() const { return m_bar; }
  Bar m_bar;
};

int main()
{
  Foo f;
  cout << f->c_str() << endl;
  return 0;
}

works pretty fine, which requires three operator->() to be evaluated - Foo::operator->(), Bar::operator->() and regular pointer resolution.

But it wont work with pointers in the middle - if Foo::operator->() returns pointer to Bar instead of reference, it wont compile. Same happens with auto_ptr<auto_ptr<string>> for example.

Is it specific to non-overloaded operator->() so it is only applied once and does not cause chaining? Is it possible to make code below works without using (*ptr2)-> ...?

int main()
{
  string s = "Hello world";
  auto_ptr<string> ptr1(&s);
  auto_ptr<auto_ptr<string> > ptr2(&ptr1);
  cout << ptr1->c_str() << endl; // fine
  cout << ptr2->c_str() << endl; // breaks compilation
}

Thanks!

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
nyrl
  • 769
  • 5
  • 15
  • Duplicate of [Overloading operator ->](http://stackoverflow.com/questions/4896238/overloading-operator) [AndreyT's answer explains the behavior of `operator->` and how the "chaining" occurs.] – James McNellis Feb 07 '11 at 15:48
  • 1
    @James I'd favor keeping this open since the wording of the question is different. It may help other people find that answer. – Judge Maygarden Feb 07 '11 at 15:52
  • 2
    @Judge: A closed question isn't automatically deleted, and a well-asked question like this one won't be deleted; the question will still exist and be searchable. – James McNellis Feb 07 '11 at 15:55
  • Thanks! And then it does not seems to be possible to override operator-> for pointer, so nothing can be done with second question. Right? – nyrl Feb 07 '11 at 15:56
  • 1
    It should be note that using `auto_ptr` this way will cause all kinds of horrible things to happen when the variables are destroyed at the end of the function. – sth Feb 07 '11 at 16:01

3 Answers3

24

C++98 standard §13.5.6/1 "Class member access":

An expression x->m is interpreted as (x.operator->())->m for a class object x of type T if T::operator-> exists and if the operator is selected at the best match function by the overload resolution mechanism (13.3).

What this means in practice is that when x is a pointer, you don’t get chaining; you then just get the built-in operator-> (i.e. x->m with x a pointer translates to (*x).m).

But when x is an object of class type T, then you can get the chaining effect. Because then the interpretation as (x.operator->())->m can be that (x.operator->()) itself is an object of some class, say class U. Whence the second -> can be resolved as U::operator->, and so on, if the result of that again is a class type object…

Like, in your case, Foo::operator-> produces (a reference to) an object of class Bar, which does define an operator->.

But when operator-> returns a pointer, as e.g. std::auto_ptr<T>::operator-> does, then it's just the built-in operator-> that's used.

In passing, the chaining can be used to practically prevent someone from using delete inappropriately. std::auto_ptr does not do that. And I’ve never seen it done.

But there was once a long discussion thread over in [comp.lang.c++.moderated] about how to prevent inadvertent delete of the raw pointer managed by a smart pointer, and this was one possibility that was discussed.

Cheers & hth.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
3

The reason your first example works is because you returned a reference instead of a pointer. That operator would normally be invalid except in the case that it is overloaded. Therefore, the compiler must execute the overloaded functions down the chain. However, in the case of auto_ptr you actually are returned a real pointer and the default operator -> is invoked for regular pointers.

Please see the Overloading operator -> question for more details.

Community
  • 1
  • 1
Judge Maygarden
  • 26,961
  • 9
  • 82
  • 99
  • Thank you for answer. I was looking for approach to simplify code for iterating vector > and similar stuff. Seems that the only option is to specialize vector's (any container) iterator for shared_ptr (some other smart ptrs), which is not acceptable. – nyrl Feb 07 '11 at 16:13
0

No, it is not possible for it to work. If you could overload operator -> for string * you could make it work. But operator -> already has a definition for all pointer types. So, just like you can't overload + for primitive numeric types, you can't overload operator -> for any pointer type.

And even if you could, how could the compiler know when the recursion should end?

Omnifarious
  • 54,333
  • 19
  • 131
  • 194