From 89831bfa86ca0975124ab6ff3c1ffa78d0efccb3 Mon Sep 17 00:00:00 2001 From: Simon Brand Date: Fri, 27 Oct 2017 12:16:31 +0100 Subject: [PATCH] First go at map_error --- expected.hpp | 96 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 4 deletions(-) diff --git a/expected.hpp b/expected.hpp index e5f75d0..f672b68 100644 --- a/expected.hpp +++ b/expected.hpp @@ -432,7 +432,7 @@ public: typedef E error_type; typedef unexpected unexpected_type; -#ifdef TL_EXPECTED_CXX14 +#ifdef TL_EXPECTED_CXX14 /// \group and_then /// Carries out some operation which returns an optional on the stored object /// if there is one. \requires `std::invoke(std::forward(f), value())` @@ -516,7 +516,7 @@ public: "F must return an expected"); return has_value() ? detail::invoke(std::forward(f), **this) - : result(unexpect, std::move(this->error())); + : result(unexpect, std::move(this->error())); } /// \group and_then @@ -528,7 +528,7 @@ public: "F must return an expected"); return has_value() ? detail::invoke(std::forward(f), **this) - : result(unexpect, this->error()); + : result(unexpect, this->error()); } #ifndef TL_EXPECTED_NO_CONSTRR @@ -541,8 +541,9 @@ public: "F must return an expected"); return has_value() ? detail::invoke(std::forward(f), **this) - : result(unexpect, std::move(this->error())); + : result(unexpect, std::move(this->error())); } +#endif #endif #ifdef TL_EXPECTED_CXX14 @@ -603,6 +604,68 @@ public: return map_impl(std::move(*this), std::forward(f)); } #endif +#endif + +#ifdef TL_EXPECTED_CXX14 + /// \brief Carries out some operation on the stored object if there is one. + /// \returns Let `U` be the result of `std::invoke(std::forward(f), + /// value())`. Returns a `std::expected`. The return value is empty if + /// `*this` is empty, otherwise an `expected` is constructed from the + /// return value of `std::invoke(std::forward(f), value())` and is + /// returned. \group map_error \synopsis template auto map_error(F + /// &&f) &; + template TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) & { + return map_error_impl(*this, std::forward(f)); + } + + template TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) && { + return map_error_impl(std::move(*this), std::forward(f)); + } + + template constexpr auto map_error(F &&f) const & { + return map_error_impl(*this, std::forward(f)); + } + + template constexpr auto map_error(F &&f) const && { + return map_error_impl(std::move(*this), std::forward(f)); + } +#else + /// \brief Carries out some operation on the stored object if there is one. + /// \returns Let `U` be the result of `std::invoke(std::forward(f), + /// value())`. Returns a `std::expected`. The return value is empty if + /// `*this` is empty, otherwise an `expected` is constructed from the + /// return value of `std::invoke(std::forward(f), value())` and is + /// returned. \group map_error \synopsis template auto map_error(F + /// &&f) &; + template + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) & { + return map_error_impl(*this, std::forward(f)); + } + + template + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) && { + return map_error_impl(std::move(*this), std::forward(f)); + } + + template + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) const & { + return map_error_impl(*this, std::forward(f)); + } + +#ifndef TL_EXPECTED_NO_CONSTRR + template + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) const && { + return map_error_impl(std::move(*this), std::forward(f)); + } +#endif #endif constexpr expected() = default; @@ -868,6 +931,31 @@ private: return unexpected>(std::forward(exp).error()); } #endif + +#ifdef TL_EXPECTED_CXX14 + template (), + *std::declval()))> + static constexpr auto map_error_impl(Exp &&exp, F &&f) { + using result = ret_t; + return exp.has_value() + ? result(*std::forward(exp)) + : result(unexpect, + detail::invoke(std::forward(f), + std::forward(exp).error())); + } +#else + template (), + *std::declval()))> + static constexpr auto map_error_impl(Exp &&exp, F &&f) -> ret_t { + using result = ret_t; + + return exp.has_value() ? result(detail::invoke(std::forward(f), + *std::forward(exp))) + : result(unexpect, std::forward(exp).error()); + } +#endif }; // TODO