From 73a8da1b867bfc66dd0061a979cbea62e2212a3a Mon Sep 17 00:00:00 2001 From: Denis Blank Date: Fri, 1 Dec 2017 19:03:13 +0100 Subject: [PATCH] Support value and error assignments in expected --- include/continuable/detail/awaiting.hpp | 40 +++++++++++++++++--- include/continuable/detail/expected.hpp | 20 ++++++++++ test/unit-test/test-continuable-expected.cpp | 21 ++++++++++ 3 files changed, 75 insertions(+), 6 deletions(-) diff --git a/include/continuable/detail/awaiting.hpp b/include/continuable/detail/awaiting.hpp index 6737662..ceda4fe 100644 --- a/include/continuable/detail/awaiting.hpp +++ b/include/continuable/detail/awaiting.hpp @@ -34,6 +34,7 @@ // Exlude this header when coroutines are not available #ifdef CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE +#include #include #include @@ -47,20 +48,47 @@ namespace cti { namespace detail { namespace awaiting { namespace detail { +struct void_guard_tag {}; + template -struct result_trait { +struct result_trait; +template <> +struct result_trait> { + using expected = util::expected; + + static auto wrap() { + return expected(void_guard_tag{}); + } + static void unwrap(expected&& e) { + assert(e.is_value()); + (void)e; + } +}; +template +struct result_trait> { using expected = util::expected; static auto wrap(T arg) { return std::move(arg); } + static void unwrap(expected&& e) { + assert(e.is_value()); + (void)e; + return std::move(e.get_value()); + } }; -template -struct result_trait> { - using expected = util::expected>; +template +struct result_trait> { + using expected = util::expected>; - static auto wrap(T... args) { - return std::make_tuple(std::move(args)...); + static auto wrap(First first, Second second, Rest... rest) { + return std::make_tuple(std::move(first), std::move(second), + std::move(rest)...); + } + static void unwrap(expected&& e) { + assert(e.is_value()); + (void)e; + return std::move(e.get_value()); } }; diff --git a/include/continuable/detail/expected.hpp b/include/continuable/detail/expected.hpp index 10e2a4b..1a94b3d 100644 --- a/include/continuable/detail/expected.hpp +++ b/include/continuable/detail/expected.hpp @@ -172,6 +172,15 @@ public: : expected(std::move(error), detail::slot_t::error) { } + expected& operator=(T value) { + set_value(std::move(value)); + return *this; + } + expected& operator=(types::error_type error) { + set_error(std::move(error)); + return *this; + } + expected(expected const&) = default; expected(expected&& right) = default; expected& operator=(expected const&) = default; @@ -190,6 +199,17 @@ public: return is_value(); } + void set_value(T value) { + weak_destroy(); + init(std::move(value)); + set(detail::slot_t::value); + } + void set_error(types::error_type error) { + weak_destroy(); + init(std::move(error)); + set(detail::slot_t::error); + } + T& get_value() noexcept { assert(is_value()); return cast(); diff --git a/test/unit-test/test-continuable-expected.cpp b/test/unit-test/test-continuable-expected.cpp index ec414be..d91b5a3 100644 --- a/test/unit-test/test-continuable-expected.cpp +++ b/test/unit-test/test-continuable-expected.cpp @@ -129,6 +129,27 @@ TYPED_TEST(expected_all_tests, is_move_assignable) { } } +TYPED_TEST(expected_all_tests, is_value_assignable) { + { + TypeParam e; + e = this->supply(CANARY); + + EXPECT_TRUE(bool(e)); + EXPECT_EQ(this->get(*e), CANARY); + EXPECT_TRUE(e.is_value()); + EXPECT_FALSE(e.is_exception()); + } + + { + TypeParam e; + e = error_type{}; + + EXPECT_FALSE(bool(e)); + EXPECT_FALSE(e.is_value()); + EXPECT_TRUE(e.is_exception()); + } +} + TEST(expected_copyable_tests, is_copy_constructible) { { copyable_type const e_old(CANARY);