From dbf73b6ac6edac40ea411d19e750a988bf20042b Mon Sep 17 00:00:00 2001 From: Denis Blank Date: Fri, 8 Dec 2017 21:59:59 +0100 Subject: [PATCH] more --- include/continuable/detail/awaiting.hpp | 18 +++- include/continuable/detail/base.hpp | 17 ++- include/continuable/detail/expected.hpp | 107 ++++++++++--------- include/continuable/detail/features.hpp | 8 ++ test/unit-test/test-continuable-expected.cpp | 34 +++--- 5 files changed, 100 insertions(+), 84 deletions(-) diff --git a/include/continuable/detail/awaiting.hpp b/include/continuable/detail/awaiting.hpp index ceda4fe..291a3a0 100644 --- a/include/continuable/detail/awaiting.hpp +++ b/include/continuable/detail/awaiting.hpp @@ -44,6 +44,10 @@ #include #include +#if defined(CONTINUABLE_WITH_EXCEPTIONS) +#include +#endif // CONTINUABLE_WITH_EXCEPTIONS + namespace cti { namespace detail { namespace awaiting { @@ -131,12 +135,18 @@ public: .done(); } - void await_resume() { + auto await_resume() noexcept(false) { if (result_) { - return result_.get_value(); - } else { - throw result_.get_error(); + // When the result was resolved return it + trait_t::unwrap(std::move(result_)); } + +#if defined(CONTINUABLE_WITH_EXCEPTIONS) + std::rethrow_exception(result_.get_error()); +#else // CONTINUABLE_WITH_EXCEPTIONS + // Returning error types in await isn't supported as of now + util::trap(); +#endif // CONTINUABLE_WITH_EXCEPTIONS } private: diff --git a/include/continuable/detail/base.hpp b/include/continuable/detail/base.hpp index 44695d5..f888642 100644 --- a/include/continuable/detail/base.hpp +++ b/include/continuable/detail/base.hpp @@ -35,17 +35,17 @@ #include #include -#if !defined(CONTINUABLE_WITH_CUSTOM_ERROR_TYPE) && \ - !defined(CONTINUABLE_WITH_NO_EXCEPTIONS) -#include -#endif - #include +#include #include #include #include #include +#if defined(CONTINUABLE_WITH_EXCEPTIONS) +#include +#endif // CONTINUABLE_WITH_EXCEPTIONS + namespace cti { namespace detail { /// The namespace `base` provides the low level API for working @@ -151,8 +151,7 @@ public: } }; -#if !defined(CONTINUABLE_WITH_CUSTOM_ERROR_TYPE) && \ - !defined(CONTINUABLE_WITH_NO_EXCEPTIONS) +#if defined(CONTINUABLE_WITH_EXCEPTIONS) #define CONTINUABLE_BLOCK_TRY_BEGIN try { #define CONTINUABLE_BLOCK_TRY_END \ } \ @@ -161,10 +160,10 @@ public: types::dispatch_error_tag{}, std::current_exception()); \ } -#else +#else // CONTINUABLE_WITH_EXCEPTIONS #define CONTINUABLE_BLOCK_TRY_BEGIN { #define CONTINUABLE_BLOCK_TRY_END } -#endif +#endif // CONTINUABLE_WITH_EXCEPTIONS template constexpr auto make_invoker(T&& invoke, hints::signature_hint_tag) { diff --git a/include/continuable/detail/expected.hpp b/include/continuable/detail/expected.hpp index 1a94b3d..0e61495 100644 --- a/include/continuable/detail/expected.hpp +++ b/include/continuable/detail/expected.hpp @@ -52,8 +52,46 @@ using storage_of_t = // ? sizeof(types::error_type) : sizeof(T))>; +template +struct expected_move_base { + constexpr expected_move_base() = default; + + expected_move_base(expected_move_base const&) = default; + explicit expected_move_base(expected_move_base&& right) { + Base& me = *static_cast(this); + Base& other = *static_cast(&right); + assert(!other.is_empty()); + +#ifndef _NDEBUG + me.set(slot_t::empty); +#endif + + other.visit([&](auto&& value) { + // ... + me.init(std::move(value)); + }); + me.set(other.get()); + other.destroy(); + } + expected_move_base& operator=(expected_move_base const&) = default; + expected_move_base& operator=(expected_move_base&& right) { + Base& me = *static_cast(this); + Base& other = *static_cast(&right); + assert(!other.is_empty()); + + me.weak_destroy(); + + other.visit([&](auto&& value) { + // ... + me.init(std::move(value)); + }); + me.set(other.get()); + other.destroy(); + return *this; + } +}; template -struct expected_copy_base { +struct expected_copy_base : expected_move_base { constexpr expected_copy_base() = default; expected_copy_base(expected_copy_base&&) = default; @@ -62,6 +100,7 @@ struct expected_copy_base { { Base& me = *static_cast(this); Base const& other = *static_cast(&right); + assert(!other->is_empty()); #ifndef _NDEBUG me.set(slot_t::empty); @@ -79,6 +118,7 @@ struct expected_copy_base { { Base& me = *static_cast(this); Base const& other = *static_cast(&right); + assert(!other.is_empty()); me.weak_destroy(); @@ -91,7 +131,7 @@ struct expected_copy_base { } }; template -struct expected_copy_base { +struct expected_copy_base : expected_move_base { constexpr expected_copy_base() = default; expected_copy_base(expected_copy_base const&) = default; @@ -99,40 +139,6 @@ struct expected_copy_base { expected_copy_base& operator=(expected_copy_base const&) = default; expected_copy_base& operator=(expected_copy_base&& right) = delete; }; -template -struct expected_move_base { - constexpr expected_move_base() = default; - - expected_move_base(expected_move_base const&) = default; - explicit expected_move_base(expected_move_base&& right) { - Base& me = *static_cast(this); - Base& other = *static_cast(&right); - -#ifndef _NDEBUG - me.set(slot_t::empty); -#endif - - other.visit([&](auto&& value) { - // ... - me.init(std::move(value)); - }); - me.set(other.consume()); - } - expected_move_base& operator=(expected_move_base const&) = default; - expected_move_base& operator=(expected_move_base&& right) { - Base& me = *static_cast(this); - Base& other = *static_cast(&right); - - me.weak_destroy(); - - other.visit([&](auto&& value) { - // ... - me.init(std::move(value)); - }); - me.set(other.consume()); - return *this; - } -}; } // namespace detail /// A class similar to the one in the expected proposal, @@ -140,8 +146,7 @@ struct expected_move_base { /// exceptions are used. template class expected - : detail::expected_move_base>, - detail::expected_copy_base< + : detail::expected_copy_base< expected, std::is_copy_constructible::value && std::is_copy_constructible::value> { @@ -153,7 +158,7 @@ class expected friend struct detail::expected_copy_base; detail::storage_of_t storage_; - detail::slot_t slot_ = detail::slot_t::empty; + detail::slot_t slot_; template expected(V&& value, detail::slot_t const slot) { @@ -163,7 +168,13 @@ class expected } public: - expected() = default; + constexpr expected() : slot_(detail::slot_t::empty) { + } + + expected(expected const&) = default; + expected(expected&&) = default; + expected& operator=(expected const&) = default; + expected& operator=(expected&&) = default; explicit expected(T value) // : expected(std::move(value), detail::slot_t::value) { @@ -181,18 +192,13 @@ public: return *this; } - expected(expected const&) = default; - expected(expected&& right) = default; - expected& operator=(expected const&) = default; - expected& operator=(expected&& right) = default; - bool is_value() const noexcept { assert(!is_empty()); - return slot_ == detail::slot_t::value; + return is(detail::slot_t::value); } bool is_exception() const noexcept { assert(!is_empty()); - return slot_ == detail::slot_t::error; + return is(detail::slot_t::error); } explicit constexpr operator bool() const noexcept { @@ -261,7 +267,7 @@ private: } bool is_empty() const noexcept { - return slot_ == detail::slot_t::empty; + return is(detail::slot_t::empty); } template @@ -308,11 +314,6 @@ private: void set(detail::slot_t const slot) { slot_ = slot; } - detail::slot_t consume() { - auto const current = get(); - destroy(); - return current; - } }; } // namespace util } // namespace detail diff --git a/include/continuable/detail/features.hpp b/include/continuable/detail/features.hpp index cae5332..0bec19b 100644 --- a/include/continuable/detail/features.hpp +++ b/include/continuable/detail/features.hpp @@ -47,6 +47,14 @@ #endif #endif // CONTINUABLE_WITH_NO_EXCEPTIONS +/// Define CONTINUABLE_WITH_EXCEPTIONS when exceptions are used +#if !defined(CONTINUABLE_WITH_CUSTOM_ERROR_TYPE) && \ + !defined(CONTINUABLE_WITH_NO_EXCEPTIONS) +#define CONTINUABLE_WITH_EXCEPTIONS 1 +#else +#undef CONTINUABLE_WITH_EXCEPTIONS +#endif + /// TODO Enable this #undef CONTINUABLE_HAS_CXX17_CONSTEXPR_IF /// TODO Enable this diff --git a/test/unit-test/test-continuable-expected.cpp b/test/unit-test/test-continuable-expected.cpp index d91b5a3..3258ad2 100644 --- a/test/unit-test/test-continuable-expected.cpp +++ b/test/unit-test/test-continuable-expected.cpp @@ -106,27 +106,25 @@ TYPED_TEST(expected_all_tests, is_move_constructible) { } } -TYPED_TEST(expected_all_tests, is_move_assignable) { - { - TypeParam old(this->supply(CANARY)); - TypeParam e; - e = std::move(old); +TYPED_TEST(expected_all_tests, is_value_move_assignable) { + TypeParam old(this->supply(CANARY)); + TypeParam e; + e = std::move(old); - EXPECT_TRUE(bool(e)); - EXPECT_EQ(this->get(*e), CANARY); - EXPECT_TRUE(e.is_value()); - EXPECT_FALSE(e.is_exception()); - } + EXPECT_TRUE(bool(e)); + EXPECT_EQ(this->get(*e), CANARY); + EXPECT_TRUE(e.is_value()); + EXPECT_FALSE(e.is_exception()); +} - { - TypeParam old(error_type{}); - TypeParam e; - e = std::move(old); +TYPED_TEST(expected_all_tests, is_error_move_assignable) { + TypeParam old(error_type{}); + TypeParam e; + e = std::move(old); - EXPECT_FALSE(bool(e)); - EXPECT_FALSE(e.is_value()); - EXPECT_TRUE(e.is_exception()); - } + EXPECT_FALSE(bool(e)); + EXPECT_FALSE(e.is_value()); + EXPECT_TRUE(e.is_exception()); } TYPED_TEST(expected_all_tests, is_value_assignable) {