diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e7bcd7..fe45fae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,7 @@ set(TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/tests/main.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tests/extensions.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tests/assignment.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tests/emplace.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tests/issues.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tests/bases.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tests/observers.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tests/constructors.cpp) diff --git a/tests/issues.cpp b/tests/issues.cpp new file mode 100644 index 0000000..2dc4201 --- /dev/null +++ b/tests/issues.cpp @@ -0,0 +1,26 @@ +#include "catch.hpp" +#include "expected.hpp" + +#include + +using std::string; + +tl::expected getInt3(int val) +{ + return val; +} + +tl::expected getInt2(int val) +{ + return val; +} + +tl::expected getInt1() +{ + return getInt2(5).and_then(getInt3); +} + + +TEST_CASE("Issue 1", "[issues.1]") { + getInt1(); +} diff --git a/tl/expected.hpp b/tl/expected.hpp index 4a61b65..6515668 100644 --- a/tl/expected.hpp +++ b/tl/expected.hpp @@ -999,8 +999,9 @@ public: /// is returned. /// \synopsis template \nconstexpr auto and_then(F &&f) &; template - TL_EXPECTED_11_CONSTEXPR detail::invoke_result_t and_then(F &&f) & { - using result = detail::invoke_result_t; + TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & + -> decltype(detail::invoke(std::forward(f), std::declval())) { + using result = decltype(detail::invoke(std::forward(f), **this)); static_assert(detail::is_expected::value, "F must return an expected"); @@ -1011,20 +1012,22 @@ public: /// \group and_then /// \synopsis template \nconstexpr auto and_then(F &&f) &&; template - TL_EXPECTED_11_CONSTEXPR detail::invoke_result_t and_then(F &&f) && { - using result = detail::invoke_result_t; + TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && + -> decltype(detail::invoke(std::forward(f), std::declval())) { + using result = decltype(detail::invoke(std::forward(f), std::move(**this))); static_assert(detail::is_expected::value, "F must return an expected"); - return has_value() ? detail::invoke(std::forward(f), **this) + return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : result(unexpect, std::move(this->error())); } /// \group and_then /// \synopsis template \nconstexpr auto and_then(F &&f) const &; template - constexpr detail::invoke_result_t and_then(F &&f) const & { - using result = detail::invoke_result_t; + constexpr auto and_then(F &&f) const & + -> decltype(detail::invoke(std::forward(f), std::declval())) { + using result = decltype(detail::invoke(std::forward(f), **this)); static_assert(detail::is_expected::value, "F must return an expected"); @@ -1036,8 +1039,9 @@ public: /// \group and_then /// \synopsis template \nconstexpr auto and_then(F &&f) const &&; template - constexpr detail::invoke_result_t and_then(F &&f) const && { - using result = detail::invoke_result_t; + constexpr auto and_then(F &&f) const && + -> decltype(detail::invoke(std::forward(f), std::declval())) { + using result = decltype(detail::invoke(std::forward(f), std::move(**this))); static_assert(detail::is_expected::value, "F must return an expected");