Bary's proposal I will study carefully, but here is mine completely different one

 template<typename T> struct valstat final {
        T* value;
        std::errc status;
    };
    valstat<const char> FindUsersCity() noexcept
    {
        if (auto [contacts, errc] = GetOrOpenContactsServerConnection(); contacts)
        {
            if (auto [uid, errc] = contacts->GetUserId(); uid) {
                if (auto [geo, errc] = GetOrOpenGeoServerConnection(); geo) {
                    if (auto [uloc, errc] = geo->GetLocation(uid); uloc) {
                        return uloc->GetCityName();
                    }
                    else {
                        return { {}, errc };
                    }
                }
                else {
                    return { {}, errc };
                }
            }
            else {
                return { {}, errc };
            }
        }
        else {
            return { {}, errc };
        }
    }

No Result, Expected, Outcome, no exceptions and no std lib either…

auto [city_name, errc] = FindUsersCity();


On Mon, 14 Sep 2020 at 21:20, Dmitry Dmitry via Std-Proposals <std-proposals@lists.isocpp.org> wrote:

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
--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals