diff --git a/include/continuable/detail/awaiting.hpp b/include/continuable/detail/awaiting.hpp index 2104944..f618fb5 100644 --- a/include/continuable/detail/awaiting.hpp +++ b/include/continuable/detail/awaiting.hpp @@ -37,13 +37,38 @@ #include #include -// #include +#include #include +#include #include +#include namespace cti { namespace detail { namespace awaiting { +namespace detail { +template +struct result_trait { + using expected = util::expected; + + static auto wrap(T arg) { + return std::move(arg); + } +}; +template +struct result_trait> { + using expected = util::expected>; + + static auto wrap(T... args) { + return std::make_tuple(std::move(args)...); + } +}; + +template +using result_storage_of_t = + result_trait()))>; +} // namespace detail + /// We import the coroutine handle in our namespace using std::experimental::coroutine_handle; @@ -51,11 +76,13 @@ using std::experimental::coroutine_handle; /// for waiting on a continuable in a stackless coroutine. template class awaitable { + using trait_t = detail::result_trait; + /// The continuable which is invoked upon suspension Continuable continuable_; /// A cache which is used to pass the result of the continuation - /// to the - // util::expected cache_; + /// to the coroutine. + typename trait_t::expected result_; public: /// Since continuables are evaluated lazily we are not @@ -68,16 +95,20 @@ public: // TODO Convert this to an r-value function once possible void await_suspend(coroutine_handle<> h) { // Forward every result to the current awaitable - std::move(continuable_).flow([h, this](auto&&... args) { - resolve(); - h.resume(); - }); + std::move(continuable_) + .flow([h, this](auto&&... args) { + resolve(std::forward(args)...); + h.resume(); + }) + .done(); } void await_resume() { - // if ec throw - // return n; - // return + if (result_) { + return result_.get_value(); + } else { + throw result_.get_error(); + } } private: diff --git a/include/continuable/detail/expected.hpp b/include/continuable/detail/expected.hpp index 8a2fe1f..10e2a4b 100644 --- a/include/continuable/detail/expected.hpp +++ b/include/continuable/detail/expected.hpp @@ -181,7 +181,7 @@ public: assert(!is_empty()); return slot_ == detail::slot_t::value; } - bool is_error() const noexcept { + bool is_exception() const noexcept { assert(!is_empty()); return slot_ == detail::slot_t::error; } @@ -189,14 +189,30 @@ public: explicit constexpr operator bool() const noexcept { return is_value(); } - T& operator*() noexcept { + + T& get_value() noexcept { assert(is_value()); return cast(); } - T const& operator*() const noexcept { + T const& get_value() const noexcept { assert(is_value()); return cast(); } + T& get_exception() noexcept { + assert(is_exception()); + return cast(); + } + T const& get_exception() const noexcept { + assert(is_exception()); + return cast(); + } + + T& operator*() noexcept { + return get_value(); + } + T const& operator*() const noexcept { + return get_value(); + } private: template diff --git a/test/unit-test/test-continuable-expected.cpp b/test/unit-test/test-continuable-expected.cpp index 31aaf70..ec414be 100644 --- a/test/unit-test/test-continuable-expected.cpp +++ b/test/unit-test/test-continuable-expected.cpp @@ -22,6 +22,7 @@ **/ #include +#include #include #include @@ -70,7 +71,7 @@ TYPED_TEST(expected_all_tests, can_carry_errors) { EXPECT_TRUE(bool(e)); EXPECT_EQ(this->get(*e), CANARY); EXPECT_TRUE(e.is_value()); - EXPECT_FALSE(e.is_error()); + EXPECT_FALSE(e.is_exception()); } { @@ -78,7 +79,7 @@ TYPED_TEST(expected_all_tests, can_carry_errors) { EXPECT_FALSE(bool(e)); EXPECT_FALSE(e.is_value()); - EXPECT_TRUE(e.is_error()); + EXPECT_TRUE(e.is_exception()); } } @@ -94,14 +95,14 @@ TYPED_TEST(expected_all_tests, is_move_constructible) { EXPECT_TRUE(bool(e)); EXPECT_EQ(this->get(*e), CANARY); EXPECT_TRUE(e.is_value()); - EXPECT_FALSE(e.is_error()); + EXPECT_FALSE(e.is_exception()); } { TypeParam e(TypeParam(error_type{})); EXPECT_FALSE(bool(e)); EXPECT_FALSE(e.is_value()); - EXPECT_TRUE(e.is_error()); + EXPECT_TRUE(e.is_exception()); } } @@ -114,7 +115,7 @@ TYPED_TEST(expected_all_tests, is_move_assignable) { EXPECT_TRUE(bool(e)); EXPECT_EQ(this->get(*e), CANARY); EXPECT_TRUE(e.is_value()); - EXPECT_FALSE(e.is_error()); + EXPECT_FALSE(e.is_exception()); } { @@ -124,7 +125,7 @@ TYPED_TEST(expected_all_tests, is_move_assignable) { EXPECT_FALSE(bool(e)); EXPECT_FALSE(e.is_value()); - EXPECT_TRUE(e.is_error()); + EXPECT_TRUE(e.is_exception()); } } @@ -136,7 +137,7 @@ TEST(expected_copyable_tests, is_copy_constructible) { EXPECT_TRUE(bool(e)); EXPECT_EQ(*e, CANARY); EXPECT_TRUE(e.is_value()); - EXPECT_FALSE(e.is_error()); + EXPECT_FALSE(e.is_exception()); } { @@ -145,7 +146,7 @@ TEST(expected_copyable_tests, is_copy_constructible) { EXPECT_FALSE(bool(e)); EXPECT_FALSE(e.is_value()); - EXPECT_TRUE(e.is_error()); + EXPECT_TRUE(e.is_exception()); } } @@ -158,7 +159,7 @@ TEST(expected_copyable_tests, is_copy_assignable) { EXPECT_TRUE(bool(e)); EXPECT_EQ(*e, CANARY); EXPECT_TRUE(e.is_value()); - EXPECT_FALSE(e.is_error()); + EXPECT_FALSE(e.is_exception()); } { @@ -168,6 +169,6 @@ TEST(expected_copyable_tests, is_copy_assignable) { EXPECT_FALSE(bool(e)); EXPECT_FALSE(e.is_value()); - EXPECT_TRUE(e.is_error()); + EXPECT_TRUE(e.is_exception()); } }