From d420c9752cdbdaf2b68e16a453ae3dd4a5413b8e Mon Sep 17 00:00:00 2001 From: Arthur O'Dwyer Date: Sun, 2 Jan 2022 14:48:19 -0500 Subject: [PATCH] Prepare and_then/map/transform/map_error/or_else for SFINAE-friendliness. This incidentally simplifies the preprocessor stuff, by making these codepaths look the same in both C++11 and C++14. The old code had the weird effect that the C++11 codepath was slightly *more* SFINAE-friendly than the C++14 codepath. This patch doesn't actually make and_then/map/transform/map_error/or_else be SFINAE-friendly. But it lays the groundwork for adding further constraints to the `enable_if` stuff in `and_then_impl` etc., which could make these functions fully SFINAE-friendly without needing to touch the non-`_impl` versions again. --- include/tl/expected.hpp | 171 +++++++++++----------------------------- 1 file changed, 47 insertions(+), 124 deletions(-) diff --git a/include/tl/expected.hpp b/include/tl/expected.hpp index 31b130a..f419aa6 100644 --- a/include/tl/expected.hpp +++ b/include/tl/expected.hpp @@ -1251,198 +1251,121 @@ class expected : private detail::expected_move_assign_base, typedef E error_type; typedef unexpected unexpected_type; -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ - !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) - template TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & { - return and_then_impl(*this, std::forward(f)); - } - template TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && { - return and_then_impl(std::move(*this), std::forward(f)); - } - template constexpr auto and_then(F &&f) const & { - return and_then_impl(*this, std::forward(f)); - } - -#ifndef TL_EXPECTED_NO_CONSTRR - template constexpr auto and_then(F &&f) const && { - return and_then_impl(std::move(*this), std::forward(f)); - } -#endif - -#else template - TL_EXPECTED_11_CONSTEXPR auto - and_then(F &&f) & -> decltype(and_then_impl(std::declval(), std::forward(f))) { + TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & + -> decltype(and_then_impl(*this, std::forward(f))) { return and_then_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && -> decltype( - and_then_impl(std::declval(), std::forward(f))) { + TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && + -> decltype(and_then_impl(std::move(*this), std::forward(f))) { return and_then_impl(std::move(*this), std::forward(f)); } template - constexpr auto and_then(F &&f) const & -> decltype( - and_then_impl(std::declval(), std::forward(f))) { + constexpr auto and_then(F &&f) const & + -> decltype(and_then_impl(*this, std::forward(f))) { return and_then_impl(*this, std::forward(f)); } - #ifndef TL_EXPECTED_NO_CONSTRR template - constexpr auto and_then(F &&f) const && -> decltype( - and_then_impl(std::declval(), std::forward(f))) { + constexpr auto and_then(F &&f) const && + -> decltype(and_then_impl(std::move(*this), std::forward(f))) { return and_then_impl(std::move(*this), std::forward(f)); } #endif -#endif -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ - !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) - template TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & { - return expected_map_impl(*this, std::forward(f)); - } - template TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && { - return expected_map_impl(std::move(*this), std::forward(f)); - } - template constexpr auto map(F &&f) const & { - return expected_map_impl(*this, std::forward(f)); - } - template constexpr auto map(F &&f) const && { - return expected_map_impl(std::move(*this), std::forward(f)); - } -#else template - TL_EXPECTED_11_CONSTEXPR decltype( - expected_map_impl(std::declval(), std::declval())) - map(F &&f) & { + TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & + -> decltype(expected_map_impl(*this, std::forward(f))) { return expected_map_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR decltype( - expected_map_impl(std::declval(), std::declval())) - map(F &&f) && { + TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && + -> decltype(expected_map_impl(std::move(*this), std::forward(f))) { return expected_map_impl(std::move(*this), std::forward(f)); } template - constexpr decltype(expected_map_impl(std::declval(), - std::declval())) - map(F &&f) const & { + constexpr auto map(F &&f) const & + -> decltype(expected_map_impl(*this, std::forward(f))) { return expected_map_impl(*this, std::forward(f)); } - #ifndef TL_EXPECTED_NO_CONSTRR template - constexpr decltype(expected_map_impl(std::declval(), - std::declval())) - map(F &&f) const && { + constexpr auto map(F &&f) const && + -> decltype(expected_map_impl(std::move(*this), std::forward(f))) { return expected_map_impl(std::move(*this), std::forward(f)); } #endif -#endif -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ - !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) - template TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) & { - return expected_map_impl(*this, std::forward(f)); - } - template TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) && { - return expected_map_impl(std::move(*this), std::forward(f)); - } - template constexpr auto transform(F &&f) const & { - return expected_map_impl(*this, std::forward(f)); - } - template constexpr auto transform(F &&f) const && { - return expected_map_impl(std::move(*this), std::forward(f)); - } -#else - template - TL_EXPECTED_11_CONSTEXPR decltype( - expected_map_impl(std::declval(), std::declval())) - transform(F &&f) & { + template + TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) & + -> decltype(expected_map_impl(*this, std::forward(f))) { return expected_map_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR decltype( - expected_map_impl(std::declval(), std::declval())) - transform(F &&f) && { + TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) && + -> decltype(expected_map_impl(std::move(*this), std::forward(f))) { return expected_map_impl(std::move(*this), std::forward(f)); } template - constexpr decltype(expected_map_impl(std::declval(), - std::declval())) - transform(F &&f) const & { + constexpr auto transform(F &&f) const & + -> decltype(expected_map_impl(*this, std::forward(f))) { return expected_map_impl(*this, std::forward(f)); } - #ifndef TL_EXPECTED_NO_CONSTRR template - constexpr decltype(expected_map_impl(std::declval(), - std::declval())) - transform(F &&f) const && { + constexpr auto transform(F &&f) const && + -> decltype(expected_map_impl(std::move(*this), std::forward(f))) { return expected_map_impl(std::move(*this), std::forward(f)); } #endif -#endif -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ - !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) - 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 template - TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), - std::declval())) - map_error(F &&f) & { + TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) & + -> decltype(map_error_impl(*this, std::forward(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) && { + TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) && + -> decltype(map_error_impl(std::move(*this), std::forward(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 & { + constexpr auto map_error(F &&f) const & + -> decltype(map_error_impl(*this, std::forward(f))) { 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 && { + constexpr auto map_error(F &&f) const && + -> decltype(map_error_impl(std::move(*this), std::forward(f))) { return map_error_impl(std::move(*this), std::forward(f)); } #endif -#endif - template expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) & { + + template + TL_EXPECTED_11_CONSTEXPR auto or_else(F &&f) & + -> decltype(or_else_impl(*this, std::forward(f))) { return or_else_impl(*this, std::forward(f)); } - - template expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) && { + template + TL_EXPECTED_11_CONSTEXPR auto or_else(F &&f) && + -> decltype(or_else_impl(std::move(*this), std::forward(f))) { return or_else_impl(std::move(*this), std::forward(f)); } - - template expected constexpr or_else(F &&f) const & { + template + constexpr auto or_else(F &&f) const & + -> decltype(or_else_impl(*this, std::forward(f))) { return or_else_impl(*this, std::forward(f)); } - #ifndef TL_EXPECTED_NO_CONSTRR - template expected constexpr or_else(F &&f) const && { + template + constexpr auto or_else(F &&f) const && + -> decltype(or_else_impl(std::move(*this), std::forward(f))) { return or_else_impl(std::move(*this), std::forward(f)); } #endif + constexpr expected() = default; constexpr expected(const expected &rhs) = default; constexpr expected(expected &&rhs) = default;