What Stanley means by "recursive" is that the statement applies to each returned object until the return type is a pointer.
What happens here on the first try: screen::operator -> returns a pointer. So this is the last call to operator -> that the compiler is trying to execute. Then it resolves the right elements of the operator ( p ) by searching for a member in the return type of the point ( dummy ) with that name.
Essentially, whenever the compiler finds the syntax aᵢ->b in the code, it essentially applies the following algorithm:
- Is
aᵢ pointer type? If so, enable the b *aᵢ element and call (*aᵢ).b . - Try again
aᵢ::operator ->- If successful, set
aᵢ₊₁ = aᵢ::operator ->() . Go to 1. - On failure, we emit a compilation error.
It’s hard for me to come up with a short, meaningful example when a chain from 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 gives a number. But I would not really recommend writing such code. This destroys 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"; }
Konrad Rudolph
source share