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