Давайте разберем по шагам.
int main() {
Box b;
b->hi();
}
Что тут происходит? Мы создаем объект типа
Box, иииии... вызываем у него оператор ->, а у того, что он вернет вызывает функцию hi(). Логично? Логично! Смотрим, что такое у нас тип
Box.
struct Box {
Proxy operator->() {
return {};
}
};
Ага, значит оператор выдает экземпляр объекта типа Proxy, и вот у него вызывается функция
hi(). Логично? Логично. Смотрим, что такое структура
Proxy.
struct Proxy {
Leaf* operator->() {
static Leaf x;
return &x;
}
};
В структуре Proxy функции
hi() нет. Ошибка компиляции. Логично? А хрен там плавал. Уберите детей от мониторов.
Вот этот код компилируется и выводит
ok
#include <iostream>
struct Leaf {
void hi() { std::cout << "ok"; }
};
struct Proxy {
Leaf* operator->() {
static Leaf x;
return &x;
}
};
struct Box {
Proxy operator->() {
return {};
}
};
int main() {
Box b;
b->hi();
}
Итак.
У нас С++ разворачивает оператор
-> до самого конца. Например сработает даже вот это:
#include <iostream>
struct Leaf {
void hi() { std::cout << "ok"; }
};
struct Proxy4 {
Leaf* operator->() {
static Leaf x;
return &x;
}
};
struct Proxy3 {
Proxy4 operator->() {
return {};
}
};
struct Proxy2 {
Proxy3 operator->() {
return {};
}
};
struct Proxy {
Proxy2 operator->() {
return {};
}
};
struct Box {
Proxy operator->() {
return {};
}
};
int main() {
Box b;
b->hi();
}
Я вот хочу куда-нибудь в шаблонный код загнать, пранкануть, таксказать, коллег.