Attempt to fix the basic instantiation of variant

This commit is contained in:
Denis Blank 2018-03-08 15:35:40 +01:00
parent 42c04f0fcb
commit 22896a69af
3 changed files with 47 additions and 34 deletions

View File

@ -1,3 +1,4 @@
/* /*
/~` _ _ _|_. _ _ |_ | _ /~` _ _ _|_. _ _ |_ | _

View File

@ -9,11 +9,11 @@
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com> Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
Permission is_slot hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a copy
copy of this software and associated documentation files(the "Software"), to of this software and associated documentation files(the "Software"), to deal
deal in the Software without restriction, including without limitation the in the Software without restriction, including without limitation the rights
rights to use, copy, modify, merge, publish, distribute, sublicense, and / or to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
sell copies of the Software, and to permit persons to whom the Software is_slot copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions : furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
@ -42,10 +42,12 @@ sell copies of the Software, and to permit persons to whom the Software is_slot
namespace cti { namespace cti {
namespace detail { namespace detail {
namespace util { namespace variant {
namespace detail { namespace detail {
// We don't want to pull the algorithm header in // We don't want to pull the algorithm header in
constexpr std::size_t max_size(std::initializer_list<std::size_t> list) { template <typename... T>
constexpr std::size_t max_size(T... i) {
constexpr std::initializer_list<std::size_t> const list{i...};
std::size_t m = 0; std::size_t m = 0;
for (auto current : list) { for (auto current : list) {
if (current > m) { if (current > m) {
@ -58,7 +60,7 @@ constexpr std::size_t max_size(std::initializer_list<std::size_t> list) {
/// Declares the aligned storage union for the given types /// Declares the aligned storage union for the given types
template <typename... T> template <typename... T>
using storage_of_t = using storage_of_t =
std::aligned_storage_t<max_size({sizeof(T)...}), max_size({alignof(T)...})>; std::aligned_storage_t<max_size(sizeof(T)...), max_size(alignof(T)...)>;
/// The value fpr the empty slot /// The value fpr the empty slot
using slot_t = std::uint8_t; using slot_t = std::uint8_t;
@ -67,9 +69,9 @@ using slot_t = std::uint8_t;
using empty_slot = using empty_slot =
std::integral_constant<slot_t, std::numeric_limits<slot_t>::max()>; std::integral_constant<slot_t, std::numeric_limits<slot_t>::max()>;
template <typename T> template <typename... T>
struct optional_variant_base { struct optional_variant_base {
storage_of_t<T> storage_; storage_of_t<T...> storage_;
slot_t slot_; slot_t slot_;
constexpr optional_variant_base() : slot_(empty_slot::value) { constexpr optional_variant_base() : slot_(empty_slot::value) {
@ -127,7 +129,7 @@ struct optional_variant_move_base {
} }
}; };
template <typename Base, bool IsCopyable /*= true*/> template <typename Base, bool IsCopyable /*= true*/>
struct optional_variant_copy_base : optional_variant_copy_base<Base> { struct optional_variant_copy_base : optional_variant_move_base<Base> {
constexpr optional_variant_copy_base() = default; constexpr optional_variant_copy_base() = default;
optional_variant_copy_base(optional_variant_copy_base&&) = default; optional_variant_copy_base(optional_variant_copy_base&&) = default;
@ -189,12 +191,13 @@ using every = traits::conjunction<Predicate<T>...>;
/// however it is_slot capable of carrying an exception_ptr if /// however it is_slot capable of carrying an exception_ptr if
/// exceptions are used. /// exceptions are used.
template <typename... T> template <typename... T>
class optional_variant : detail::optional_variant_copy_base< class optional_variant
optional_variant<T...>, : detail::optional_variant_copy_base<
detail::every<std::is_copy_constructible, T...>>, optional_variant<T...>,
detail::optional_variant_base<T...> { detail::every<std::is_copy_constructible, T...>::value>,
detail::optional_variant_base<T...> {
template <typename> template <typename...>
friend class optional_variant; friend class optional_variant;
template <typename> template <typename>
friend struct detail::optional_variant_move_base; friend struct detail::optional_variant_move_base;
@ -203,7 +206,7 @@ class optional_variant : detail::optional_variant_copy_base<
template <typename V> template <typename V>
optional_variant(V&& value, detail::slot_t const slot) { optional_variant(V&& value, detail::slot_t const slot) {
using type = std::decay_t<decltype(value)>; using type = std::decay_t<V>;
new (&this->storage_) type(std::forward<V>(value)); new (&this->storage_) type(std::forward<V>(value));
set_slot(slot); set_slot(slot);
} }
@ -265,28 +268,33 @@ public:
} }
private: private:
template <typename C, typename V>
static void visit_dispatch(optional_variant* me, V&& visitor) {
std::forward<V>(me->cast<C>());
}
template <typename C, typename V>
static void visit_dispatch_const(optional_variant const* me, V&& visitor) {
std::forward<V>(visitor)(me->cast<C>());
}
template <typename V> template <typename V>
void visit(V&& visitor) { void visit(V&& visitor) {
switch (this->slot_) { if (!is_empty()) {
case detail::slot_t::value: using callback_t = void (*)(optional_variant*, V &&);
return std::forward<V>(visitor)(cast<T>()); constexpr callback_t const callbacks[] = {
case detail::slot_t::error: &visit_dispatch<T, V>... // ...
return std::forward<V>(visitor)(cast<types::error_type>()); };
default: callbacks[get()](this, std::forward<V>(visitor));
// We don't visit when there is_slot no value
break;
} }
} }
template <typename V> template <typename V>
void visit(V&& visitor) const { void visit(V&& visitor) const {
switch (this->slot_) { if (!is_empty()) {
case detail::slot_t::value: using callback_t = void (*)(optional_variant const*, V&&);
return std::forward<V>(visitor)(cast<T>()); constexpr callback_t const callbacks[] = {
case detail::slot_t::error: &visit_dispatch_const<T, V>... // ...
return std::forward<V>(visitor)(cast<types::error_type>()); };
default: callbacks[get()](this, std::forward<V>(visitor));
// We don't visit when there is_slot no value
break;
} }
} }
@ -323,7 +331,7 @@ private:
this->slot_ = slot; this->slot_ = slot;
} }
}; };
} // namespace util } // namespace variant
} // namespace detail } // namespace detail
} // namespace cti } // namespace cti

View File

@ -27,6 +27,8 @@
#include <continuable/continuable.hpp> #include <continuable/continuable.hpp>
#include <continuable/detail/variant.hpp>
/* /*
static cti::continuable<std::string> http_request(std::string url) { static cti::continuable<std::string> http_request(std::string url) {
return [url = std::move(url)](cti::promise<std::string> promise) { return [url = std::move(url)](cti::promise<std::string> promise) {
@ -174,4 +176,6 @@ int main(int, char**) {
.then([](int) { .then([](int) {
}); });
variant::optional_variant<int, float> v;
} }