diff --git a/expected.hpp b/expected.hpp index 5430e0d..7bc2508 100644 --- a/expected.hpp +++ b/expected.hpp @@ -1138,11 +1138,35 @@ public: #endif #endif + /// \brief Calls `f` if the expectd is in the unexpected state + /// \requires `std::invoke_result_t` must be void or convertible to + /// `expcted`. + /// \effects If `*this` has a value, returns `*this`. + /// Otherwise, if `f` returns `void`, calls `std::forward(f)` and returns + /// `std::nullopt`. Otherwise, returns `std::forward(f)()`. + /// + /// \group or_else + template expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) & { + return or_else_impl(*this, std::forward(f)); + } + + template expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) && { + return or_else_impl(std::move(*this), std::forward(f)); + } + + template expected constexpr or_else(F &&f) const & { + return or_else_impl(*this, std::forward(f)); + } + + template expected constexpr or_else(F &&f) const && { + return or_else_impl(std::move(*this), std::forward(f)); + } + constexpr expected() = default; constexpr expected(const expected &rhs) = default; constexpr expected(expected &&rhs) = default; - expected &operator=(const expected &rhs) = default; - expected &operator=(expected &&rhs) = default; + expected &operator=(const expected &rhs) = default; + expected &operator=(expected &&rhs) = default; template ::value> * = @@ -1592,6 +1616,31 @@ constexpr auto map_error_impl(Exp &&exp, F &&f) -> ret_t { } #endif +template (), + *std::declval())), + detail::enable_if_t::value> * = nullptr> +constexpr detail::decay_t or_else_impl(Exp &&exp, F &&f) { + if (exp.has_value()) { + return std::forward(exp); + } + + return detail::invoke(std::forward(f), *std::forward(exp)); +} + +template (), + *std::declval())), + detail::enable_if_t::value> * = nullptr> +detail::decay_t or_else_impl(Exp &&exp, F &&f) { + if (exp.has_value()) { + return std::forward(exp); + } + + detail::invoke(std::forward(f), *std::forward(exp)); + return std::forward(exp); +} + } // namespace detail template