Support value and error assignments in expected

This commit is contained in:
Denis Blank 2017-12-01 19:03:13 +01:00
parent 95d5f25f84
commit 73a8da1b86
3 changed files with 75 additions and 6 deletions

View File

@ -34,6 +34,7 @@
// Exlude this header when coroutines are not available // Exlude this header when coroutines are not available
#ifdef CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE #ifdef CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE
#include <cassert>
#include <experimental/coroutine> #include <experimental/coroutine>
#include <continuable/continuable-api.hpp> #include <continuable/continuable-api.hpp>
@ -47,20 +48,47 @@ namespace cti {
namespace detail { namespace detail {
namespace awaiting { namespace awaiting {
namespace detail { namespace detail {
struct void_guard_tag {};
template <typename T> template <typename T>
struct result_trait { struct result_trait;
template <>
struct result_trait<traits::identity<void>> {
using expected = util::expected<void_guard_tag>;
static auto wrap() {
return expected(void_guard_tag{});
}
static void unwrap(expected&& e) {
assert(e.is_value());
(void)e;
}
};
template <typename T>
struct result_trait<traits::identity<T>> {
using expected = util::expected<T>; using expected = util::expected<T>;
static auto wrap(T arg) { static auto wrap(T arg) {
return std::move(arg); return std::move(arg);
} }
static void unwrap(expected&& e) {
assert(e.is_value());
(void)e;
return std::move(e.get_value());
}
}; };
template <typename... T> template <typename First, typename Second, typename... Rest>
struct result_trait<traits::identity<T...>> { struct result_trait<traits::identity<First, Second, Rest...>> {
using expected = util::expected<std::tuple<T...>>; using expected = util::expected<std::tuple<First, Second, Rest...>>;
static auto wrap(T... args) { static auto wrap(First first, Second second, Rest... rest) {
return std::make_tuple(std::move(args)...); 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());
} }
}; };

View File

@ -172,6 +172,15 @@ public:
: expected(std::move(error), detail::slot_t::error) { : 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 const&) = default;
expected(expected&& right) = default; expected(expected&& right) = default;
expected& operator=(expected const&) = default; expected& operator=(expected const&) = default;
@ -190,6 +199,17 @@ public:
return is_value(); 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 { T& get_value() noexcept {
assert(is_value()); assert(is_value());
return cast<T>(); return cast<T>();

View File

@ -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) { TEST(expected_copyable_tests, is_copy_constructible) {
{ {
copyable_type const e_old(CANARY); copyable_type const e_old(CANARY);