Fix the build

This commit is contained in:
Denis Blank 2017-11-30 02:16:49 +01:00
parent 8b99c72071
commit bf89a98d60
4 changed files with 68 additions and 35 deletions

View File

@ -54,7 +54,7 @@ class awaitable {
Continuable continuable_; Continuable continuable_;
/// A cache which is used to pass the result of the continuation /// A cache which is used to pass the result of the continuation
/// to the /// to the
expected::expected<int /*TODO*/> cache_; util::expected<int /*TODO*/> cache_;
public: public:
/// Since continuables are evaluated lazily we are not /// Since continuables are evaluated lazily we are not

View File

@ -31,6 +31,7 @@
#ifndef CONTINUABLE_DETAIL_EXPECTED_HPP_INCLUDED__ #ifndef CONTINUABLE_DETAIL_EXPECTED_HPP_INCLUDED__
#define CONTINUABLE_DETAIL_EXPECTED_HPP_INCLUDED__ #define CONTINUABLE_DETAIL_EXPECTED_HPP_INCLUDED__
#include <cassert>
#include <memory> #include <memory>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
@ -55,25 +56,25 @@ template <typename Base, bool IsCopyable /*= true*/>
struct expected_copy_base { struct expected_copy_base {
constexpr expected_copy_base() = default; constexpr expected_copy_base() = default;
expected_copy_base(expected_copy_base const&) = default; expected_copy_base(expected_copy_base&&) = default;
explicit expected_copy_base(expected_copy_base&& right) explicit expected_copy_base(expected_copy_base const& right)
// TODO noexcept(Base::is_nothrow_move_constructible) // TODO noexcept(Base::is_nothrow_move_constructible)
{ {
Base& me = *static_cast<Base*>(this); Base& me = *static_cast<Base*>(this);
Base& other = *static_cast<Base*>(&right); Base const& other = *static_cast<Base const*>(&right);
other.visit([&](auto&& value) { other.visit([&](auto&& value) {
// ... // ...
me.init(std::move(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&&) = default;
expected_copy_base& operator=(expected_copy_base&& right) expected_copy_base& operator=(expected_copy_base const& right)
// TODO noexcept(Base::is_nothrow_move_constructible) // TODO noexcept(Base::is_nothrow_move_constructible)
{ {
Base& me = *static_cast<Base*>(this); Base& me = *static_cast<Base*>(this);
Base& other = *static_cast<Base*>(&right); Base const& other = *static_cast<Base const*>(&right);
me.weak_destroy(); me.weak_destroy();
@ -81,7 +82,7 @@ struct expected_copy_base {
// ... // ...
me.init(std::move(value)); me.init(std::move(value));
}); });
set(other.get()); me.set(other.get());
return *this; return *this;
} }
}; };
@ -98,19 +99,19 @@ template <typename Base>
struct expected_move_base { struct expected_move_base {
constexpr expected_move_base() = default; constexpr expected_move_base() = default;
expected_move_base(expected_move_base&&) = default; expected_move_base(expected_move_base const&) = default;
explicit expected_move_base(expected_move_base const& right) { explicit expected_move_base(expected_move_base&& right) {
Base& me = *static_cast<Base*>(this); Base& me = *static_cast<Base*>(this);
Base const& other = *static_cast<Base const*>(&right); Base& other = *static_cast<Base*>(&right);
other.visit([&](auto&& value) { other.visit([&](auto&& value) {
// ... // ...
me.init(std::move(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&) = default;
expected_move_base& operator=(expected_move_base const& right) { expected_move_base& operator=(expected_move_base&& right) {
Base& me = *static_cast<Base*>(this); Base& me = *static_cast<Base*>(this);
Base const& other = *static_cast<Base*>(&right); Base const& other = *static_cast<Base*>(&right);
@ -120,7 +121,7 @@ struct expected_move_base {
// ... // ...
me.init(std::move(value)); me.init(std::move(value));
}); });
set(other.consume()); me.set(other.consume());
return *this; return *this;
} }
}; };
@ -137,9 +138,11 @@ class expected
std::is_copy_constructible<T>::value> { std::is_copy_constructible<T>::value> {
template <typename> template <typename>
friend class expected_move_base; friend class expected;
template <typename>
friend struct detail::expected_move_base;
template <typename, bool> template <typename, bool>
friend class expected_copy_base; friend struct detail::expected_copy_base;
detail::storage_of_t<T> storage_; detail::storage_of_t<T> storage_;
detail::slot_t slot_ = detail::slot_t::empty; detail::slot_t slot_ = detail::slot_t::empty;
@ -152,6 +155,8 @@ class expected
} }
public: public:
expected() = default;
explicit expected(T value) // explicit expected(T value) //
: expected(std::move(value), detail::slot_t::value) { : expected(std::move(value), detail::slot_t::value) {
} }
@ -165,25 +170,30 @@ public:
expected& operator=(expected&& right) = default; expected& operator=(expected&& right) = default;
bool is_value() const noexcept { bool is_value() const noexcept {
assert(!is_empty());
return slot_ == detail::slot_t::value; return slot_ == detail::slot_t::value;
} }
bool is_error() const noexcept { bool is_error() const noexcept {
assert(!is_empty());
return slot_ == detail::slot_t::error; return slot_ == detail::slot_t::error;
} }
protected: explicit constexpr operator bool() const noexcept {
bool is_empty() const noexcept { return is_value();
return slot_ == detail::slot_t::empty; }
T& operator*() const noexcept {
assert(!is_value());
return cast<T>();
} }
private:
template <typename V> template <typename V>
void visit(V&& visitor) { void visit(V&& visitor) {
switch (slot_) { switch (slot_) {
case detail::slot_t::value: case detail::slot_t::value:
return std::forward<V>(visitor)(static_cast<T*>(&storage_)); return std::forward<V>(visitor)(cast<T>());
case detail::slot_t::error: case detail::slot_t::error:
return std::forward<V>(visitor)( return std::forward<V>(visitor)(cast<types::error_type>());
static_cast<types::error_type*>(&storage_));
default: default:
// We don't visit when there is no value // We don't visit when there is no value
break; break;
@ -193,20 +203,33 @@ protected:
void visit(V&& visitor) const { void visit(V&& visitor) const {
switch (slot_) { switch (slot_) {
case detail::slot_t::value: case detail::slot_t::value:
return std::forward<V>(visitor)(static_cast<T*>(&storage_)); return std::forward<V>(visitor)(cast<T>());
case detail::slot_t::error: case detail::slot_t::error:
return std::forward<V>(visitor)( return std::forward<V>(visitor)(cast<types::error_type>());
static_cast<types::error_type*>(&storage_));
default: default:
// We don't visit when there is no value // We don't visit when there is no value
break; break;
} }
} }
bool is_empty() const noexcept {
return slot_ == detail::slot_t::empty;
}
template <typename V> template <typename V>
void init(V&& value, detail::slot_t const slot) { V& cast() noexcept {
assert(is(slot_t::empty)); assert(!is_empty());
set(slot); return *reinterpret_cast<V*>(&storage_);
}
template <typename V>
V const& cast() const noexcept {
assert(!is_empty());
return *reinterpret_cast<V const*>(&storage_);
}
template <typename V>
void init(V&& value) {
assert(is_empty());
using type = std::decay_t<decltype(value)>; using type = std::decay_t<decltype(value)>;
auto storage = &storage_; auto storage = &storage_;
new (storage) type(std::forward<V>(value)); new (storage) type(std::forward<V>(value));
@ -237,7 +260,7 @@ protected:
void set(detail::slot_t const slot) { void set(detail::slot_t const slot) {
slot_ = slot; slot_ = slot;
} }
detail::slot_t consume(detail::slot_t slot) { detail::slot_t consume() {
auto const current = get(); auto const current = get();
destroy(); destroy();
return current; return current;

View File

@ -66,7 +66,7 @@ auto mk() {
void teststhh() { void teststhh() {
auto c = mk(); auto c = mk();
co_await std::move(c); // co_await std::move(c);
} }
#endif // CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE #endif // CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE

View File

@ -23,11 +23,21 @@
#include "test-continuable.hpp" #include "test-continuable.hpp"
using cti::detail::util::expected;
using cti::detail::types::error_type; using cti::detail::types::error_type;
using cti::detail::util::expected;
TEST(expected_tests, can_carry_errors) { TEST(expected_tests, can_carry_errors) {
expected<int> e(1); {
expected<int> e(1);
EXPECT_TRUE(bool(e));
EXPECT_TRUE(e.is_value());
EXPECT_FALSE(e.is_error());
}
auto i = e; {
expected<int> e(error_type{});
EXPECT_FALSE(bool(e));
EXPECT_FALSE(e.is_value());
EXPECT_TRUE(e.is_error());
}
} }