It is said that the arrow operator is applied recursively. But when I try to execute the following code, it prints gibberish when it is supposed to print 4.
class dummy
{
public:
int *p;
int operator->()
{
return 4;
}
};
class screen
{
public:
dummy *p;
screen(dummy *pp): p(pp){}
dummy* operator->()
{
return p;
}
};
int main()
{
dummy *d = new dummy;
screen s(d);
cout<<s->p;
delete d;
}
What Stanley meant by “recursive” is just that the operator is applied to every returned object until the returned type is a pointer.
Which happens here on the first try: screen::operator ->
returns a pointer. Thus this is the last call to an operator ->
that the compiler attempts. It then resolves the right-hand sice of the operator (p
) by looking up a member in the returned pointee type (dummy
) with that name.
Essentially, whenever the compiler finds the syntax aᵢ->b
in code, it essentially applies the following algorithm:
aᵢ
of pointer type? If so, resolve member b
of *aᵢ
and call (*aᵢ).b
.aᵢ::operator ->
aᵢ₊₁ = aᵢ::operator ->()
. Goto 1.I’m hard-pressed to come up with a short, meaningful example where a chain of operator ->
invocations even makes sense. Probably the only real use is when you write a smart pointer class.
However, the following toy example at least compiles and yields a number. But I wouldn’t advise actually writing such code. It breaks encapsulation and makes kittens cry.
#include <iostream>
struct size {
int width;
int height;
size() : width(640), height(480) { }
};
struct metrics {
size s;
size const* operator ->() const {
return &s;
}
};
struct screen {
metrics m;
metrics operator ->() const {
return m;
}
};
int main() {
screen s;
std::cout << s->width << "\n";
}
C++ Primer (5th edition) formulates it as follows on page 570:
The arrow operator never loses its fundamental meaning of member access. When we overload arrow, we change the object from which arrow fetches the specified member. We cannot change the fact that arrow fetches a member.
The deal is once screen::operator->()
returns a pointer (dummy*
) the recursion stops because built-in (default) ->
in used on that pointer. If you want recursion you should return dummy
or dummy&
from screen::operator->()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With