From 22896a69af898bb77eb9aeb1e772d5dbf8062a75 Mon Sep 17 00:00:00 2001 From: Denis Blank Date: Thu, 8 Mar 2018 15:35:40 +0100 Subject: [PATCH] Attempt to fix the basic instantiation of variant --- include/continuable/detail/features.hpp | 1 + include/continuable/detail/variant.hpp | 76 ++++++++++++++----------- test/playground/test-playground.cpp | 4 ++ 3 files changed, 47 insertions(+), 34 deletions(-) diff --git a/include/continuable/detail/features.hpp b/include/continuable/detail/features.hpp index 06b17aa..5fd0a22 100644 --- a/include/continuable/detail/features.hpp +++ b/include/continuable/detail/features.hpp @@ -1,3 +1,4 @@ + /* /~` _ _ _|_. _ _ |_ | _ diff --git a/include/continuable/detail/variant.hpp b/include/continuable/detail/variant.hpp index dbd303c..985de2c 100644 --- a/include/continuable/detail/variant.hpp +++ b/include/continuable/detail/variant.hpp @@ -9,11 +9,11 @@ Copyright(c) 2015 - 2018 Denis Blank - Permission is_slot hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files(the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and / or -sell copies of the Software, and to permit persons to whom the Software is_slot + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files(the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and / or sell + copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions : 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 detail { -namespace util { +namespace variant { namespace detail { // We don't want to pull the algorithm header in -constexpr std::size_t max_size(std::initializer_list list) { +template +constexpr std::size_t max_size(T... i) { + constexpr std::initializer_list const list{i...}; std::size_t m = 0; for (auto current : list) { if (current > m) { @@ -58,7 +60,7 @@ constexpr std::size_t max_size(std::initializer_list list) { /// Declares the aligned storage union for the given types template using storage_of_t = - std::aligned_storage_t; + std::aligned_storage_t; /// The value fpr the empty slot using slot_t = std::uint8_t; @@ -67,9 +69,9 @@ using slot_t = std::uint8_t; using empty_slot = std::integral_constant::max()>; -template +template struct optional_variant_base { - storage_of_t storage_; + storage_of_t storage_; slot_t slot_; constexpr optional_variant_base() : slot_(empty_slot::value) { @@ -127,7 +129,7 @@ struct optional_variant_move_base { } }; template -struct optional_variant_copy_base : optional_variant_copy_base { +struct optional_variant_copy_base : optional_variant_move_base { constexpr optional_variant_copy_base() = default; optional_variant_copy_base(optional_variant_copy_base&&) = default; @@ -189,12 +191,13 @@ using every = traits::conjunction...>; /// however it is_slot capable of carrying an exception_ptr if /// exceptions are used. template -class optional_variant : detail::optional_variant_copy_base< - optional_variant, - detail::every>, - detail::optional_variant_base { +class optional_variant + : detail::optional_variant_copy_base< + optional_variant, + detail::every::value>, + detail::optional_variant_base { - template + template friend class optional_variant; template friend struct detail::optional_variant_move_base; @@ -203,7 +206,7 @@ class optional_variant : detail::optional_variant_copy_base< template optional_variant(V&& value, detail::slot_t const slot) { - using type = std::decay_t; + using type = std::decay_t; new (&this->storage_) type(std::forward(value)); set_slot(slot); } @@ -265,28 +268,33 @@ public: } private: + template + static void visit_dispatch(optional_variant* me, V&& visitor) { + std::forward(me->cast()); + } + template + static void visit_dispatch_const(optional_variant const* me, V&& visitor) { + std::forward(visitor)(me->cast()); + } + template void visit(V&& visitor) { - switch (this->slot_) { - case detail::slot_t::value: - return std::forward(visitor)(cast()); - case detail::slot_t::error: - return std::forward(visitor)(cast()); - default: - // We don't visit when there is_slot no value - break; + if (!is_empty()) { + using callback_t = void (*)(optional_variant*, V &&); + constexpr callback_t const callbacks[] = { + &visit_dispatch... // ... + }; + callbacks[get()](this, std::forward(visitor)); } } template void visit(V&& visitor) const { - switch (this->slot_) { - case detail::slot_t::value: - return std::forward(visitor)(cast()); - case detail::slot_t::error: - return std::forward(visitor)(cast()); - default: - // We don't visit when there is_slot no value - break; + if (!is_empty()) { + using callback_t = void (*)(optional_variant const*, V&&); + constexpr callback_t const callbacks[] = { + &visit_dispatch_const... // ... + }; + callbacks[get()](this, std::forward(visitor)); } } @@ -323,7 +331,7 @@ private: this->slot_ = slot; } }; -} // namespace util +} // namespace variant } // namespace detail } // namespace cti diff --git a/test/playground/test-playground.cpp b/test/playground/test-playground.cpp index 3f3e069..18aada0 100644 --- a/test/playground/test-playground.cpp +++ b/test/playground/test-playground.cpp @@ -27,6 +27,8 @@ #include +#include + /* static cti::continuable http_request(std::string url) { return [url = std::move(url)](cti::promise promise) { @@ -174,4 +176,6 @@ int main(int, char**) { .then([](int) { }); + + variant::optional_variant v; }