It seems, that there are many situations with the following pattern:
- there is a type
- that defines some invalid state (in case of iterator the state is "being equal to end()", in case of Result/Outcome/Expected the state is "representing an error", in case of optional it is "nullopt", and so on...)
- attempts of using which in the invalid state are supposed to "return" (from the scope where it is used). We can take a step back and consider other control-flow statements.
Without going into implementation details, what do you think about the idea (on a conceptual level) of being able to describe this pattern somewhere somehow?
If conceptually it is fine, then what do you think about implementing the idea by creating another flavour of return statements that can return not only from its own scope, but also from outer/parent scope?
If you wish, this new flavour can be viewed as a middle ground between (1) regular return's (which often requires boilerplate for handling the pattern above) and (2) exceptions (which are too non-local and implicit and can "jump" at an arbitrary place).
The code above would look like this:
std::optional<std::string> FindUsersCity() {
std::optional<ContactsServer> contacts = GetOrOpenContactsServerConnection();
std::optional<UserId> uid = contacts.GetOrReturnNullOpt()->GetUserId();
std::optional<GeoServer> geo = GetOrOpenGeoServerConnection();
std::optional<Location> uloc = geo.GetOrReturnNullOpt()->GetLocation(*uid);
return uloc.GetOrReturnNullOpt()->GetCityName();
}where
GetOrReturnNullOpt() is a method that (1) either returns a value if std::optional is not empty, (2) or returns from
FindUsersCity() if std::optional is empty.
I think it could solve
- Initial problem mentioned in "Initialisers in ternary operators": we could have something like this: return Cont.find(42).GetOrReturn(0).
- The problem of using optional without boilerplate (see above).
- The problem of Error-handling via Result<> without boilerplate, which has been a constant source of pain and complaints and holy wars between exceptions and return-values for error handling.
- It also eliminates one more reason to exist for macros (that is how people are solving it right now: 1, 2).