diff --git a/optional.hpp b/optional.hpp index 45413bc..f90b3c9 100644 --- a/optional.hpp +++ b/optional.hpp @@ -87,9 +87,8 @@ constexpr auto invoke(Fn &&f, Args &&... args) noexcept( return std::mem_fn(f)(std::forward(args)...); } -template < - typename Fn, typename... Args, - enable_if_t>{}, int> = 0> +template >{}, int> = 0> constexpr auto invoke(Fn &&f, Args &&... args) noexcept( noexcept(std::forward(f)(std::forward(args)...))) -> decltype(std::forward(f)(std::forward(args)...)) { @@ -118,7 +117,8 @@ template struct get_invoke_optional_ret { using type = invoke_result_t< conditional_t::value, typename remove_reference_t::value_type &, - typename remove_reference_t::value_type &&>, U>; + typename remove_reference_t::value_type &&>, + U>; }; template @@ -711,10 +711,14 @@ public: constexpr const T *operator->() const { return std::addressof(this->m_value); } - TL_OPTIONAL_11_CONSTEXPR T *operator->() { return std::addressof(this->m_value); } + TL_OPTIONAL_11_CONSTEXPR T *operator->() { + return std::addressof(this->m_value); + } constexpr const T &operator*() const & { return this->m_value; } TL_OPTIONAL_11_CONSTEXPR T &operator*() & { return this->m_value; } - TL_OPTIONAL_11_CONSTEXPR T &&operator*() && { return std::move(this->m_value); } + TL_OPTIONAL_11_CONSTEXPR T &&operator*() && { + return std::move(this->m_value); + } constexpr const T &&operator*() const && { return std::move(this->m_value); } constexpr explicit operator bool() const noexcept { return this->m_has_value; @@ -761,20 +765,24 @@ public: } } - template TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t bind(F &&f) & { + template + TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t bind(F &&f) & { using result = detail::invoke_result_t; static_assert(detail::is_optional::value, "F must return an optional"); - return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); + return has_value() ? detail::invoke(std::forward(f), **this) + : result(nullopt); } - template TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t bind(F &&f) && { + template + TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t bind(F &&f) && { using result = detail::invoke_result_t; static_assert(detail::is_optional::value, "F must return an optional"); - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : result(nullopt); + return has_value() ? detail::invoke(std::forward(f), std::move(**this)) + : result(nullopt); } template @@ -783,7 +791,8 @@ public: static_assert(detail::is_optional::value, "F must return an optional"); - return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); + return has_value() ? detail::invoke(std::forward(f), **this) + : result(nullopt); } template @@ -792,11 +801,15 @@ public: static_assert(detail::is_optional::value, "F must return an optional"); - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : result(nullopt); + return has_value() ? detail::invoke(std::forward(f), std::move(**this)) + : result(nullopt); } template - detail::invoke_result_t bind(F &&f, E &&e) & { + detail::invoke_result_t bind(F &&f, E &&e) & + noexcept(noexcept(detail::invoke(std::forward(f), + std::declval())) && + noexcept(std::forward(e)())) { using result = detail::invoke_result_t; static_assert(detail::is_optional::value, "F must return an optional"); @@ -811,7 +824,7 @@ public: } template - detail::invoke_result_t bind(F &&f, E &&e) && { + detail::invoke_result_t bind(F &&f, E &&e) && { using result = detail::invoke_result_t; static_assert(detail::is_optional::value, "F must return an optional"); @@ -857,16 +870,17 @@ public: template * = nullptr, detail::disable_if_ret_void * = nullptr> - detail::get_map_return map(F &&f) & { - using result = detail::get_map_return; - return has_value() ? - detail::invoke(std::forward(f), **this) : - result(nullopt); + detail::get_map_return map(F &&f) & + noexcept(noexcept(detail::invoke(std::forward(f), + std::declval()))) { + using result = detail::get_map_return; + return has_value() ? detail::invoke(std::forward(f), **this) + : result(nullopt); } template * = nullptr, detail::enable_if_ret_void * = nullptr> - detail::get_map_return map(F &&f) & { + detail::get_map_return map(F &&f) & { if (!has_value()) return nullopt; @@ -876,16 +890,16 @@ public: template * = nullptr, detail::disable_if_ret_void * = nullptr> - detail::get_map_return map(F &&f) & { - using result = detail::get_map_return; - return (f.has_value() && has_value()) ? - detail::invoke(*std::forward(f), **this) : - result(nullopt); + detail::get_map_return map(F &&f) & { + using result = detail::get_map_return; + return (f.has_value() && has_value()) + ? detail::invoke(*std::forward(f), **this) + : result(nullopt); } template * = nullptr, detail::enable_if_ret_void * = nullptr> - detail::get_map_return map(F &&f) & { + detail::get_map_return map(F &&f) & { if (!f.has_value() || !has_value()) return nullopt; @@ -896,15 +910,14 @@ public: template * = nullptr, detail::disable_if_ret_void * = nullptr> detail::get_map_return map(F &&f) && { - using result = detail::get_map_return; - return has_value() ? - detail::invoke(std::forward(f), std::move(**this)) : - result(nullopt); + using result = detail::get_map_return; + return has_value() ? detail::invoke(std::forward(f), std::move(**this)) + : result(nullopt); } template * = nullptr, detail::enable_if_ret_void * = nullptr> - detail::get_map_return map(F &&f) && { + detail::get_map_return map(F &&f) && { if (!has_value()) return nullopt; @@ -914,16 +927,16 @@ public: template * = nullptr, detail::disable_if_ret_void * = nullptr> - detail::get_map_return map(F &&f) && { - using result = detail::get_map_return; - return (f.has_value() && has_value()) ? - detail::invoke(*std::forward(f), std::move(**this)) : - result(nullopt); + detail::get_map_return map(F &&f) && { + using result = detail::get_map_return; + return (f.has_value() && has_value()) + ? detail::invoke(*std::forward(f), std::move(**this)) + : result(nullopt); } template * = nullptr, detail::enable_if_ret_void * = nullptr> - detail::get_map_return map(F &&f) && { + detail::get_map_return map(F &&f) && { if (!f.has_value() || !has_value()) return nullopt; @@ -934,13 +947,15 @@ public: template * = nullptr, detail::disable_if_ret_void * = nullptr> constexpr detail::get_map_return map(F &&f) const & { - using result = detail::get_map_return; - return this->has_value() ? result(detail::invoke(std::forward(f), **this)) : result(nullopt); + using result = detail::get_map_return; + return this->has_value() + ? result(detail::invoke(std::forward(f), **this)) + : result(nullopt); } template * = nullptr, detail::enable_if_ret_void * = nullptr> - detail::get_map_return map(F &&f) const & { + detail::get_map_return map(F &&f) const & { if (!has_value()) return nullopt; @@ -951,10 +966,10 @@ public: template * = nullptr, detail::disable_if_ret_void * = nullptr> constexpr detail::get_map_return map(F &&f) const & { - using result = detail::get_map_return; - return (f.has_value() && has_value()) ? - detail::invoke(*std::forward(f), **this) : - result(nullopt); + using result = detail::get_map_return; + return (f.has_value() && has_value()) + ? detail::invoke(*std::forward(f), **this) + : result(nullopt); } template * = nullptr, @@ -970,15 +985,14 @@ public: template * = nullptr, detail::disable_if_ret_void * = nullptr> constexpr detail::get_map_return map(F &&f) const && { - using result = detail::get_map_return; - return has_value() ? - detail::invoke(std::forward(f), std::move(**this)) : - result(nullopt); + using result = detail::get_map_return; + return has_value() ? detail::invoke(std::forward(f), std::move(**this)) + : result(nullopt); } template * = nullptr, detail::enable_if_ret_void * = nullptr> - detail::get_map_return map(F &&f) const && { + detail::get_map_return map(F &&f) const && { if (!has_value()) return nullopt; @@ -989,22 +1003,62 @@ public: template * = nullptr, detail::disable_if_ret_void * = nullptr> constexpr detail::get_map_return map(F &&f) const && { - using result = detail::get_map_return; - return (f.has_value() && has_value()) ? - detail::invoke(*std::forward(f), std::move(**this)) : - result(nullopt); + using result = detail::get_map_return; + return (f.has_value() && has_value()) + ? detail::invoke(*std::forward(f), std::move(**this)) + : result(nullopt); } template * = nullptr, detail::enable_if_ret_void * = nullptr> - detail::get_map_return map(F &&f) const && { + detail::get_map_return map(F &&f) const && { if (!f.has_value() || !has_value()) return nullopt; detail::invoke(*std::forward(f), std::move(**this)); return monostate{}; } + + template U map_or(F &&f, U &&u) & { + return has_value() ? detail::invoke(std::forward(f), **this) + : std::forward(u); + } + + template U map_or(F &&f, U &&u) && { + return has_value() ? detail::invoke(std::forward(f), std::move(**this)) + : std::forward(u); + } + + template U map_or(F &&f, U &&u) const & { + return has_value() ? detail::invoke(std::forward(f), **this) + : std::forward(u); + } + + template U map_or(F &&f, U &&u) const && { + return has_value() ? detail::invoke(std::forward(f), std::move(**this)) + : std::forward(u); + } + + template U map_or_else(F &&f, U &&u) & { + return has_value() ? detail::invoke(std::forward(f), **this) + : std::forward(u)(); + } + + template U map_or_else(F &&f, U &&u) && { + return has_value() ? detail::invoke(std::forward(f), std::move(**this)) + : std::forward(u)(); + } + + template U map_or_else(F &&f, U &&u) const & { + return has_value() ? detail::invoke(std::forward(f), **this) + : std::forward(u)(); + } + + template U map_or_else(F &&f, U &&u) const && { + return has_value() ? detail::invoke(std::forward(f), std::move(**this)) + : std::forward(u)(); + } }; -//template optional(T)->optional; +// template optional(T)->optional; }