diff --git a/tests/issues.cpp b/tests/issues.cpp index c3efa44..db42783 100644 --- a/tests/issues.cpp +++ b/tests/issues.cpp @@ -73,3 +73,10 @@ TEST_CASE("Issue 31", "[issues.31]") { tl::expected< void, std::string > result2 = result; result2 = result; } + +TEST_CASE("Issue 33", "[issues.33]") { + tl::expected res {tl::unexpect, 0}; + REQUIRE(!res); + res = res.map_error([](auto i) { return 42; }); + REQUIRE(res.error() == 42); +} diff --git a/tl/expected.hpp b/tl/expected.hpp index c48cb38..71329f2 100644 --- a/tl/expected.hpp +++ b/tl/expected.hpp @@ -2053,6 +2053,7 @@ auto expected_map_impl(Exp &&exp, F &&f) -> expected> { #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) template >::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), detail::enable_if_t::value> * = nullptr> @@ -2064,6 +2065,7 @@ constexpr auto map_error_impl(Exp &&exp, F &&f) { std::forward(exp).error())); } template >::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), detail::enable_if_t::value> * = nullptr> @@ -2076,8 +2078,35 @@ auto map_error_impl(Exp &&exp, F &&f) { detail::invoke(std::forward(f), std::forward(exp).error()); return result(unexpect, monostate{}); } +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +constexpr auto map_error_impl(Exp &&exp, F &&f) { + using result = expected, detail::decay_t>; + return exp.has_value() + ? result() + : result(unexpect, detail::invoke(std::forward(f), + std::forward(exp).error())); +} +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +auto map_error_impl(Exp &&exp, F &&f) { + using result = expected, monostate>; + if (exp.has_value()) { + return result(); + } + + detail::invoke(std::forward(f), std::forward(exp).error()); + return result(unexpect, monostate{}); +} #else template >::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), detail::enable_if_t::value> * = nullptr> @@ -2092,6 +2121,7 @@ constexpr auto map_error_impl(Exp &&exp, F &&f) } template >::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), detail::enable_if_t::value> * = nullptr> @@ -2104,6 +2134,36 @@ auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { detail::invoke(std::forward(f), std::forward(exp).error()); return result(unexpect, monostate{}); } + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +constexpr auto map_error_impl(Exp &&exp, F &&f) + -> expected, detail::decay_t> { + using result = expected, detail::decay_t>; + + return exp.has_value() + ? result() + : result(unexpect, detail::invoke(std::forward(f), + std::forward(exp).error())); +} + +template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> +auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { + using result = expected, monostate>; + if (exp.has_value()) { + return result(); + } + + detail::invoke(std::forward(f), std::forward(exp).error()); + return result(unexpect, monostate{}); +} #endif #ifdef TL_EXPECTED_CXX14