From 25914d8dd2f7a536f3aa74b38aae67fb94ce2604 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Sun, 28 May 2017 20:09:05 -0700 Subject: [PATCH] working on implementing util::variant --- src/util/CMakeLists.txt | 3 +- src/util/variant.h | 145 +++++++++++++++++++++++++++++++++++++--- src/util/void_t.cpp | 23 +++++++ src/util/void_t.h | 45 +++++++++++++ 4 files changed, 207 insertions(+), 9 deletions(-) create mode 100644 src/util/void_t.cpp create mode 100644 src/util/void_t.h diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 854e345..ffe89a1 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -22,5 +22,6 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR) set(sources in_place.cpp is_referenceable.cpp is_swappable.cpp - optional.cpp) + optional.cpp + void_t.cpp) add_library(util STATIC ${sources}) diff --git a/src/util/variant.h b/src/util/variant.h index 13b8186..e2bf17d 100644 --- a/src/util/variant.h +++ b/src/util/variant.h @@ -31,6 +31,7 @@ #include #include #include "in_place.h" +#include "void_t.h" namespace vulkan_cpu { @@ -149,6 +150,46 @@ using variant_alternative_t = typename variant_alternative::type; namespace detail { +template +struct variant_identity_type +{ + typedef T type; +}; + +template +struct variant_hypothetical_overload_set; + +template +struct variant_hypothetical_overload_set + : public variant_hypothetical_overload_set +{ + using variant_hypothetical_overload_set::fn; + static variant_identity_type fn(T); // not implemented +}; + +template <> +struct variant_hypothetical_overload_set +{ + static void fn(); // not implemented +}; + +template +struct variant_conversion_deduce_type_helper; + +template +struct variant_conversion_deduce_type_helper::fn( + std::declval()))::type>> +{ + typedef typename decltype( + variant_hypothetical_overload_set::fn(std::declval()))::type type; +}; + +template +using variant_conversion_deduce_type = + typename variant_conversion_deduce_type_helper::type; + template union variant_values { @@ -157,6 +198,11 @@ union variant_values static constexpr bool is_move_constructible = true; static constexpr bool is_nothrow_copy_constructible = true; static constexpr bool is_nothrow_move_constructible = true; + static constexpr bool is_copy_assignable = true; + static constexpr bool is_move_assignable = true; + static constexpr bool is_nothrow_copy_assignable = true; + static constexpr bool is_nothrow_move_assignable = true; + static constexpr bool is_trivially_destructible = true; variant_values() = delete; template constexpr variant_values(in_place_index_t) noexcept : value() @@ -173,6 +219,15 @@ union variant_values void move_construct(variant_values &&rt, std::size_t index) noexcept { } + void copy_assign(const variant_values &rt, std::size_t index) noexcept + { + } + void move_assign(variant_values &&rt, std::size_t index) noexcept + { + } + void destroy(std::size_t index) noexcept + { + } }; template @@ -194,6 +249,19 @@ union variant_values static constexpr bool is_nothrow_move_constructible = std::is_nothrow_move_constructible::value && variant_values::is_nothrow_move_constructible; + static constexpr bool is_copy_assignable = + std::is_copy_assignable::value && variant_values::is_copy_assignable; + static constexpr bool is_move_assignable = + std::is_move_assignable::value && variant_values::is_move_assignable; + static constexpr bool is_nothrow_copy_assignable = + std::is_nothrow_copy_assignable::value + && variant_values::is_nothrow_copy_assignable; + static constexpr bool is_nothrow_move_assignable = + std::is_nothrow_move_assignable::value + && variant_values::is_nothrow_move_assignable; + static constexpr bool is_trivially_destructible = + std::is_trivially_destructible::value + && variant_values::is_trivially_destructible; template ::value>::type> constexpr variant_values() noexcept(std::is_nothrow_default_constructible::value) @@ -230,20 +298,44 @@ union variant_values return variant_npos; return next + 1; } - void copy_construct(const variant_values &rt, std::size_t index) noexcept + void copy_construct(const variant_values &rt, + std::size_t index) noexcept(is_nothrow_copy_constructible) { if(index == 0) new(const_cast(std::addressof(current_value))) T(rt.current_value); else other_values.copy_construct(rt.other_values, index - 1); } - void move_construct(variant_values &&rt, std::size_t index) noexcept + void move_construct(variant_values &&rt, + std::size_t index) noexcept(is_nothrow_move_constructible) { if(index == 0) new(const_cast(std::addressof(current_value))) T(std::move(rt.current_value)); else other_values.move_construct(std::move(rt.other_values), index - 1); } + void copy_assign(const variant_values &rt, + std::size_t index) noexcept(is_nothrow_copy_assignable) + { + if(index == 0) + current_value = rt.current_value; + else + other_values.copy_assign(rt.other_values, index - 1); + } + void move_assign(variant_values &&rt, std::size_t index) noexcept(is_nothrow_move_assignable) + { + if(index == 0) + current_value = std::move(rt.current_value); + else + other_values.move_assign(std::move(rt.other_values), index - 1); + } + void destruct(std::size_t index) noexcept + { + if(index == 0) + current_value.~T(); + else + other_values.destruct(index - 1); + } }; template @@ -291,25 +383,62 @@ struct variant_index_type index_value = new_value; } }; + +template +struct variant_base +{ + detail::variant_values values; + detail::variant_index_type index_value; + template + constexpr variant_base(std::size_t index_value, Args &&... args) // + noexcept(noexcept(new(std::declval()) + detail::variant_values(std::declval()...))) + : values(std::forward(args)...), index_value(index_value) + { + } + ~variant_base() + { + values.destroy(index_value.get()); + } +}; + +template +struct variant_base +{ + detail::variant_values values; + detail::variant_index_type index_value; + template + constexpr variant_base(std::size_t index_value, Args &&... args) // + noexcept(noexcept(new(std::declval()) + detail::variant_values(std::declval()...))) + : values(std::forward(args)...), index_value(index_value) + { + } + ~variant_base() = default; +}; } template class variant + : private detail::variant_base::is_trivially_destructible, + Types...> { static_assert(sizeof...(Types) > 0, "empty variant is not permitted"); private: typedef typename detail::variant_values::type_0 type_0; + typedef detail::variant_base::is_trivially_destructible, + Types...> base; private: - detail::variant_values values; - detail::variant_index_type index_value; + using base::values; + using base::index_value; public: template < typename = typename std::enable_if::value>::value> constexpr variant() noexcept(std::is_nothrow_default_constructible::value) - : values(), index_value(0) + : base(0) { } template < @@ -317,7 +446,7 @@ public: typename std::enable_if::is_copy_constructible>::type> variant(const variant &rt) noexcept( detail::variant_values::is_nothrow_copy_constructible) - : values(in_place_index()), index_value(variant_npos) + : base(variant_npos, in_place_index()) { values.copy_construct(rt.values, rt.index_value.get()); index_value = rt.index_value; @@ -326,7 +455,7 @@ public: typename = typename std::enable_if::is_move_constructible>::type> variant(variant &&rt) noexcept(detail::variant_values::is_nothrow_move_constructible) - : values(in_place_index()), index_value(variant_npos) + : base(variant_npos, in_place_index()) { values.move_construct(std::move(rt.values), rt.index_value.get()); index_value = rt.index_value; @@ -339,7 +468,7 @@ public: constexpr explicit variant(in_place_index_t, Args &&... args) noexcept( std::is_nothrow_constructible>, Args...>::value) - : values(in_place_index, std::forward(args)...), index_value(index) + : base(index, in_place_index, std::forward(args)...) { } #error finish diff --git a/src/util/void_t.cpp b/src/util/void_t.cpp new file mode 100644 index 0000000..5d70f40 --- /dev/null +++ b/src/util/void_t.cpp @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Jacob Lifshay + * + * 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 all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +#include "void_t.h" diff --git a/src/util/void_t.h b/src/util/void_t.h new file mode 100644 index 0000000..1e51882 --- /dev/null +++ b/src/util/void_t.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Jacob Lifshay + * + * 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 all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef SOURCE_UTIL_VOID_T_H_ +#define SOURCE_UTIL_VOID_T_H_ + +namespace vulkan_cpu +{ +namespace util +{ +namespace detail +{ +template +struct void_t_helper +{ + typedef void type; +}; +} + +template +using void_t = typename detail::void_t_helper::type; +} +} + +#endif /* SOURCE_UTIL_VOID_T_H_ */ -- 2.30.2