summaryrefslogtreecommitdiffstats
path: root/include/mapbox/variant.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/mapbox/variant.hpp')
-rw-r--r--include/mapbox/variant.hpp1013
1 files changed, 0 insertions, 1013 deletions
diff --git a/include/mapbox/variant.hpp b/include/mapbox/variant.hpp
deleted file mode 100644
index fb0f77e..0000000
--- a/include/mapbox/variant.hpp
+++ /dev/null
@@ -1,1013 +0,0 @@
-#ifndef MAPBOX_UTIL_VARIANT_HPP
-#define MAPBOX_UTIL_VARIANT_HPP
-
-#include <cassert>
-#include <cstddef> // size_t
-#include <new> // operator new
-#include <stdexcept> // runtime_error
-#include <string>
-#include <tuple>
-#include <type_traits>
-#include <typeinfo>
-#include <utility>
-#include <functional>
-
-#include <mapbox/recursive_wrapper.hpp>
-#include <mapbox/variant_visitor.hpp>
-
-// clang-format off
-// [[deprecated]] is only available in C++14, use this for the time being
-#if __cplusplus <= 201103L
-# ifdef __GNUC__
-# define MAPBOX_VARIANT_DEPRECATED __attribute__((deprecated))
-# elif defined(_MSC_VER)
-# define MAPBOX_VARIANT_DEPRECATED __declspec(deprecated)
-# else
-# define MAPBOX_VARIANT_DEPRECATED
-# endif
-#else
-# define MAPBOX_VARIANT_DEPRECATED [[deprecated]]
-#endif
-
-
-#ifdef _MSC_VER
-// https://msdn.microsoft.com/en-us/library/bw1hbe6y.aspx
-# ifdef NDEBUG
-# define VARIANT_INLINE __forceinline
-# else
-# define VARIANT_INLINE //__declspec(noinline)
-# endif
-#else
-# ifdef NDEBUG
-# define VARIANT_INLINE //inline __attribute__((always_inline))
-# else
-# define VARIANT_INLINE __attribute__((noinline))
-# endif
-#endif
-// clang-format on
-
-// Exceptions
-#if defined( __EXCEPTIONS) || defined( _MSC_VER)
-#define HAS_EXCEPTIONS
-#endif
-
-#define VARIANT_MAJOR_VERSION 1
-#define VARIANT_MINOR_VERSION 1
-#define VARIANT_PATCH_VERSION 0
-
-#define VARIANT_VERSION (VARIANT_MAJOR_VERSION * 100000) + (VARIANT_MINOR_VERSION * 100) + (VARIANT_PATCH_VERSION)
-
-namespace mapbox {
-namespace util {
-
-// XXX This should derive from std::logic_error instead of std::runtime_error.
-// See https://github.com/mapbox/variant/issues/48 for details.
-class bad_variant_access : public std::runtime_error
-{
-
-public:
- explicit bad_variant_access(const std::string& what_arg)
- : runtime_error(what_arg) {}
-
- explicit bad_variant_access(const char* what_arg)
- : runtime_error(what_arg) {}
-
-}; // class bad_variant_access
-
-template <typename R = void>
-struct MAPBOX_VARIANT_DEPRECATED static_visitor
-{
- using result_type = R;
-
-protected:
- static_visitor() {}
- ~static_visitor() {}
-};
-
-namespace detail {
-
-static constexpr std::size_t invalid_value = std::size_t(-1);
-
-template <typename T, typename... Types>
-struct direct_type;
-
-template <typename T, typename First, typename... Types>
-struct direct_type<T, First, Types...>
-{
- static constexpr std::size_t index = std::is_same<T, First>::value
- ? sizeof...(Types)
- : direct_type<T, Types...>::index;
-};
-
-template <typename T>
-struct direct_type<T>
-{
- static constexpr std::size_t index = invalid_value;
-};
-
-#if __cpp_lib_logical_traits >= 201510L
-
-using std::disjunction;
-
-#else
-
-template <typename...>
-struct disjunction : std::false_type {};
-
-template <typename B1>
-struct disjunction<B1> : B1 {};
-
-template <typename B1, typename B2>
-struct disjunction<B1, B2> : std::conditional<B1::value, B1, B2>::type {};
-
-template <typename B1, typename... Bs>
-struct disjunction<B1, Bs...> : std::conditional<B1::value, B1, disjunction<Bs...>>::type {};
-
-#endif
-
-template <typename T, typename... Types>
-struct convertible_type;
-
-template <typename T, typename First, typename... Types>
-struct convertible_type<T, First, Types...>
-{
- static constexpr std::size_t index = std::is_convertible<T, First>::value
- ? disjunction<std::is_convertible<T, Types>...>::value ? invalid_value : sizeof...(Types)
- : convertible_type<T, Types...>::index;
-};
-
-template <typename T>
-struct convertible_type<T>
-{
- static constexpr std::size_t index = invalid_value;
-};
-
-template <typename T, typename... Types>
-struct value_traits
-{
- using value_type = typename std::remove_const<typename std::remove_reference<T>::type>::type;
- static constexpr std::size_t direct_index = direct_type<value_type, Types...>::index;
- static constexpr bool is_direct = direct_index != invalid_value;
- static constexpr std::size_t index = is_direct ? direct_index : convertible_type<value_type, Types...>::index;
- static constexpr bool is_valid = index != invalid_value;
- static constexpr std::size_t tindex = is_valid ? sizeof...(Types)-index : 0;
- using target_type = typename std::tuple_element<tindex, std::tuple<void, Types...>>::type;
-};
-
-template <typename T, typename R = void>
-struct enable_if_type
-{
- using type = R;
-};
-
-template <typename F, typename V, typename Enable = void>
-struct result_of_unary_visit
-{
- using type = typename std::result_of<F(V&)>::type;
-};
-
-template <typename F, typename V>
-struct result_of_unary_visit<F, V, typename enable_if_type<typename F::result_type>::type>
-{
- using type = typename F::result_type;
-};
-
-template <typename F, typename V, typename Enable = void>
-struct result_of_binary_visit
-{
- using type = typename std::result_of<F(V&, V&)>::type;
-};
-
-template <typename F, typename V>
-struct result_of_binary_visit<F, V, typename enable_if_type<typename F::result_type>::type>
-{
- using type = typename F::result_type;
-};
-
-template <std::size_t arg1, std::size_t... others>
-struct static_max;
-
-template <std::size_t arg>
-struct static_max<arg>
-{
- static const std::size_t value = arg;
-};
-
-template <std::size_t arg1, std::size_t arg2, std::size_t... others>
-struct static_max<arg1, arg2, others...>
-{
- static const std::size_t value = arg1 >= arg2 ? static_max<arg1, others...>::value : static_max<arg2, others...>::value;
-};
-
-template <typename... Types>
-struct variant_helper;
-
-template <typename T, typename... Types>
-struct variant_helper<T, Types...>
-{
- VARIANT_INLINE static void destroy(const std::size_t type_index, void* data)
- {
- if (type_index == sizeof...(Types))
- {
- reinterpret_cast<T*>(data)->~T();
- }
- else
- {
- variant_helper<Types...>::destroy(type_index, data);
- }
- }
-
- VARIANT_INLINE static void move(const std::size_t old_type_index, void* old_value, void* new_value)
- {
- if (old_type_index == sizeof...(Types))
- {
- new (new_value) T(std::move(*reinterpret_cast<T*>(old_value)));
- }
- else
- {
- variant_helper<Types...>::move(old_type_index, old_value, new_value);
- }
- }
-
- VARIANT_INLINE static void copy(const std::size_t old_type_index, const void* old_value, void* new_value)
- {
- if (old_type_index == sizeof...(Types))
- {
- new (new_value) T(*reinterpret_cast<const T*>(old_value));
- }
- else
- {
- variant_helper<Types...>::copy(old_type_index, old_value, new_value);
- }
- }
-};
-
-template <>
-struct variant_helper<>
-{
- VARIANT_INLINE static void destroy(const std::size_t, void*) {}
- VARIANT_INLINE static void move(const std::size_t, void*, void*) {}
- VARIANT_INLINE static void copy(const std::size_t, const void*, void*) {}
-};
-
-template <typename T>
-struct unwrapper
-{
- static T const& apply_const(T const& obj) { return obj; }
- static T& apply(T& obj) { return obj; }
-};
-
-template <typename T>
-struct unwrapper<recursive_wrapper<T>>
-{
- static auto apply_const(recursive_wrapper<T> const& obj)
- -> typename recursive_wrapper<T>::type const&
- {
- return obj.get();
- }
- static auto apply(recursive_wrapper<T>& obj)
- -> typename recursive_wrapper<T>::type&
- {
- return obj.get();
- }
-};
-
-template <typename T>
-struct unwrapper<std::reference_wrapper<T>>
-{
- static auto apply_const(std::reference_wrapper<T> const& obj)
- -> typename std::reference_wrapper<T>::type const&
- {
- return obj.get();
- }
- static auto apply(std::reference_wrapper<T>& obj)
- -> typename std::reference_wrapper<T>::type&
- {
- return obj.get();
- }
-};
-
-template <typename F, typename V, typename R, typename... Types>
-struct dispatcher;
-
-template <typename F, typename V, typename R, typename T, typename... Types>
-struct dispatcher<F, V, R, T, Types...>
-{
- VARIANT_INLINE static R apply_const(V const& v, F&& f)
- {
- if (v.template is<T>())
- {
- return f(unwrapper<T>::apply_const(v.template get_unchecked<T>()));
- }
- else
- {
- return dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f));
- }
- }
-
- VARIANT_INLINE static R apply(V& v, F&& f)
- {
- if (v.template is<T>())
- {
- return f(unwrapper<T>::apply(v.template get_unchecked<T>()));
- }
- else
- {
- return dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f));
- }
- }
-};
-
-template <typename F, typename V, typename R, typename T>
-struct dispatcher<F, V, R, T>
-{
- VARIANT_INLINE static R apply_const(V const& v, F&& f)
- {
- return f(unwrapper<T>::apply_const(v.template get_unchecked<T>()));
- }
-
- VARIANT_INLINE static R apply(V& v, F&& f)
- {
- return f(unwrapper<T>::apply(v.template get_unchecked<T>()));
- }
-};
-
-template <typename F, typename V, typename R, typename T, typename... Types>
-struct binary_dispatcher_rhs;
-
-template <typename F, typename V, typename R, typename T0, typename T1, typename... Types>
-struct binary_dispatcher_rhs<F, V, R, T0, T1, Types...>
-{
- VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
- {
- if (rhs.template is<T1>()) // call binary functor
- {
- return f(unwrapper<T0>::apply_const(lhs.template get_unchecked<T0>()),
- unwrapper<T1>::apply_const(rhs.template get_unchecked<T1>()));
- }
- else
- {
- return binary_dispatcher_rhs<F, V, R, T0, Types...>::apply_const(lhs, rhs, std::forward<F>(f));
- }
- }
-
- VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
- {
- if (rhs.template is<T1>()) // call binary functor
- {
- return f(unwrapper<T0>::apply(lhs.template get_unchecked<T0>()),
- unwrapper<T1>::apply(rhs.template get_unchecked<T1>()));
- }
- else
- {
- return binary_dispatcher_rhs<F, V, R, T0, Types...>::apply(lhs, rhs, std::forward<F>(f));
- }
- }
-};
-
-template <typename F, typename V, typename R, typename T0, typename T1>
-struct binary_dispatcher_rhs<F, V, R, T0, T1>
-{
- VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
- {
- return f(unwrapper<T0>::apply_const(lhs.template get_unchecked<T0>()),
- unwrapper<T1>::apply_const(rhs.template get_unchecked<T1>()));
- }
-
- VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
- {
- return f(unwrapper<T0>::apply(lhs.template get_unchecked<T0>()),
- unwrapper<T1>::apply(rhs.template get_unchecked<T1>()));
- }
-};
-
-template <typename F, typename V, typename R, typename T, typename... Types>
-struct binary_dispatcher_lhs;
-
-template <typename F, typename V, typename R, typename T0, typename T1, typename... Types>
-struct binary_dispatcher_lhs<F, V, R, T0, T1, Types...>
-{
- VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
- {
- if (lhs.template is<T1>()) // call binary functor
- {
- return f(unwrapper<T1>::apply_const(lhs.template get_unchecked<T1>()),
- unwrapper<T0>::apply_const(rhs.template get_unchecked<T0>()));
- }
- else
- {
- return binary_dispatcher_lhs<F, V, R, T0, Types...>::apply_const(lhs, rhs, std::forward<F>(f));
- }
- }
-
- VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
- {
- if (lhs.template is<T1>()) // call binary functor
- {
- return f(unwrapper<T1>::apply(lhs.template get_unchecked<T1>()),
- unwrapper<T0>::apply(rhs.template get_unchecked<T0>()));
- }
- else
- {
- return binary_dispatcher_lhs<F, V, R, T0, Types...>::apply(lhs, rhs, std::forward<F>(f));
- }
- }
-};
-
-template <typename F, typename V, typename R, typename T0, typename T1>
-struct binary_dispatcher_lhs<F, V, R, T0, T1>
-{
- VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
- {
- return f(unwrapper<T1>::apply_const(lhs.template get_unchecked<T1>()),
- unwrapper<T0>::apply_const(rhs.template get_unchecked<T0>()));
- }
-
- VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
- {
- return f(unwrapper<T1>::apply(lhs.template get_unchecked<T1>()),
- unwrapper<T0>::apply(rhs.template get_unchecked<T0>()));
- }
-};
-
-template <typename F, typename V, typename R, typename... Types>
-struct binary_dispatcher;
-
-template <typename F, typename V, typename R, typename T, typename... Types>
-struct binary_dispatcher<F, V, R, T, Types...>
-{
- VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f)
- {
- if (v0.template is<T>())
- {
- if (v1.template is<T>())
- {
- return f(unwrapper<T>::apply_const(v0.template get_unchecked<T>()),
- unwrapper<T>::apply_const(v1.template get_unchecked<T>())); // call binary functor
- }
- else
- {
- return binary_dispatcher_rhs<F, V, R, T, Types...>::apply_const(v0, v1, std::forward<F>(f));
- }
- }
- else if (v1.template is<T>())
- {
- return binary_dispatcher_lhs<F, V, R, T, Types...>::apply_const(v0, v1, std::forward<F>(f));
- }
- return binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f));
- }
-
- VARIANT_INLINE static R apply(V& v0, V& v1, F&& f)
- {
- if (v0.template is<T>())
- {
- if (v1.template is<T>())
- {
- return f(unwrapper<T>::apply(v0.template get_unchecked<T>()),
- unwrapper<T>::apply(v1.template get_unchecked<T>())); // call binary functor
- }
- else
- {
- return binary_dispatcher_rhs<F, V, R, T, Types...>::apply(v0, v1, std::forward<F>(f));
- }
- }
- else if (v1.template is<T>())
- {
- return binary_dispatcher_lhs<F, V, R, T, Types...>::apply(v0, v1, std::forward<F>(f));
- }
- return binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f));
- }
-};
-
-template <typename F, typename V, typename R, typename T>
-struct binary_dispatcher<F, V, R, T>
-{
- VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f)
- {
- return f(unwrapper<T>::apply_const(v0.template get_unchecked<T>()),
- unwrapper<T>::apply_const(v1.template get_unchecked<T>())); // call binary functor
- }
-
- VARIANT_INLINE static R apply(V& v0, V& v1, F&& f)
- {
- return f(unwrapper<T>::apply(v0.template get_unchecked<T>()),
- unwrapper<T>::apply(v1.template get_unchecked<T>())); // call binary functor
- }
-};
-
-// comparator functors
-struct equal_comp
-{
- template <typename T>
- bool operator()(T const& lhs, T const& rhs) const
- {
- return lhs == rhs;
- }
-};
-
-struct less_comp
-{
- template <typename T>
- bool operator()(T const& lhs, T const& rhs) const
- {
- return lhs < rhs;
- }
-};
-
-template <typename Variant, typename Comp>
-class comparer
-{
-public:
- explicit comparer(Variant const& lhs) noexcept
- : lhs_(lhs) {}
- comparer& operator=(comparer const&) = delete;
- // visitor
- template <typename T>
- bool operator()(T const& rhs_content) const
- {
- T const& lhs_content = lhs_.template get_unchecked<T>();
- return Comp()(lhs_content, rhs_content);
- }
-
-private:
- Variant const& lhs_;
-};
-
-// hashing visitor
-struct hasher
-{
- template <typename T>
- std::size_t operator()(const T& hashable) const
- {
- return std::hash<T>{}(hashable);
- }
-};
-
-} // namespace detail
-
-struct no_init
-{
-};
-
-template <typename... Types>
-class variant
-{
- static_assert(sizeof...(Types) > 0, "Template parameter type list of variant can not be empty");
- static_assert(!detail::disjunction<std::is_reference<Types>...>::value, "Variant can not hold reference types. Maybe use std::reference_wrapper?");
-
-private:
- static const std::size_t data_size = detail::static_max<sizeof(Types)...>::value;
- static const std::size_t data_align = detail::static_max<alignof(Types)...>::value;
-public:
- struct adapted_variant_tag;
- using types = std::tuple<Types...>;
-private:
- using first_type = typename std::tuple_element<0, types>::type;
- using data_type = typename std::aligned_storage<data_size, data_align>::type;
- using helper_type = detail::variant_helper<Types...>;
-
- std::size_t type_index;
- data_type data;
-
-public:
- VARIANT_INLINE variant() noexcept(std::is_nothrow_default_constructible<first_type>::value)
- : type_index(sizeof...(Types)-1)
- {
- static_assert(std::is_default_constructible<first_type>::value, "First type in variant must be default constructible to allow default construction of variant");
- new (&data) first_type();
- }
-
- VARIANT_INLINE variant(no_init) noexcept
- : type_index(detail::invalid_value) {}
-
- // http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers
- template <typename T, typename Traits = detail::value_traits<T, Types...>,
- typename Enable = typename std::enable_if<Traits::is_valid && !std::is_same<variant<Types...>, typename Traits::value_type>::value>::type >
- VARIANT_INLINE variant(T&& val) noexcept(std::is_nothrow_constructible<typename Traits::target_type, T&&>::value)
- : type_index(Traits::index)
- {
- new (&data) typename Traits::target_type(std::forward<T>(val));
- }
-
- VARIANT_INLINE variant(variant<Types...> const& old)
- : type_index(old.type_index)
- {
- helper_type::copy(old.type_index, &old.data, &data);
- }
-
- VARIANT_INLINE variant(variant<Types...>&& old) noexcept(std::is_nothrow_move_constructible<types>::value)
- : type_index(old.type_index)
- {
- helper_type::move(old.type_index, &old.data, &data);
- }
-
-private:
- VARIANT_INLINE void copy_assign(variant<Types...> const& rhs)
- {
- helper_type::destroy(type_index, &data);
- type_index = detail::invalid_value;
- helper_type::copy(rhs.type_index, &rhs.data, &data);
- type_index = rhs.type_index;
- }
-
- VARIANT_INLINE void move_assign(variant<Types...>&& rhs)
- {
- helper_type::destroy(type_index, &data);
- type_index = detail::invalid_value;
- helper_type::move(rhs.type_index, &rhs.data, &data);
- type_index = rhs.type_index;
- }
-
-public:
- VARIANT_INLINE variant<Types...>& operator=(variant<Types...>&& other)
- {
- move_assign(std::move(other));
- return *this;
- }
-
- VARIANT_INLINE variant<Types...>& operator=(variant<Types...> const& other)
- {
- copy_assign(other);
- return *this;
- }
-
- // conversions
- // move-assign
- template <typename T>
- VARIANT_INLINE variant<Types...>& operator=(T&& rhs) noexcept
- {
- variant<Types...> temp(std::forward<T>(rhs));
- move_assign(std::move(temp));
- return *this;
- }
-
- // copy-assign
- template <typename T>
- VARIANT_INLINE variant<Types...>& operator=(T const& rhs)
- {
- variant<Types...> temp(rhs);
- copy_assign(temp);
- return *this;
- }
-
- template <typename T, typename std::enable_if<
- (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
- VARIANT_INLINE bool is() const
- {
- return type_index == detail::direct_type<T, Types...>::index;
- }
-
- template <typename T,typename std::enable_if<
- (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
- VARIANT_INLINE bool is() const
- {
- return type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index;
- }
-
- VARIANT_INLINE bool valid() const
- {
- return type_index != detail::invalid_value;
- }
-
- template <typename T, typename... Args>
- VARIANT_INLINE void set(Args&&... args)
- {
- helper_type::destroy(type_index, &data);
- type_index = detail::invalid_value;
- new (&data) T(std::forward<Args>(args)...);
- type_index = detail::direct_type<T, Types...>::index;
- }
-
- // get_unchecked<T>()
- template <typename T, typename std::enable_if<
- (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
- VARIANT_INLINE T& get_unchecked()
- {
- return *reinterpret_cast<T*>(&data);
- }
-
-#ifdef HAS_EXCEPTIONS
- // get<T>()
- template <typename T, typename std::enable_if<
- (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
- VARIANT_INLINE T& get()
- {
- if (type_index == detail::direct_type<T, Types...>::index)
- {
- return *reinterpret_cast<T*>(&data);
- }
- else
- {
- throw bad_variant_access("in get<T>()");
- }
- }
-#endif
-
- template <typename T, typename std::enable_if<
- (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
- VARIANT_INLINE T const& get_unchecked() const
- {
- return *reinterpret_cast<T const*>(&data);
- }
-
-#ifdef HAS_EXCEPTIONS
- template <typename T, typename std::enable_if<
- (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
- VARIANT_INLINE T const& get() const
- {
- if (type_index == detail::direct_type<T, Types...>::index)
- {
- return *reinterpret_cast<T const*>(&data);
- }
- else
- {
- throw bad_variant_access("in get<T>()");
- }
- }
-#endif
-
- // get_unchecked<T>() - T stored as recursive_wrapper<T>
- template <typename T, typename std::enable_if<
- (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
- VARIANT_INLINE T& get_unchecked()
- {
- return (*reinterpret_cast<recursive_wrapper<T>*>(&data)).get();
- }
-
-#ifdef HAS_EXCEPTIONS
- // get<T>() - T stored as recursive_wrapper<T>
- template <typename T, typename std::enable_if<
- (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
- VARIANT_INLINE T& get()
- {
- if (type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index)
- {
- return (*reinterpret_cast<recursive_wrapper<T>*>(&data)).get();
- }
- else
- {
- throw bad_variant_access("in get<T>()");
- }
- }
-#endif
-
- template <typename T, typename std::enable_if<
- (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
- VARIANT_INLINE T const& get_unchecked() const
- {
- return (*reinterpret_cast<recursive_wrapper<T> const*>(&data)).get();
- }
-
-#ifdef HAS_EXCEPTIONS
- template <typename T, typename std::enable_if<
- (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
- VARIANT_INLINE T const& get() const
- {
- if (type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index)
- {
- return (*reinterpret_cast<recursive_wrapper<T> const*>(&data)).get();
- }
- else
- {
- throw bad_variant_access("in get<T>()");
- }
- }
-#endif
-
- // get_unchecked<T>() - T stored as std::reference_wrapper<T>
- template <typename T, typename std::enable_if<
- (detail::direct_type<std::reference_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
- VARIANT_INLINE T& get_unchecked()
- {
- return (*reinterpret_cast<std::reference_wrapper<T>*>(&data)).get();
- }
-
-#ifdef HAS_EXCEPTIONS
- // get<T>() - T stored as std::reference_wrapper<T>
- template <typename T, typename std::enable_if<
- (detail::direct_type<std::reference_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
- VARIANT_INLINE T& get()
- {
- if (type_index == detail::direct_type<std::reference_wrapper<T>, Types...>::index)
- {
- return (*reinterpret_cast<std::reference_wrapper<T>*>(&data)).get();
- }
- else
- {
- throw bad_variant_access("in get<T>()");
- }
- }
-#endif
-
- template <typename T, typename std::enable_if<
- (detail::direct_type<std::reference_wrapper<T const>, Types...>::index != detail::invalid_value)>::type* = nullptr>
- VARIANT_INLINE T const& get_unchecked() const
- {
- return (*reinterpret_cast<std::reference_wrapper<T const> const*>(&data)).get();
- }
-
-#ifdef HAS_EXCEPTIONS
- template <typename T, typename std::enable_if<
- (detail::direct_type<std::reference_wrapper<T const>, Types...>::index != detail::invalid_value)>::type* = nullptr>
- VARIANT_INLINE T const& get() const
- {
- if (type_index == detail::direct_type<std::reference_wrapper<T const>, Types...>::index)
- {
- return (*reinterpret_cast<std::reference_wrapper<T const> const*>(&data)).get();
- }
- else
- {
- throw bad_variant_access("in get<T>()");
- }
- }
-#endif
-
- // This function is deprecated because it returns an internal index field.
- // Use which() instead.
- MAPBOX_VARIANT_DEPRECATED VARIANT_INLINE std::size_t get_type_index() const
- {
- return type_index;
- }
-
- VARIANT_INLINE int which() const noexcept
- {
- return static_cast<int>(sizeof...(Types)-type_index - 1);
- }
-
- template <typename T, typename std::enable_if<
- (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
- VARIANT_INLINE static constexpr int which() noexcept
- {
- return static_cast<int>(sizeof...(Types)-detail::direct_type<T, Types...>::index - 1);
- }
-
- // visitor
- // unary
- template <typename F, typename V, typename R = typename detail::result_of_unary_visit<F, first_type>::type>
- auto VARIANT_INLINE static visit(V const& v, F&& f)
- -> decltype(detail::dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f)))
- {
- return detail::dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f));
- }
- // non-const
- template <typename F, typename V, typename R = typename detail::result_of_unary_visit<F, first_type>::type>
- auto VARIANT_INLINE static visit(V& v, F&& f)
- -> decltype(detail::dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f)))
- {
- return detail::dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f));
- }
-
- // binary
- // const
- template <typename F, typename V, typename R = typename detail::result_of_binary_visit<F, first_type>::type>
- auto VARIANT_INLINE static binary_visit(V const& v0, V const& v1, F&& f)
- -> decltype(detail::binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f)))
- {
- return detail::binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f));
- }
- // non-const
- template <typename F, typename V, typename R = typename detail::result_of_binary_visit<F, first_type>::type>
- auto VARIANT_INLINE static binary_visit(V& v0, V& v1, F&& f)
- -> decltype(detail::binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f)))
- {
- return detail::binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f));
- }
-
- // match
- // unary
- template <typename... Fs>
- auto VARIANT_INLINE match(Fs&&... fs) const
- -> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)))
- {
- return variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...));
- }
- // non-const
- template <typename... Fs>
- auto VARIANT_INLINE match(Fs&&... fs)
- -> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)))
- {
- return variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...));
- }
-
- ~variant() noexcept // no-throw destructor
- {
- helper_type::destroy(type_index, &data);
- }
-
- // comparison operators
- // equality
- VARIANT_INLINE bool operator==(variant const& rhs) const
- {
- assert(valid() && rhs.valid());
- if (this->which() != rhs.which())
- {
- return false;
- }
- detail::comparer<variant, detail::equal_comp> visitor(*this);
- return visit(rhs, visitor);
- }
-
- VARIANT_INLINE bool operator!=(variant const& rhs) const
- {
- return !(*this == rhs);
- }
-
- // less than
- VARIANT_INLINE bool operator<(variant const& rhs) const
- {
- assert(valid() && rhs.valid());
- if (this->which() != rhs.which())
- {
- return this->which() < rhs.which();
- }
- detail::comparer<variant, detail::less_comp> visitor(*this);
- return visit(rhs, visitor);
- }
- VARIANT_INLINE bool operator>(variant const& rhs) const
- {
- return rhs < *this;
- }
- VARIANT_INLINE bool operator<=(variant const& rhs) const
- {
- return !(*this > rhs);
- }
- VARIANT_INLINE bool operator>=(variant const& rhs) const
- {
- return !(*this < rhs);
- }
-};
-
-// unary visitor interface
-// const
-template <typename F, typename V>
-auto VARIANT_INLINE apply_visitor(F&& f, V const& v) -> decltype(V::visit(v, std::forward<F>(f)))
-{
- return V::visit(v, std::forward<F>(f));
-}
-
-// non-const
-template <typename F, typename V>
-auto VARIANT_INLINE apply_visitor(F&& f, V& v) -> decltype(V::visit(v, std::forward<F>(f)))
-{
- return V::visit(v, std::forward<F>(f));
-}
-
-// binary visitor interface
-// const
-template <typename F, typename V>
-auto VARIANT_INLINE apply_visitor(F&& f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, std::forward<F>(f)))
-{
- return V::binary_visit(v0, v1, std::forward<F>(f));
-}
-
-// non-const
-template <typename F, typename V>
-auto VARIANT_INLINE apply_visitor(F&& f, V& v0, V& v1) -> decltype(V::binary_visit(v0, v1, std::forward<F>(f)))
-{
- return V::binary_visit(v0, v1, std::forward<F>(f));
-}
-
-// getter interface
-
-#ifdef HAS_EXCEPTIONS
-template <typename ResultType, typename T>
-auto get(T& var)->decltype(var.template get<ResultType>())
-{
- return var.template get<ResultType>();
-}
-#endif
-
-template <typename ResultType, typename T>
-ResultType& get_unchecked(T& var)
-{
- return var.template get_unchecked<ResultType>();
-}
-
-#ifdef HAS_EXCEPTIONS
-template <typename ResultType, typename T>
-auto get(T const& var)->decltype(var.template get<ResultType>())
-{
- return var.template get<ResultType>();
-}
-#endif
-
-template <typename ResultType, typename T>
-ResultType const& get_unchecked(T const& var)
-{
- return var.template get_unchecked<ResultType>();
-}
-} // namespace util
-} // namespace mapbox
-
-// hashable iff underlying types are hashable
-namespace std {
-template <typename... Types>
-struct hash< ::mapbox::util::variant<Types...>> {
- std::size_t operator()(const ::mapbox::util::variant<Types...>& v) const noexcept
- {
- return ::mapbox::util::apply_visitor(::mapbox::util::detail::hasher{}, v);
- }
-};
-}
-
-#endif // MAPBOX_UTIL_VARIANT_HPP