Hi all,

Had an idea for a language feature that I'd like to float.

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).

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);

The motivation here is to allow something that looks very like a monad. This secondary overload would provide the bind functionality of the monad, composing the member function of the other class into the monadic context.

The real-life example that motivated this is the clunkiness of return types in a serialization structure (Thrift structs, to be exact). At present, if a Thrift field is marked optional, the accessor method returns an optional reference wrapper for the type of that field. When there is a hierarchy of optional fields, this tends to lead to code that looks like:
  if (c.field1_ref().has_value() &&
       c.field1_ref()->field2_ref().has_value() && 
       c.field1_ref()->field2_ref()->field3_ref().has_value() {
    ... do something with c.field1_ref()->field2_ref()->field3_ref().value() ...
  }
Each level of the hierarchy has to be checked before moving onto the next, or the expression will throw when a field is not present.

The above overload would allow the reference wrapper to recursively wrap the return types of the child methods in an optional reference wrapper, making a call to:
    c.field1_ref()->field2_ref()->field3_ref().has_value()
safe regardless of whether the fields are missing or not.

This would also allow other functionality that wants to intercept and potentially redirect smart pointer function calls like:
* calling the method on a different thread
* calling the method on a different machine over RPC
* logging function call statistics
* experimental diversions on new code being tested