mirror of
https://github.com/Naios/continuable.git
synced 2025-12-07 01:06:44 +08:00
Make result<> return void when calling get_value()
This commit is contained in:
parent
5354d3512e
commit
cd367b3d43
@ -86,15 +86,15 @@ public:
|
||||
|
||||
/// A class similar to the one in the result proposal,
|
||||
/// however it's capable of carrying an exception_t.
|
||||
// TODO -> async_result
|
||||
template <typename... T>
|
||||
class result {
|
||||
using trait = detail::result_trait<T...>;
|
||||
using value_t = typename trait::value_t;
|
||||
|
||||
detail::container::flat_variant<value_t, exception_t> variant_;
|
||||
using trait_t = detail::result_trait<T...>;
|
||||
using surrogate_t = typename trait_t::surrogate_t;
|
||||
|
||||
public:
|
||||
using value_t = typename trait_t::value_t;
|
||||
using exception_t = exception_t;
|
||||
|
||||
result() = default;
|
||||
result(result const&) = default;
|
||||
result(result&&) = default;
|
||||
@ -103,9 +103,9 @@ public:
|
||||
~result() = default;
|
||||
|
||||
template <typename... Args,
|
||||
decltype(trait::wrap(std::declval<Args>()...))* = nullptr>
|
||||
decltype(trait_t::wrap(std::declval<Args>()...))* = nullptr>
|
||||
explicit result(Args&&... values)
|
||||
: variant_(trait::wrap(std::forward<Args>(values)...)) {
|
||||
: variant_(trait_t::wrap(std::forward<Args>(values)...)) {
|
||||
}
|
||||
explicit result(exception_t exception) : variant_(std::move(exception)) {
|
||||
}
|
||||
@ -127,7 +127,7 @@ public:
|
||||
variant_.set_empty();
|
||||
}
|
||||
void set_value(T... values) {
|
||||
variant_ = trait::wrap(std::move(values)...);
|
||||
variant_ = trait_t::wrap(std::move(values)...);
|
||||
}
|
||||
void set_exception(exception_t exception) {
|
||||
variant_ = std::move(exception);
|
||||
@ -137,7 +137,7 @@ public:
|
||||
return variant_.is_empty();
|
||||
}
|
||||
bool is_value() const noexcept {
|
||||
return variant_.template is<value_t>();
|
||||
return variant_.template is<surrogate_t>();
|
||||
}
|
||||
bool is_exception() const noexcept {
|
||||
return variant_.template is<exception_t>();
|
||||
@ -147,15 +147,26 @@ public:
|
||||
return is_value();
|
||||
}
|
||||
|
||||
value_t& get_value() & noexcept {
|
||||
return variant_.template cast<value_t>();
|
||||
decltype(auto) get_value() & noexcept {
|
||||
return trait_t::unwrap(variant_.template cast<surrogate_t>());
|
||||
}
|
||||
value_t const& get_value() const& noexcept {
|
||||
return variant_.template cast<value_t>();
|
||||
decltype(auto) get_value() const& noexcept {
|
||||
return trait_t::unwrap(variant_.template cast<surrogate_t>());
|
||||
}
|
||||
value_t&& get_value() && noexcept {
|
||||
return std::move(variant_).template cast<value_t>();
|
||||
decltype(auto) get_value() && noexcept {
|
||||
return trait_t::unwrap(std::move(variant_).template cast<surrogate_t>());
|
||||
}
|
||||
|
||||
decltype(auto) operator*() & noexcept {
|
||||
return get_value();
|
||||
}
|
||||
decltype(auto) operator*() const& noexcept {
|
||||
return get_value();
|
||||
}
|
||||
decltype(auto) operator*() && noexcept {
|
||||
return std::move(*this).get_value();
|
||||
}
|
||||
|
||||
exception_t& get_exception() & noexcept {
|
||||
return variant_.template cast<exception_t>();
|
||||
}
|
||||
@ -166,15 +177,8 @@ public:
|
||||
return std::move(variant_).template cast<exception_t>();
|
||||
}
|
||||
|
||||
value_t& operator*() & noexcept {
|
||||
return get_value();
|
||||
}
|
||||
value_t const& operator*() const& noexcept {
|
||||
return get_value();
|
||||
}
|
||||
value_t&& operator*() && noexcept {
|
||||
return std::move(*this).get_value();
|
||||
}
|
||||
private:
|
||||
detail::container::flat_variant<surrogate_t, exception_t> variant_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
||||
@ -595,8 +595,8 @@ auto chain_continuation(Continuation&& continuation, Callback&& callback,
|
||||
return attorney::create_from(
|
||||
[continuation = std::forward<Continuation>(continuation),
|
||||
callback = std::forward<Callback>(callback),
|
||||
executor =
|
||||
std::forward<Executor>(executor)](auto&& next_callback) mutable {
|
||||
executor = std::forward<Executor>(executor)] //
|
||||
(auto&& next_callback) mutable {
|
||||
// Invokes a continuation with a given callback.
|
||||
// Passes the next callback to the resulting continuable or
|
||||
// invokes the next callback directly if possible.
|
||||
|
||||
@ -98,7 +98,7 @@ public:
|
||||
}
|
||||
|
||||
/// Resume the coroutine represented by the handle
|
||||
auto await_resume() noexcept(false) {
|
||||
typename result_t::value_t await_resume() noexcept(false) {
|
||||
if (result_) {
|
||||
// When the result was resolved return it
|
||||
return std::move(result_).get_value();
|
||||
@ -120,8 +120,8 @@ private:
|
||||
}
|
||||
|
||||
/// Resolve the continuation through an error
|
||||
void resolve(exception_arg_t, exception_t error) {
|
||||
result_.set_exception(std::move(error));
|
||||
void resolve(exception_arg_t, exception_t exception) {
|
||||
result_.set_exception(std::move(exception));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -43,29 +43,44 @@ template <typename... T>
|
||||
struct result_trait;
|
||||
template <>
|
||||
struct result_trait<> {
|
||||
struct value_t {};
|
||||
using value_t = void;
|
||||
struct surrogate_t {};
|
||||
|
||||
static constexpr value_t wrap() noexcept {
|
||||
static constexpr surrogate_t wrap() noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
static constexpr void unwrap(surrogate_t) {
|
||||
}
|
||||
};
|
||||
template <typename T>
|
||||
struct result_trait<T> {
|
||||
using value_t = T;
|
||||
using surrogate_t = value_t;
|
||||
|
||||
static auto wrap(T arg) {
|
||||
static surrogate_t wrap(T arg) {
|
||||
return std::move(arg);
|
||||
}
|
||||
|
||||
template <typename R>
|
||||
static decltype(auto) unwrap(R&& unwrap) {
|
||||
return std::forward<R>(unwrap);
|
||||
}
|
||||
};
|
||||
template <typename First, typename Second, typename... Rest>
|
||||
struct result_trait<First, Second, Rest...> {
|
||||
using value_t = std::tuple<First, Second, Rest...>;
|
||||
using surrogate_t = value_t;
|
||||
|
||||
static std::tuple<First, Second, Rest...> wrap(First first, Second second,
|
||||
Rest... rest) {
|
||||
static surrogate_t wrap(First first, Second second, Rest... rest) {
|
||||
return std::make_tuple(std::move(first), std::move(second),
|
||||
std::move(rest)...);
|
||||
}
|
||||
|
||||
template <typename R>
|
||||
static decltype(auto) unwrap(R&& unwrap) {
|
||||
return std::forward<R>(unwrap);
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace cti
|
||||
|
||||
@ -39,7 +39,7 @@ cti::continuable<> resolve_async(S&& supplier) {
|
||||
co_await supplier();
|
||||
|
||||
// 1 args
|
||||
int a1 = co_await supplier(1);
|
||||
co_await supplier(1);
|
||||
EXPECT_EQ(a1, 1);
|
||||
|
||||
// 2-n args
|
||||
@ -66,7 +66,7 @@ cti::continuable<int, int, int, int> resolve_async_multiple(S&& supplier) {
|
||||
}
|
||||
|
||||
TYPED_TEST(single_dimension_tests, are_awaitable) {
|
||||
auto const& supply = [&](auto&&... args) {
|
||||
auto const supply = [&](auto&&... args) {
|
||||
// Supplies the current tested continuable
|
||||
return this->supply(std::forward<decltype(args)>(args)...);
|
||||
};
|
||||
|
||||
@ -28,8 +28,8 @@
|
||||
#include <test-continuable.hpp>
|
||||
|
||||
using cti::exception_t;
|
||||
using cti::result;
|
||||
using cti::make_result;
|
||||
using cti::result;
|
||||
|
||||
static int const CANARY = 373671;
|
||||
|
||||
@ -66,10 +66,17 @@ TYPED_TEST_CASE(result_all_tests, result_test_types);
|
||||
TYPED_TEST(result_all_tests, is_default_constructible) {
|
||||
TypeParam e;
|
||||
result<> e1;
|
||||
static_assert(std::is_void<decltype(e1.get_value())>::value);
|
||||
EXPECT_TRUE(e1.is_empty());
|
||||
|
||||
result<int> e2;
|
||||
EXPECT_TRUE(e2.is_empty());
|
||||
|
||||
result<int, int> e3;
|
||||
EXPECT_TRUE(e3.is_empty());
|
||||
|
||||
auto empty = make_result();
|
||||
EXPECT_TRUE(empty.is_empty());
|
||||
}
|
||||
|
||||
TYPED_TEST(result_all_tests, can_carry_errors) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user