diff --git a/include/continuable/detail/awaiting.hpp b/include/continuable/detail/awaiting.hpp index 5db87ce..2bf78e8 100644 --- a/include/continuable/detail/awaiting.hpp +++ b/include/continuable/detail/awaiting.hpp @@ -54,7 +54,7 @@ class awaitable { Continuable continuable_; /// A cache which is used to pass the result of the continuation /// to the - expected::expected cache_; + util::expected cache_; public: /// Since continuables are evaluated lazily we are not diff --git a/include/continuable/detail/expected.hpp b/include/continuable/detail/expected.hpp index 6b02524..ac0245f 100644 --- a/include/continuable/detail/expected.hpp +++ b/include/continuable/detail/expected.hpp @@ -31,6 +31,7 @@ #ifndef CONTINUABLE_DETAIL_EXPECTED_HPP_INCLUDED__ #define CONTINUABLE_DETAIL_EXPECTED_HPP_INCLUDED__ +#include #include #include #include @@ -55,25 +56,25 @@ template struct expected_copy_base { constexpr expected_copy_base() = default; - expected_copy_base(expected_copy_base const&) = default; - explicit expected_copy_base(expected_copy_base&& right) + expected_copy_base(expected_copy_base&&) = default; + explicit expected_copy_base(expected_copy_base const& right) // TODO noexcept(Base::is_nothrow_move_constructible) { Base& me = *static_cast(this); - Base& other = *static_cast(&right); + Base const& other = *static_cast(&right); other.visit([&](auto&& value) { // ... me.init(std::move(value)); }); - set(other.get()); + me.set(other.get()); } - expected_copy_base& operator=(expected_copy_base const&) = default; - expected_copy_base& operator=(expected_copy_base&& right) + expected_copy_base& operator=(expected_copy_base&&) = default; + expected_copy_base& operator=(expected_copy_base const& right) // TODO noexcept(Base::is_nothrow_move_constructible) { Base& me = *static_cast(this); - Base& other = *static_cast(&right); + Base const& other = *static_cast(&right); me.weak_destroy(); @@ -81,7 +82,7 @@ struct expected_copy_base { // ... me.init(std::move(value)); }); - set(other.get()); + me.set(other.get()); return *this; } }; @@ -98,19 +99,19 @@ template struct expected_move_base { constexpr expected_move_base() = default; - expected_move_base(expected_move_base&&) = default; - explicit expected_move_base(expected_move_base const& right) { + expected_move_base(expected_move_base const&) = default; + explicit expected_move_base(expected_move_base&& right) { Base& me = *static_cast(this); - Base const& other = *static_cast(&right); + Base& other = *static_cast(&right); other.visit([&](auto&& value) { // ... me.init(std::move(value)); }); - set(other.consume()); + me.set(other.consume()); } - expected_move_base& operator=(expected_move_base&&) = default; - expected_move_base& operator=(expected_move_base const& right) { + expected_move_base& operator=(expected_move_base const&) = default; + expected_move_base& operator=(expected_move_base&& right) { Base& me = *static_cast(this); Base const& other = *static_cast(&right); @@ -120,7 +121,7 @@ struct expected_move_base { // ... me.init(std::move(value)); }); - set(other.consume()); + me.set(other.consume()); return *this; } }; @@ -137,9 +138,11 @@ class expected std::is_copy_constructible::value> { template - friend class expected_move_base; + friend class expected; + template + friend struct detail::expected_move_base; template - friend class expected_copy_base; + friend struct detail::expected_copy_base; detail::storage_of_t storage_; detail::slot_t slot_ = detail::slot_t::empty; @@ -152,6 +155,8 @@ class expected } public: + expected() = default; + explicit expected(T value) // : expected(std::move(value), detail::slot_t::value) { } @@ -165,25 +170,30 @@ public: expected& operator=(expected&& right) = default; bool is_value() const noexcept { + assert(!is_empty()); return slot_ == detail::slot_t::value; } bool is_error() const noexcept { + assert(!is_empty()); return slot_ == detail::slot_t::error; } -protected: - bool is_empty() const noexcept { - return slot_ == detail::slot_t::empty; + explicit constexpr operator bool() const noexcept { + return is_value(); + } + T& operator*() const noexcept { + assert(!is_value()); + return cast(); } +private: template void visit(V&& visitor) { switch (slot_) { case detail::slot_t::value: - return std::forward(visitor)(static_cast(&storage_)); + return std::forward(visitor)(cast()); case detail::slot_t::error: - return std::forward(visitor)( - static_cast(&storage_)); + return std::forward(visitor)(cast()); default: // We don't visit when there is no value break; @@ -193,20 +203,33 @@ protected: void visit(V&& visitor) const { switch (slot_) { case detail::slot_t::value: - return std::forward(visitor)(static_cast(&storage_)); + return std::forward(visitor)(cast()); case detail::slot_t::error: - return std::forward(visitor)( - static_cast(&storage_)); + return std::forward(visitor)(cast()); default: // We don't visit when there is no value break; } } + bool is_empty() const noexcept { + return slot_ == detail::slot_t::empty; + } + template - void init(V&& value, detail::slot_t const slot) { - assert(is(slot_t::empty)); - set(slot); + V& cast() noexcept { + assert(!is_empty()); + return *reinterpret_cast(&storage_); + } + template + V const& cast() const noexcept { + assert(!is_empty()); + return *reinterpret_cast(&storage_); + } + + template + void init(V&& value) { + assert(is_empty()); using type = std::decay_t; auto storage = &storage_; new (storage) type(std::forward(value)); @@ -237,7 +260,7 @@ protected: void set(detail::slot_t const slot) { slot_ = slot; } - detail::slot_t consume(detail::slot_t slot) { + detail::slot_t consume() { auto const current = get(); destroy(); return current; diff --git a/test/unit-test/test-continuable-await.cpp b/test/unit-test/test-continuable-await.cpp index 70afb14..2d9c964 100644 --- a/test/unit-test/test-continuable-await.cpp +++ b/test/unit-test/test-continuable-await.cpp @@ -66,7 +66,7 @@ auto mk() { void teststhh() { auto c = mk(); - co_await std::move(c); + // co_await std::move(c); } #endif // CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE diff --git a/test/unit-test/test-continuable-expected.cpp b/test/unit-test/test-continuable-expected.cpp index 9926db0..1eabc2e 100644 --- a/test/unit-test/test-continuable-expected.cpp +++ b/test/unit-test/test-continuable-expected.cpp @@ -23,11 +23,21 @@ #include "test-continuable.hpp" -using cti::detail::util::expected; using cti::detail::types::error_type; +using cti::detail::util::expected; TEST(expected_tests, can_carry_errors) { - expected e(1); + { + expected e(1); + EXPECT_TRUE(bool(e)); + EXPECT_TRUE(e.is_value()); + EXPECT_FALSE(e.is_error()); + } - auto i = e; + { + expected e(error_type{}); + EXPECT_FALSE(bool(e)); + EXPECT_FALSE(e.is_value()); + EXPECT_TRUE(e.is_error()); + } }