finished members of util::variant; need to finish the rest of variant.h
authorJacob Lifshay <programmerjake@gmail.com>
Thu, 1 Jun 2017 00:57:43 +0000 (17:57 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Thu, 1 Jun 2017 00:59:04 +0000 (17:59 -0700)
src/util/CMakeLists.txt
src/util/copy_cv_ref.cpp [new file with mode: 0644]
src/util/copy_cv_ref.h [new file with mode: 0644]
src/util/is_swappable.h
src/util/variant.h

index ffe89a1f5b92ec34fe3492952badc285fe9d4747..a775745783a32ec8ca2f866d63cd0fe699f4afac 100644 (file)
@@ -19,7 +19,8 @@
 # SOFTWARE.
 #
 cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
-set(sources in_place.cpp
+set(sources copy_cv_ref.cpp
+            in_place.cpp
             is_referenceable.cpp
             is_swappable.cpp
             optional.cpp
diff --git a/src/util/copy_cv_ref.cpp b/src/util/copy_cv_ref.cpp
new file mode 100644 (file)
index 0000000..7f5606a
--- /dev/null
@@ -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 "copy_cv_ref.h"
diff --git a/src/util/copy_cv_ref.h b/src/util/copy_cv_ref.h
new file mode 100644 (file)
index 0000000..ce68ca6
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * 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_COPY_CV_REF_H_
+#define SOURCE_UTIL_COPY_CV_REF_H_
+
+namespace vulkan_cpu
+{
+namespace util
+{
+template <typename Source, typename Dest>
+struct copy_const
+{
+    typedef Dest type;
+};
+
+template <typename Source, typename Dest>
+struct copy_const<const Source, Dest>
+{
+    typedef const Dest type;
+};
+
+template <typename Source, typename Dest>
+using copy_const_t = typename copy_const<Source, Dest>::type;
+
+template <typename Source, typename Dest>
+struct copy_volatile
+{
+    typedef Dest type;
+};
+
+template <typename Source, typename Dest>
+struct copy_volatile<volatile Source, Dest>
+{
+    typedef volatile Dest type;
+};
+
+template <typename Source, typename Dest>
+using copy_volatile_t = typename copy_volatile<Source, Dest>::type;
+
+template <typename Source, typename Dest>
+struct copy_cv
+{
+    typedef copy_const_t<Source, copy_volatile_t<Source, Dest>> type;
+};
+
+template <typename Source, typename Dest>
+using copy_cv_t = typename copy_cv<Source, Dest>::type;
+
+template <typename Source, typename Dest>
+struct copy_ref
+{
+    typedef Dest type;
+};
+
+template <typename Source, typename Dest>
+struct copy_ref<Source &, Dest>
+{
+    typedef Dest &type;
+};
+
+template <typename Source, typename Dest>
+struct copy_ref<Source &&, Dest>
+{
+    typedef Dest &&type;
+};
+
+template <typename Source, typename Dest>
+using copy_ref_t = typename copy_ref<Source, Dest>::type;
+
+template <typename Source, typename Dest>
+struct copy_cv_ref
+{
+    typedef copy_cv_t<Source, copy_ref_t<Source, Dest>> type;
+};
+
+template <typename Source, typename Dest>
+using copy_cv_ref_t = typename copy_cv_ref<Source, Dest>::type;
+}
+}
+
+#endif /* SOURCE_UTIL_COPY_CV_REF_H_ */
index b744200ae6de36b8bcb4cc21b6ba00bc618da0a1..483fb33c8913ef1b7b95ac3ff8693381c8e486c5 100644 (file)
@@ -80,6 +80,9 @@ struct is_swappable_with
 {
 };
 
+template <typename T, typename U>
+constexpr bool is_swappable_with_v = is_swappable_with<T, U>::value;
+
 template <typename T, typename U>
 struct is_nothrow_swappable_with
     : public std::integral_constant<bool,
@@ -88,6 +91,9 @@ struct is_nothrow_swappable_with
 {
 };
 
+template <typename T, typename U>
+constexpr bool is_nothrow_swappable_with_v = is_nothrow_swappable_with<T, U>::value;
+
 namespace detail
 {
 template <typename T, bool Is_Referenceable = is_referenceable<T>::value>
@@ -120,11 +126,17 @@ struct is_swappable : public std::integral_constant<bool, detail::is_swappable_h
 {
 };
 
+template <typename T>
+constexpr bool is_swappable_v = is_swappable<T>::value;
+
 template <typename T>
 struct is_nothrow_swappable
     : public std::integral_constant<bool, detail::is_nothrow_swappable_helper<T>::value>
 {
 };
+
+template <typename T>
+constexpr bool is_nothrow_swappable_v = is_nothrow_swappable<T>::value;
 }
 }
 
index 8a0d03d4e60e269e7f1aaeedff9618aad16fe8b4..19ef314cfedefd84a827fe02ed14d8c72f06d7b6 100644 (file)
@@ -32,6 +32,8 @@
 #include <new>
 #include "in_place.h"
 #include "void_t.h"
+#include "copy_cv_ref.h"
+#include "is_swappable.h"
 
 namespace vulkan_cpu
 {
@@ -186,6 +188,8 @@ union variant_values
     static constexpr bool is_nothrow_copy_assignable = true;
     static constexpr bool is_nothrow_move_assignable = true;
     static constexpr bool is_trivially_destructible = true;
+    static constexpr bool is_swappable = true;
+    static constexpr bool is_nothrow_swappable = true;
     variant_values() = delete;
     template <std::size_t index>
     constexpr variant_values(in_place_index_t<index>) noexcept : value()
@@ -211,6 +215,9 @@ union variant_values
     void destroy(std::size_t index) noexcept
     {
     }
+    void swap(variant_values &rt, std::size_t index) noexcept
+    {
+    }
 };
 
 template <typename T, typename... Types>
@@ -232,19 +239,28 @@ union variant_values<T, Types...>
     static constexpr bool is_nothrow_move_constructible =
         std::is_nothrow_move_constructible<T>::value
         && variant_values<Types...>::is_nothrow_move_constructible;
-    static constexpr bool is_copy_assignable =
-        std::is_copy_assignable<T>::value && variant_values<Types...>::is_copy_assignable;
-    static constexpr bool is_move_assignable =
-        std::is_move_assignable<T>::value && variant_values<Types...>::is_move_assignable;
+    static constexpr bool is_copy_assignable = std::is_copy_assignable<T>::value
+                                               && std::is_copy_constructible<T>::value
+                                               && variant_values<Types...>::is_copy_assignable;
+    static constexpr bool is_move_assignable = std::is_move_assignable<T>::value
+                                               && std::is_move_constructible<T>::value
+                                               && variant_values<Types...>::is_move_assignable;
     static constexpr bool is_nothrow_copy_assignable =
-        std::is_nothrow_copy_assignable<T>::value
+        std::is_nothrow_copy_assignable<T>::value && std::is_nothrow_copy_constructible<T>::value
         && variant_values<Types...>::is_nothrow_copy_assignable;
     static constexpr bool is_nothrow_move_assignable =
-        std::is_nothrow_move_assignable<T>::value
+        std::is_nothrow_move_assignable<T>::value && std::is_nothrow_move_constructible<T>::value
         && variant_values<Types...>::is_nothrow_move_assignable;
     static constexpr bool is_trivially_destructible =
         std::is_trivially_destructible<T>::value
         && variant_values<Types...>::is_trivially_destructible;
+    static constexpr bool is_swappable =
+        is_swappable_v<T> && std::is_move_constructible<T> && variant_values<Types...>::
+                                                                  is_swappable;
+    static constexpr bool is_nothrow_swappable =
+        is_nothrow_swappable_v<T> && std::
+                                         is_nothrow_move_constructible<T> && variant_values<Types...>::
+                                                                                 is_nothrow_swappable;
     template <typename T2 = T,
               typename = typename std::enable_if<std::is_default_constructible<T2>::value>::type>
     constexpr variant_values() noexcept(std::is_nothrow_default_constructible<T2>::value)
@@ -333,8 +349,170 @@ union variant_values<T, Types...>
         else
             other_values.destruct(index - 1);
     }
+    void swap(variant_values &rt, std::size_t index) noexcept(is_nothrow_swappable)
+    {
+        using std::swap;
+        if(index == 0)
+            swap(current_value, rt.current_value);
+        else
+            other_values.swap(rt.other_values, index - 1);
+    }
+};
+
+template <std::size_t Index, typename... Types>
+struct variant_get;
+
+template <std::size_t Index, typename T, typename... Types>
+struct variant_get<Index, T, Types...>
+{
+    static constexpr auto get(const variant_values<T, Types...> &values) noexcept
+        -> decltype(variant_get<Index - 1, Types...>::get(values.other_values))
+    {
+        return variant_get<Index - 1, Types...>::get(values.other_values);
+    }
+    static constexpr auto get(variant_values<T, Types...> &values) noexcept
+        -> decltype(variant_get<Index - 1, Types...>::get(values.other_values))
+    {
+        return variant_get<Index - 1, Types...>::get(values.other_values);
+    }
+    static constexpr auto get(const variant_values<T, Types...> &&values) noexcept
+        -> decltype(variant_get<Index - 1, Types...>::get(std::move(values.other_values)))
+    {
+        return variant_get<Index - 1, Types...>::get(std::move(values.other_values));
+    }
+    static constexpr auto get(variant_values<T, Types...> &&values) noexcept
+        -> decltype(variant_get<Index - 1, Types...>::get(std::move(values.other_values)))
+    {
+        return variant_get<Index - 1, Types...>::get(std::move(values.other_values));
+    }
+};
+
+template <typename T, typename... Types>
+struct variant_get<0, T, Types...>
+{
+    static constexpr const T &get(const variant_values<T, Types...> &values) noexcept
+    {
+        return values.current_value;
+    }
+    static constexpr T &get(variant_values<T, Types...> &values) noexcept
+    {
+        return values.current_value;
+    }
+    static constexpr const T &&get(const variant_values<T, Types...> &&values) noexcept
+    {
+        return std::move(values.current_value);
+    }
+    static constexpr T &&get(variant_values<T, Types...> &&values) noexcept
+    {
+        return std::move(values.current_value);
+    }
 };
 
+#define VULKAN_CPU_UTIL_VARIANT_DISPATCH(Const, Ref)                                             \
+    template <typename Fn,                                                                       \
+              typename... Args,                                                                  \
+              typename... Types,                                                                 \
+              std::size_t... Indexes,                                                            \
+              typename Return_Type = typename std::common_type<decltype(std::declval<Fn>()(      \
+                  std::declval<Const Types Ref>(), std::declval<Args>()...))...>::type>          \
+    constexpr Return_Type variant_dispatch_helper(Fn &&fn,                                       \
+                                                  Const variant_values<Types...> Ref values,     \
+                                                  std::size_t index,                             \
+                                                  std::index_sequence<Indexes...>,               \
+                                                  Args &&... args)                               \
+    {                                                                                            \
+        typedef Return_Type (*Dispatch_Function)(                                                \
+            Fn && fn, Const variant_values<Types...> & values, Args && ... args);                \
+        static const Dispatch_Function dispatch_functions[sizeof...(Types)] = {                  \
+            static_cast<Dispatch_Function>(                                                      \
+                [](Fn &&fn, Const variant_values<Types...> &values, Args &&... args)             \
+                    -> Return_Type                                                               \
+                {                                                                                \
+                    return std::forward<Fn>(fn)(                                                 \
+                        variant_get<Indexes, Types...>::get(                                     \
+                            std::forward<Const variant_values<Types...> Ref>(values)),           \
+                        std::forward<Args>(args)...);                                            \
+                })...,                                                                           \
+        };                                                                                       \
+        if(index < sizeof...(Types))                                                             \
+            return dispatch_functions[index](                                                    \
+                std::forward<Fn>(fn), values, std::forward<Args>(args)...);                      \
+        throw bad_variant_access();                                                              \
+    }                                                                                            \
+                                                                                                 \
+    template <typename Fn, typename... Args, typename... Types>                                  \
+    constexpr auto variant_dispatch(                                                             \
+        Fn &&fn, Const variant_values<Types...> Ref values, std::size_t index, Args &&... args)  \
+        ->decltype(                                                                              \
+            variant_dispatch_helper(std::forward<Fn>(fn),                                        \
+                                    std::forward<Const variant_values<Types...> Ref>(values),    \
+                                    index,                                                       \
+                                    std::index_sequence_for<Types...>{},                         \
+                                    std::forward<Args>(args)...))                                \
+    {                                                                                            \
+        return variant_dispatch_helper(std::forward<Fn>(fn),                                     \
+                                       std::forward<Const variant_values<Types...> Ref>(values), \
+                                       index,                                                    \
+                                       std::index_sequence_for<Types...>{},                      \
+                                       std::forward<Args>(args)...);                             \
+    }                                                                                            \
+                                                                                                 \
+    template <typename Fn,                                                                       \
+              typename... Args,                                                                  \
+              typename... Types,                                                                 \
+              std::size_t... Indexes,                                                            \
+              typename Return_Type = typename std::common_type<decltype(std::declval<Fn>()(      \
+                  std::declval<Const Types Ref>(), std::declval<Args>()...))...>::type>          \
+    constexpr Return_Type variant_dispatch_helper_nothrow(                                       \
+        Fn &&fn,                                                                                 \
+        Const variant_values<Types...> Ref values,                                               \
+        std::size_t index,                                                                       \
+        std::index_sequence<Indexes...>,                                                         \
+        Args &&... args)                                                                         \
+    {                                                                                            \
+        typedef Return_Type (*Dispatch_Function)(                                                \
+            Fn && fn, Const variant_values<Types...> & values, Args && ... args);                \
+        static const Dispatch_Function dispatch_functions[sizeof...(Types)] = {                  \
+            static_cast<Dispatch_Function>(                                                      \
+                [](Fn &&fn, Const variant_values<Types...> &values, Args &&... args)             \
+                    -> Return_Type                                                               \
+                {                                                                                \
+                    return std::forward<Fn>(fn)(                                                 \
+                        variant_get<Indexes, Types...>::get(                                     \
+                            std::forward<Const variant_values<Types...> Ref>(values)),           \
+                        std::forward<Args>(args)...);                                            \
+                })...,                                                                           \
+        };                                                                                       \
+        if(index < sizeof...(Types))                                                             \
+            return dispatch_functions[index](                                                    \
+                std::forward<Fn>(fn), values, std::forward<Args>(args)...);                      \
+        return {};                                                                               \
+    }                                                                                            \
+                                                                                                 \
+    template <typename Fn, typename... Args, typename... Types>                                  \
+    constexpr auto variant_dispatch_nothrow(                                                     \
+        Fn &&fn, Const variant_values<Types...> Ref values, std::size_t index, Args &&... args)  \
+        ->decltype(variant_dispatch_helper_nothrow(                                              \
+            std::forward<Fn>(fn),                                                                \
+            std::forward<Const variant_values<Types...> Ref>(values),                            \
+            index,                                                                               \
+            std::index_sequence_for<Types...>{},                                                 \
+            std::forward<Args>(args)...))                                                        \
+    {                                                                                            \
+        return variant_dispatch_helper_nothrow(                                                  \
+            std::forward<Fn>(fn),                                                                \
+            std::forward<Const variant_values<Types...> Ref>(values),                            \
+            index,                                                                               \
+            std::index_sequence_for<Types...>{},                                                 \
+            std::forward<Args>(args)...);                                                        \
+    }
+
+VULKAN_CPU_UTIL_VARIANT_DISPATCH(, &)
+VULKAN_CPU_UTIL_VARIANT_DISPATCH(const, &)
+VULKAN_CPU_UTIL_VARIANT_DISPATCH(, &&)
+VULKAN_CPU_UTIL_VARIANT_DISPATCH(const, &&)
+#undef VULKAN_CPU_UTIL_VARIANT_DISPATCH
+
 template <typename T,
           typename... Types,
           typename Deduced_Type = typename decltype(
@@ -502,13 +680,41 @@ public:
         typename = typename std::
             enable_if<!std::is_same<typename std::decay<T>::type, variant>::value
                       && !detail::variant_is_in_place_index<typename std::decay<T>::type>::value
-                      && !detail::variant_is_in_place_type<typename std::decay<T>::type>::value>::
-                type>
+                      && !detail::variant_is_in_place_type<typename std::decay<T>::type>::value
+                      && std::is_constructible<variant_alternative_t<Index, variant<Types...>>,
+                                               T>::value>::type>
     constexpr variant(T &&value) noexcept(
         std::is_nothrow_constructible<variant_alternative_t<Index, variant<Types...>>, T>::value)
         : base(Index, in_place_index<Index>, std::forward<T>(value))
     {
     }
+    template <typename T,
+              typename... Args,
+              std::size_t Index = detail::variant_values<Types...>::index_from_type<T>(),
+              typename = typename std::enable_if<(Index < sizeof...(Types))
+                                                 && std::is_constructible<T, Args...>::value>::type>
+    constexpr explicit variant(in_place_type_t<T>, Args &&... args) noexcept(
+        std::is_nothrow_constructible<T, Args...>::value)
+        : base(Index, in_place_index<Index>, std::forward<Args>(args)...)
+    {
+    }
+    template <
+        typename T,
+        typename U,
+        typename... Args,
+        std::size_t Index = detail::variant_values<Types...>::index_from_type<T>(),
+        typename = typename std::
+            enable_if<(Index < sizeof...(Types))
+                      && std::is_constructible<T, std::initializer_list<U>, Args...>::value>::type>
+    constexpr explicit variant(
+        in_place_type_t<T>,
+        std::initializer_list<U> il,
+        Args &&... args) noexcept(std::is_nothrow_constructible<T,
+                                                                std::initializer_list<U>,
+                                                                Args...>::value)
+        : base(Index, in_place_index<Index>, il, std::forward<Args>(args)...)
+    {
+    }
     template <std::size_t Index,
               typename... Args,
               typename = typename std::
@@ -536,12 +742,152 @@ public:
         : base(Index, in_place_index<Index>, il, std::forward<Args>(args)...)
     {
     }
-#error finish
+    template <
+        typename =
+            typename std::enable_if<detail::variant_values<Types...>::is_copy_assignable>::type>
+    variant &operator=(const variant &rt) noexcept(
+        detail::variant_values<Types...>::is_nothrow_copy_assignable)
+    {
+        if(index_value.get() == rt.index_value.get())
+        {
+            values.copy_assign(rt.values, index_value.get());
+        }
+        else
+        {
+            values.destruct(index_value.get());
+            index_value.set(variant_npos); // in case copy_construct throws
+            values.copy_construct(rt, rt.index_value.get());
+            index_value = rt.index_value;
+        }
+        return *this;
+    }
+    template <
+        typename =
+            typename std::enable_if<detail::variant_values<Types...>::is_move_assignable>::type>
+    variant &operator=(variant &&rt) noexcept(
+        detail::variant_values<Types...>::is_nothrow_move_assignable)
+    {
+        if(index_value.get() == rt.index_value.get())
+        {
+            values.move_assign(std::move(rt.values), index_value.get());
+        }
+        else
+        {
+            values.destruct(index_value.get());
+            index_value.set(variant_npos); // in case move_construct throws
+            values.move_construct(std::move(rt), rt.index_value.get());
+            index_value = rt.index_value;
+        }
+        return *this;
+    }
+    template <
+        typename T,
+        std::size_t Index = detail::variant_conversion_deduce_index<T, Types...>(),
+        typename = typename std::
+            enable_if<!std::is_same<typename std::decay<T>::type, variant>::value
+                      && !detail::variant_is_in_place_index<typename std::decay<T>::type>::value
+                      && !detail::variant_is_in_place_type<typename std::decay<T>::type>::value
+                      && std::is_constructible<variant_alternative_t<Index, variant<Types...>>,
+                                               T>::value
+                      && std::is_assignable<variant_alternative_t<Index, variant<Types...>>,
+                                            T>::value>::type>
+    variant &operator=(T &&new_value) noexcept(
+        std::is_nothrow_constructible<variant_alternative_t<Index, variant<Types...>>, T>::value
+            &&std::is_nothrow_assignable<variant_alternative_t<Index, variant<Types...>>, T>::value)
+    {
+        if(index_value.get() == Index)
+        {
+            detail::variant_get<Index, Types...>::get(values) = std::forward<T>(new_value);
+        }
+        else
+        {
+            values.destruct(index_value.get());
+            index_value.set(variant_npos); // in case construction throws
+            auto &value = detail::variant_get<Index, Types...>::get(values);
+            new(const_cast<void *>(std::addressof(value)))
+                variant_alternative_t<Index, variant<Types...>>(std::forward<T>(new_value));
+            index_value.set(Index);
+        }
+        return *this;
+    }
+    template <typename T,
+              typename... Args,
+              std::size_t Index = detail::variant_values<Types...>::index_from_type<T>(),
+              typename = typename std::enable_if<(Index < sizeof...(Types))
+                                                 && std::is_constructible<T, Args...>::value>::type>
+    void emplace(Args &&... args)
+    {
+        emplace<Index>(std::forward<Args>(args)...);
+    }
+    template <
+        typename T,
+        typename U,
+        typename... Args,
+        std::size_t Index = detail::variant_values<Types...>::index_from_type<T>(),
+        typename = typename std::
+            enable_if<(Index < sizeof...(Types))
+                      && std::is_constructible<T, std::initializer_list<U>, Args...>::value>::type>
+    void emplace(std::initializer_list<U> il, Args &&... args)
+    {
+        emplace<Index>(il, std::forward<Args>(args)...);
+    }
+    template <std::size_t Index,
+              typename... Args,
+              typename = typename std::
+                  enable_if<(Index < sizeof...(Types))
+                            && std::is_constructible<variant_alternative_t<Index,
+                                                                           variant<Types...>>,
+                                                     Args...>::value>::type>
+    void emplace(Args &&... args)
+    {
+        values.destruct(index_value.get());
+        index_value.set(variant_npos); // in case construction throws
+        auto &value = detail::variant_get<Index, Types...>::get(values);
+        new(const_cast<void *>(std::addressof(value)))
+            variant_alternative_t<Index, variant<Types...>>(std::forward<Args>(args)...);
+        index_value.set(Index);
+    }
+    template <std::size_t Index,
+              typename U,
+              typename... Args,
+              typename = typename std::
+                  enable_if<(Index < sizeof...(Types))
+                            && std::is_constructible<variant_alternative_t<Index,
+                                                                           variant<Types...>>,
+                                                     std::initializer_list<U>,
+                                                     Args...>::value>::type>
+    void emplace(std::initializer_list<U> il, Args &&... args)
+    {
+        values.destruct(index_value.get());
+        index_value.set(variant_npos); // in case construction throws
+        auto &value = detail::variant_get<Index, Types...>::get(values);
+        new(const_cast<void *>(std::addressof(value)))
+            variant_alternative_t<Index, variant<Types...>>(il, std::forward<Args>(args)...);
+        index_value.set(Index);
+    }
+    constexpr bool valueless_by_exception() const noexcept
+    {
+        return index_value.get() == variant_npos;
+    }
     constexpr std::size_t index() const noexcept
     {
         return index_value.get();
     }
+    template <
+        typename = typename std::enable_if<detail::variant_values<Types...>::is_swappable>::type>
+    void swap(variant &rt) noexcept(detail::variant_values<Types...>::is_nothrow_swappable)
+    {
+        if(index_value.get() == rt.index_value.get())
+            values.swap(rt.values, index_value.get());
+        else
+        {
+            variant temp = std::move(rt);
+            rt = std::move(*this);
+            *this = std::move(temp);
+        }
+    }
 };
+#error finish
 }
 }
 
@@ -555,6 +901,16 @@ struct hash<vulkan_cpu::util::monostate>
         return 5546275UL;
     }
 };
+
+template <typename... Types,
+          typename = typename std::
+              enable_if<vulkan_cpu::util::detail::variant_values<Types...>::is_swappable>::type>
+inline void
+    swap(vulkan_cpu::util::variant<Types...> &l, vulkan_cpu::util::variant<Types...> &r) noexcept(
+        vulkan_cpu::util::detail::variant_values<Types...>::is_nothrow_swappable)
+{
+    l.swap(r);
+}
 }
 
 #endif /* SOURCE_UTIL_VARIANT_H_ */