However, what you want is already possible in Standard C++:

std::optional<std::string> FindUsersCity() {
    try {
        std::optional<ContactsServer> contacts = GetOrOpenContactsServerConnection();
        std::optional<UserId> uid = contacts.value().GetUserId();  // throw bad_optional_access on empty
        std::optional<GeoServer> geo = GetOrOpenGeoServerConnection();
        std::optional<Location> uloc = geo.value().GetLocation(uid.value());  // throw bad_optional_access on empty
        return uloc.value().GetCityName();
    } catch (const std::bad_optional_access&) {
        return std::nullopt;
    }
}

 
If you want the same level of flexibility as with returns (and you usually want, because sometimes you need to be more specific and capture some context/explanation), then it would be: 
Result<int, std::string> FindUsersCity() {
    std::optional<ContactsServer> contacts = GetOrOpenContactsServerConnection();
    std::optional<UserId> uid;
    try {
        uid = contacts.value().GetUserId();  // throw bad_optional_access on empty
    } catch (const std::bad_optional_access&) {
        return failure("failed to get GetOrOpenContactsServerConnection: details: " + ...)
    }
    std::optional<GeoServer> geo = GetOrOpenGeoServerConnection();
    try {
        std::optional<Location> uloc = geo.value().GetLocation(uid.value());  // throw bad_optional_access on empty
    } catch (const std::bad_optional_access&) {
        return failure("failed to get GetOrOpenGeoServerConnection: details: " + ...)
    }
    try {
        return uloc.value().GetCityName();
    } catch (const std::bad_optional_access&) {
        return failure("failed to get GetLocation of: " + ...)
    }
}

--
Dmitry
Sent from gmail