#include <limits>
#include <new>
#include "in_place.h"
+#include "void_t.h"
namespace vulkan_cpu
{
namespace detail
{
+template <typename T>
+struct variant_identity_type
+{
+ typedef T type;
+};
+
+template <typename... Types>
+struct variant_hypothetical_overload_set;
+
+template <typename T, typename... Types>
+struct variant_hypothetical_overload_set<T, Types...>
+ : public variant_hypothetical_overload_set<Types...>
+{
+ using variant_hypothetical_overload_set<Types...>::fn;
+ static variant_identity_type<T> fn(T); // not implemented
+};
+
+template <>
+struct variant_hypothetical_overload_set
+{
+ static void fn(); // not implemented
+};
+
+template <typename T, typename = void, typename... Types>
+struct variant_conversion_deduce_type_helper;
+
+template <typename T, typename... Types>
+struct variant_conversion_deduce_type_helper<T,
+ void_t<typename decltype(
+ variant_hypothetical_overload_set<Types...>::fn(
+ std::declval<T>()))::type>>
+{
+ typedef typename decltype(
+ variant_hypothetical_overload_set<Types...>::fn(std::declval<T>()))::type type;
+};
+
+template <typename T, typename... Types>
+using variant_conversion_deduce_type =
+ typename variant_conversion_deduce_type_helper<T, void, Types...>::type;
+
template <typename... Types>
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 <std::size_t index>
constexpr variant_values(in_place_index_t<index>) noexcept : value()
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 <typename T, typename... 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_nothrow_copy_assignable =
+ std::is_nothrow_copy_assignable<T>::value
+ && variant_values<Types...>::is_nothrow_copy_assignable;
+ static constexpr bool is_nothrow_move_assignable =
+ std::is_nothrow_move_assignable<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;
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)
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<void *>(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<void *>(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 <std::size_t Type_Count>
index_value = new_value;
}
};
+
+template <bool Is_Trivially_Destructible, typename... Types>
+struct variant_base
+{
+ detail::variant_values<Types...> values;
+ detail::variant_index_type<sizeof...(Types)> index_value;
+ template <typename... Args>
+ constexpr variant_base(std::size_t index_value, Args &&... args) //
+ noexcept(noexcept(new(std::declval<void *>())
+ detail::variant_values<Types...>(std::declval<Args>()...)))
+ : values(std::forward<Args>(args)...), index_value(index_value)
+ {
+ }
+ ~variant_base()
+ {
+ values.destroy(index_value.get());
+ }
+};
+
+template <typename... Types>
+struct variant_base<true, Types...>
+{
+ detail::variant_values<Types...> values;
+ detail::variant_index_type<sizeof...(Types)> index_value;
+ template <typename... Args>
+ constexpr variant_base(std::size_t index_value, Args &&... args) //
+ noexcept(noexcept(new(std::declval<void *>())
+ detail::variant_values<Types...>(std::declval<Args>()...)))
+ : values(std::forward<Args>(args)...), index_value(index_value)
+ {
+ }
+ ~variant_base() = default;
+};
}
template <typename... Types>
class variant
+ : private detail::variant_base<detail::variant_values<Types...>::is_trivially_destructible,
+ Types...>
{
static_assert(sizeof...(Types) > 0, "empty variant is not permitted");
private:
typedef typename detail::variant_values<Types...>::type_0 type_0;
+ typedef detail::variant_base<detail::variant_values<Types...>::is_trivially_destructible,
+ Types...> base;
private:
- detail::variant_values<Types...> values;
- detail::variant_index_type<sizeof...(Types)> index_value;
+ using base::values;
+ using base::index_value;
public:
template <
typename = typename std::enable_if<std::is_default_constructible<type_0>::value>::value>
constexpr variant() noexcept(std::is_nothrow_default_constructible<type_0>::value)
- : values(), index_value(0)
+ : base(0)
{
}
template <
typename std::enable_if<detail::variant_values<Types...>::is_copy_constructible>::type>
variant(const variant &rt) noexcept(
detail::variant_values<Types...>::is_nothrow_copy_constructible)
- : values(in_place_index<variant_npos>()), index_value(variant_npos)
+ : base(variant_npos, in_place_index<variant_npos>())
{
values.copy_construct(rt.values, rt.index_value.get());
index_value = rt.index_value;
typename =
typename std::enable_if<detail::variant_values<Types...>::is_move_constructible>::type>
variant(variant &&rt) noexcept(detail::variant_values<Types...>::is_nothrow_move_constructible)
- : values(in_place_index<variant_npos>()), index_value(variant_npos)
+ : base(variant_npos, in_place_index<variant_npos>())
{
values.move_construct(std::move(rt.values), rt.index_value.get());
index_value = rt.index_value;
constexpr explicit variant(in_place_index_t<index>, Args &&... args) noexcept(
std::is_nothrow_constructible<variant_alternative_t<index, variant<Types...>>,
Args...>::value)
- : values(in_place_index<index>, std::forward<Args>(args)...), index_value(index)
+ : base(index, in_place_index<index>, std::forward<Args>(args)...)
{
}
#error finish
--- /dev/null
+/*
+ * 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 <typename... Types>
+struct void_t_helper
+{
+ typedef void type;
+};
+}
+
+template <typename... Types>
+using void_t = typename detail::void_t_helper<Types...>::type;
+}
+}
+
+#endif /* SOURCE_UTIL_VOID_T_H_ */