At the moment, an overloaded operator->() eventually resolves to a pointer of arbitrary type, before calling some method or accessing a data member from the type of that pointer.
class SmartPointer {
public:
Pointee* operator->();
};
SmartPointer s;
s->f(); // Resolves to a Pointee* p, then calls Pointee::*f(p).
Important detail: If the return type of `SmartPointer::operator->()` is not a native pointer type, then the compiler will generate a call to that type's operator->(), and so on forever or until a native pointer type is finally reached.
I would like to change this, so that instead of immediately calling Pointee::*f(p), we look for a method in the current class scope and if found, call that instead:
class SmartPointer {
public:
Pointee* operator->();
template<typename R, typename... Args>
T operator->(Pointee* p, R (Pointee::*f)(Args...));
};
SmartPointer s;
s->f(); // Resolves to s.operator-><Pointee>(s->operator(), &Pointee::f);
Minor problem #1: What's the purpose of calling the zero-argument `operator->()` here? Shouldn't this example be more like
struct SP {
T *ptr_;
template<class R, class... As>
R operator->(R (T::*pm)(As...));
};
?
Major problem #2: What if `Pointee::f` has multiple overloads?
Major major problem #3: Show me the implementation of `operator->` above.
struct SP {
T *ptr_;
template<class R, class... As>
R operator->(R (T::*pm)(As...)) {
return (ptr_->*pm)(args...); // wait, where the heck did these `args...` appear from? How did we get them?
}
};
Major problem #4: What if `Pointee::f` is a data member, or pseudo-destructor, or any of the other kinds of things that are allowed to appear on the right-hand side of an `->` operator?
Minor problem #5: Couldn't you achieve your stated goal more easily by just making your optional's `operator->` return a proxy object?
Are you familiar with the "arrow proxy" idiom?
I think you need some kind of proxy no matter what. You certainly don't want `x->y()` to behave subtly differently from `(*x).y()`. So any solution you come up with must work uniformly for both `operator->` and `operator*`.
I suggest you read about arrow_proxy, then see if it completely solves your problem, and if not, then come back with a worked example — a complete program, with a unit test that "fails now, but would pass if my fantasy feature existed." Show the code you'd write using your fantasy feature that would make the test pass. Then, people can either show different ways to make it pass within today's language, or perhaps they might say "oh yeah, I see how that would be useful."
HTH,
–Arthur