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
#ifdef CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE
#include <cassert>
#include <experimental/coroutine>
#include <continuable/continuable-api.hpp>
@ -47,20 +48,47 @@ namespace cti {
namespace detail {
namespace awaiting {
namespace detail {
struct void_guard_tag {};
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>;
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 <typename... T>
struct result_trait<traits::identity<T...>> {
using expected = util::expected<std::tuple<T...>>;
template <typename First, typename Second, typename... Rest>
struct result_trait<traits::identity<First, Second, Rest...>> {
using expected = util::expected<std::tuple<First, Second, Rest...>>;
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());
}
};

View File

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