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