xref: /aosp_15_r20/external/armnn/third-party/mapbox/variant.hpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
1*89c4ff92SAndroid Build Coastguard Worker //
2*89c4ff92SAndroid Build Coastguard Worker // Copyright (c) MapBox All rights reserved.
3*89c4ff92SAndroid Build Coastguard Worker // SPDX-License-Identifier: BSD-3-Clause
4*89c4ff92SAndroid Build Coastguard Worker //
5*89c4ff92SAndroid Build Coastguard Worker 
6*89c4ff92SAndroid Build Coastguard Worker #ifndef MAPBOX_UTIL_VARIANT_HPP
7*89c4ff92SAndroid Build Coastguard Worker #define MAPBOX_UTIL_VARIANT_HPP
8*89c4ff92SAndroid Build Coastguard Worker 
9*89c4ff92SAndroid Build Coastguard Worker #include <cassert>
10*89c4ff92SAndroid Build Coastguard Worker #include <cstddef>   // size_t
11*89c4ff92SAndroid Build Coastguard Worker #include <new>       // operator new
12*89c4ff92SAndroid Build Coastguard Worker #include <stdexcept> // runtime_error
13*89c4ff92SAndroid Build Coastguard Worker #include <string>
14*89c4ff92SAndroid Build Coastguard Worker #include <tuple>
15*89c4ff92SAndroid Build Coastguard Worker #include <type_traits>
16*89c4ff92SAndroid Build Coastguard Worker #include <typeinfo>
17*89c4ff92SAndroid Build Coastguard Worker #include <utility>
18*89c4ff92SAndroid Build Coastguard Worker #include <functional>
19*89c4ff92SAndroid Build Coastguard Worker #include <limits>
20*89c4ff92SAndroid Build Coastguard Worker 
21*89c4ff92SAndroid Build Coastguard Worker #include <mapbox/recursive_wrapper.hpp>
22*89c4ff92SAndroid Build Coastguard Worker #include <mapbox/variant_visitor.hpp>
23*89c4ff92SAndroid Build Coastguard Worker 
24*89c4ff92SAndroid Build Coastguard Worker // clang-format off
25*89c4ff92SAndroid Build Coastguard Worker // [[deprecated]] is only available in C++14, use this for the time being
26*89c4ff92SAndroid Build Coastguard Worker #if __cplusplus <= 201103L
27*89c4ff92SAndroid Build Coastguard Worker # ifdef __GNUC__
28*89c4ff92SAndroid Build Coastguard Worker #  define MAPBOX_VARIANT_DEPRECATED __attribute__((deprecated))
29*89c4ff92SAndroid Build Coastguard Worker # elif defined(_MSC_VER)
30*89c4ff92SAndroid Build Coastguard Worker #  define MAPBOX_VARIANT_DEPRECATED __declspec(deprecated)
31*89c4ff92SAndroid Build Coastguard Worker # else
32*89c4ff92SAndroid Build Coastguard Worker #  define MAPBOX_VARIANT_DEPRECATED
33*89c4ff92SAndroid Build Coastguard Worker # endif
34*89c4ff92SAndroid Build Coastguard Worker #else
35*89c4ff92SAndroid Build Coastguard Worker #  define MAPBOX_VARIANT_DEPRECATED [[deprecated]]
36*89c4ff92SAndroid Build Coastguard Worker #endif
37*89c4ff92SAndroid Build Coastguard Worker 
38*89c4ff92SAndroid Build Coastguard Worker 
39*89c4ff92SAndroid Build Coastguard Worker #ifdef _MSC_VER
40*89c4ff92SAndroid Build Coastguard Worker // https://msdn.microsoft.com/en-us/library/bw1hbe6y.aspx
41*89c4ff92SAndroid Build Coastguard Worker # ifdef NDEBUG
42*89c4ff92SAndroid Build Coastguard Worker #  define VARIANT_INLINE __forceinline
43*89c4ff92SAndroid Build Coastguard Worker # else
44*89c4ff92SAndroid Build Coastguard Worker #  define VARIANT_INLINE //__declspec(noinline)
45*89c4ff92SAndroid Build Coastguard Worker # endif
46*89c4ff92SAndroid Build Coastguard Worker #else
47*89c4ff92SAndroid Build Coastguard Worker # ifdef NDEBUG
48*89c4ff92SAndroid Build Coastguard Worker #  define VARIANT_INLINE //inline __attribute__((always_inline))
49*89c4ff92SAndroid Build Coastguard Worker # else
50*89c4ff92SAndroid Build Coastguard Worker #  define VARIANT_INLINE __attribute__((noinline))
51*89c4ff92SAndroid Build Coastguard Worker # endif
52*89c4ff92SAndroid Build Coastguard Worker #endif
53*89c4ff92SAndroid Build Coastguard Worker // clang-format on
54*89c4ff92SAndroid Build Coastguard Worker 
55*89c4ff92SAndroid Build Coastguard Worker // Exceptions
56*89c4ff92SAndroid Build Coastguard Worker #if defined( __EXCEPTIONS) || defined( _MSC_VER)
57*89c4ff92SAndroid Build Coastguard Worker #define HAS_EXCEPTIONS
58*89c4ff92SAndroid Build Coastguard Worker #endif
59*89c4ff92SAndroid Build Coastguard Worker 
60*89c4ff92SAndroid Build Coastguard Worker #define VARIANT_MAJOR_VERSION 1
61*89c4ff92SAndroid Build Coastguard Worker #define VARIANT_MINOR_VERSION 1
62*89c4ff92SAndroid Build Coastguard Worker #define VARIANT_PATCH_VERSION 0
63*89c4ff92SAndroid Build Coastguard Worker 
64*89c4ff92SAndroid Build Coastguard Worker #define VARIANT_VERSION (VARIANT_MAJOR_VERSION * 100000) + (VARIANT_MINOR_VERSION * 100) + (VARIANT_PATCH_VERSION)
65*89c4ff92SAndroid Build Coastguard Worker 
66*89c4ff92SAndroid Build Coastguard Worker namespace mapbox {
67*89c4ff92SAndroid Build Coastguard Worker namespace util {
68*89c4ff92SAndroid Build Coastguard Worker 
69*89c4ff92SAndroid Build Coastguard Worker // XXX This should derive from std::logic_error instead of std::runtime_error.
70*89c4ff92SAndroid Build Coastguard Worker //     See https://github.com/mapbox/variant/issues/48 for details.
71*89c4ff92SAndroid Build Coastguard Worker class bad_variant_access : public std::runtime_error
72*89c4ff92SAndroid Build Coastguard Worker {
73*89c4ff92SAndroid Build Coastguard Worker 
74*89c4ff92SAndroid Build Coastguard Worker public:
bad_variant_access(const std::string & what_arg)75*89c4ff92SAndroid Build Coastguard Worker     explicit bad_variant_access(const std::string& what_arg)
76*89c4ff92SAndroid Build Coastguard Worker         : runtime_error(what_arg) {}
77*89c4ff92SAndroid Build Coastguard Worker 
bad_variant_access(const char * what_arg)78*89c4ff92SAndroid Build Coastguard Worker     explicit bad_variant_access(const char* what_arg)
79*89c4ff92SAndroid Build Coastguard Worker         : runtime_error(what_arg) {}
80*89c4ff92SAndroid Build Coastguard Worker 
81*89c4ff92SAndroid Build Coastguard Worker }; // class bad_variant_access
82*89c4ff92SAndroid Build Coastguard Worker 
83*89c4ff92SAndroid Build Coastguard Worker #if !defined(MAPBOX_VARIANT_MINIMIZE_SIZE)
84*89c4ff92SAndroid Build Coastguard Worker using type_index_t = unsigned int;
85*89c4ff92SAndroid Build Coastguard Worker #else
86*89c4ff92SAndroid Build Coastguard Worker #if defined(MAPBOX_VARIANT_OPTIMIZE_FOR_SPEED)
87*89c4ff92SAndroid Build Coastguard Worker using type_index_t = std::uint_fast8_t;
88*89c4ff92SAndroid Build Coastguard Worker #else
89*89c4ff92SAndroid Build Coastguard Worker using type_index_t = std::uint_least8_t;
90*89c4ff92SAndroid Build Coastguard Worker #endif
91*89c4ff92SAndroid Build Coastguard Worker #endif
92*89c4ff92SAndroid Build Coastguard Worker 
93*89c4ff92SAndroid Build Coastguard Worker namespace detail {
94*89c4ff92SAndroid Build Coastguard Worker 
95*89c4ff92SAndroid Build Coastguard Worker static constexpr type_index_t invalid_value = type_index_t(-1);
96*89c4ff92SAndroid Build Coastguard Worker 
97*89c4ff92SAndroid Build Coastguard Worker template <typename T, typename... Types>
98*89c4ff92SAndroid Build Coastguard Worker struct direct_type;
99*89c4ff92SAndroid Build Coastguard Worker 
100*89c4ff92SAndroid Build Coastguard Worker template <typename T, typename First, typename... Types>
101*89c4ff92SAndroid Build Coastguard Worker struct direct_type<T, First, Types...>
102*89c4ff92SAndroid Build Coastguard Worker {
103*89c4ff92SAndroid Build Coastguard Worker     static constexpr type_index_t index = std::is_same<T, First>::value
104*89c4ff92SAndroid Build Coastguard Worker         ? sizeof...(Types)
105*89c4ff92SAndroid Build Coastguard Worker         : direct_type<T, Types...>::index;
106*89c4ff92SAndroid Build Coastguard Worker };
107*89c4ff92SAndroid Build Coastguard Worker 
108*89c4ff92SAndroid Build Coastguard Worker template <typename T>
109*89c4ff92SAndroid Build Coastguard Worker struct direct_type<T>
110*89c4ff92SAndroid Build Coastguard Worker {
111*89c4ff92SAndroid Build Coastguard Worker     static constexpr type_index_t index = invalid_value;
112*89c4ff92SAndroid Build Coastguard Worker };
113*89c4ff92SAndroid Build Coastguard Worker 
114*89c4ff92SAndroid Build Coastguard Worker #if __cpp_lib_logical_traits >= 201510L
115*89c4ff92SAndroid Build Coastguard Worker 
116*89c4ff92SAndroid Build Coastguard Worker using std::conjunction;
117*89c4ff92SAndroid Build Coastguard Worker using std::disjunction;
118*89c4ff92SAndroid Build Coastguard Worker 
119*89c4ff92SAndroid Build Coastguard Worker #else
120*89c4ff92SAndroid Build Coastguard Worker 
121*89c4ff92SAndroid Build Coastguard Worker template <typename...>
122*89c4ff92SAndroid Build Coastguard Worker struct conjunction : std::true_type {};
123*89c4ff92SAndroid Build Coastguard Worker 
124*89c4ff92SAndroid Build Coastguard Worker template <typename B1>
125*89c4ff92SAndroid Build Coastguard Worker struct conjunction<B1> : B1 {};
126*89c4ff92SAndroid Build Coastguard Worker 
127*89c4ff92SAndroid Build Coastguard Worker template <typename B1, typename B2>
128*89c4ff92SAndroid Build Coastguard Worker struct conjunction<B1, B2> : std::conditional<B1::value, B2, B1>::type {};
129*89c4ff92SAndroid Build Coastguard Worker 
130*89c4ff92SAndroid Build Coastguard Worker template <typename B1, typename... Bs>
131*89c4ff92SAndroid Build Coastguard Worker struct conjunction<B1, Bs...> : std::conditional<B1::value, conjunction<Bs...>, B1>::type {};
132*89c4ff92SAndroid Build Coastguard Worker 
133*89c4ff92SAndroid Build Coastguard Worker template <typename...>
134*89c4ff92SAndroid Build Coastguard Worker struct disjunction : std::false_type {};
135*89c4ff92SAndroid Build Coastguard Worker 
136*89c4ff92SAndroid Build Coastguard Worker template <typename B1>
137*89c4ff92SAndroid Build Coastguard Worker struct disjunction<B1> : B1 {};
138*89c4ff92SAndroid Build Coastguard Worker 
139*89c4ff92SAndroid Build Coastguard Worker template <typename B1, typename B2>
140*89c4ff92SAndroid Build Coastguard Worker struct disjunction<B1, B2> : std::conditional<B1::value, B1, B2>::type {};
141*89c4ff92SAndroid Build Coastguard Worker 
142*89c4ff92SAndroid Build Coastguard Worker template <typename B1, typename... Bs>
143*89c4ff92SAndroid Build Coastguard Worker struct disjunction<B1, Bs...> : std::conditional<B1::value, B1, disjunction<Bs...>>::type {};
144*89c4ff92SAndroid Build Coastguard Worker 
145*89c4ff92SAndroid Build Coastguard Worker #endif
146*89c4ff92SAndroid Build Coastguard Worker 
147*89c4ff92SAndroid Build Coastguard Worker template <typename T, typename... Types>
148*89c4ff92SAndroid Build Coastguard Worker struct convertible_type;
149*89c4ff92SAndroid Build Coastguard Worker 
150*89c4ff92SAndroid Build Coastguard Worker template <typename T, typename First, typename... Types>
151*89c4ff92SAndroid Build Coastguard Worker struct convertible_type<T, First, Types...>
152*89c4ff92SAndroid Build Coastguard Worker {
153*89c4ff92SAndroid Build Coastguard Worker     static constexpr type_index_t index = std::is_convertible<T, First>::value
154*89c4ff92SAndroid Build Coastguard Worker         ? disjunction<std::is_convertible<T, Types>...>::value ? invalid_value : sizeof...(Types)
155*89c4ff92SAndroid Build Coastguard Worker         : convertible_type<T, Types...>::index;
156*89c4ff92SAndroid Build Coastguard Worker };
157*89c4ff92SAndroid Build Coastguard Worker 
158*89c4ff92SAndroid Build Coastguard Worker template <typename T>
159*89c4ff92SAndroid Build Coastguard Worker struct convertible_type<T>
160*89c4ff92SAndroid Build Coastguard Worker {
161*89c4ff92SAndroid Build Coastguard Worker     static constexpr type_index_t index = invalid_value;
162*89c4ff92SAndroid Build Coastguard Worker };
163*89c4ff92SAndroid Build Coastguard Worker 
164*89c4ff92SAndroid Build Coastguard Worker template <typename T, typename... Types>
165*89c4ff92SAndroid Build Coastguard Worker struct value_traits
166*89c4ff92SAndroid Build Coastguard Worker {
167*89c4ff92SAndroid Build Coastguard Worker     using value_type = typename std::remove_const<typename std::remove_reference<T>::type>::type;
168*89c4ff92SAndroid Build Coastguard Worker     using value_type_wrapper = recursive_wrapper<value_type>;
169*89c4ff92SAndroid Build Coastguard Worker     static constexpr type_index_t direct_index = direct_type<value_type, Types...>::index;
170*89c4ff92SAndroid Build Coastguard Worker     static constexpr bool is_direct = direct_index != invalid_value;
171*89c4ff92SAndroid Build Coastguard Worker     static constexpr type_index_t index_direct_or_wrapper = is_direct ? direct_index : direct_type<value_type_wrapper, Types...>::index;
172*89c4ff92SAndroid Build Coastguard Worker     static constexpr bool is_direct_or_wrapper = index_direct_or_wrapper != invalid_value;
173*89c4ff92SAndroid Build Coastguard Worker     static constexpr type_index_t index = is_direct_or_wrapper ? index_direct_or_wrapper : convertible_type<value_type, Types...>::index;
174*89c4ff92SAndroid Build Coastguard Worker     static constexpr bool is_valid = index != invalid_value;
175*89c4ff92SAndroid Build Coastguard Worker     static constexpr type_index_t tindex = is_valid ? sizeof...(Types)-index : 0;
176*89c4ff92SAndroid Build Coastguard Worker     using target_type = typename std::tuple_element<tindex, std::tuple<void, Types...>>::type;
177*89c4ff92SAndroid Build Coastguard Worker };
178*89c4ff92SAndroid Build Coastguard Worker 
179*89c4ff92SAndroid Build Coastguard Worker template <typename Src, typename Dest>
180*89c4ff92SAndroid Build Coastguard Worker struct copy_cvref
181*89c4ff92SAndroid Build Coastguard Worker {
182*89c4ff92SAndroid Build Coastguard Worker     using type = Dest;
183*89c4ff92SAndroid Build Coastguard Worker };
184*89c4ff92SAndroid Build Coastguard Worker 
185*89c4ff92SAndroid Build Coastguard Worker template <typename Src, typename Dest>
186*89c4ff92SAndroid Build Coastguard Worker struct copy_cvref<Src const&, Dest>
187*89c4ff92SAndroid Build Coastguard Worker {
188*89c4ff92SAndroid Build Coastguard Worker     using type = Dest const&;
189*89c4ff92SAndroid Build Coastguard Worker };
190*89c4ff92SAndroid Build Coastguard Worker 
191*89c4ff92SAndroid Build Coastguard Worker template <typename Src, typename Dest>
192*89c4ff92SAndroid Build Coastguard Worker struct copy_cvref<Src&, Dest>
193*89c4ff92SAndroid Build Coastguard Worker {
194*89c4ff92SAndroid Build Coastguard Worker     using type = Dest&;
195*89c4ff92SAndroid Build Coastguard Worker };
196*89c4ff92SAndroid Build Coastguard Worker 
197*89c4ff92SAndroid Build Coastguard Worker template <typename Src, typename Dest>
198*89c4ff92SAndroid Build Coastguard Worker struct copy_cvref<Src&&, Dest>
199*89c4ff92SAndroid Build Coastguard Worker {
200*89c4ff92SAndroid Build Coastguard Worker     using type = Dest&&;
201*89c4ff92SAndroid Build Coastguard Worker };
202*89c4ff92SAndroid Build Coastguard Worker 
203*89c4ff92SAndroid Build Coastguard Worker template <typename F, typename = void>
204*89c4ff92SAndroid Build Coastguard Worker struct deduced_result_type
205*89c4ff92SAndroid Build Coastguard Worker {};
206*89c4ff92SAndroid Build Coastguard Worker 
207*89c4ff92SAndroid Build Coastguard Worker template <typename F, typename... Args>
208*89c4ff92SAndroid Build Coastguard Worker struct deduced_result_type<F(Args...), decltype((void)std::declval<F>()(std::declval<Args>()...))>
209*89c4ff92SAndroid Build Coastguard Worker {
210*89c4ff92SAndroid Build Coastguard Worker     using type = decltype(std::declval<F>()(std::declval<Args>()...));
211*89c4ff92SAndroid Build Coastguard Worker };
212*89c4ff92SAndroid Build Coastguard Worker 
213*89c4ff92SAndroid Build Coastguard Worker template <typename F, typename = void>
214*89c4ff92SAndroid Build Coastguard Worker struct visitor_result_type : deduced_result_type<F>
215*89c4ff92SAndroid Build Coastguard Worker {};
216*89c4ff92SAndroid Build Coastguard Worker 
217*89c4ff92SAndroid Build Coastguard Worker // specialization for explicit result_type member in visitor class
218*89c4ff92SAndroid Build Coastguard Worker template <typename F, typename... Args>
219*89c4ff92SAndroid Build Coastguard Worker struct visitor_result_type<F(Args...), decltype((void)std::declval<typename std::decay<F>::type::result_type>())>
220*89c4ff92SAndroid Build Coastguard Worker {
221*89c4ff92SAndroid Build Coastguard Worker     using type = typename std::decay<F>::type::result_type;
222*89c4ff92SAndroid Build Coastguard Worker };
223*89c4ff92SAndroid Build Coastguard Worker 
224*89c4ff92SAndroid Build Coastguard Worker template <typename F, typename T>
225*89c4ff92SAndroid Build Coastguard Worker using result_of_unary_visit = typename visitor_result_type<F&&(T&&)>::type;
226*89c4ff92SAndroid Build Coastguard Worker 
227*89c4ff92SAndroid Build Coastguard Worker template <typename F, typename T>
228*89c4ff92SAndroid Build Coastguard Worker using result_of_binary_visit = typename visitor_result_type<F&&(T&&, T&&)>::type;
229*89c4ff92SAndroid Build Coastguard Worker 
230*89c4ff92SAndroid Build Coastguard Worker template <type_index_t arg1, type_index_t... others>
231*89c4ff92SAndroid Build Coastguard Worker struct static_max;
232*89c4ff92SAndroid Build Coastguard Worker 
233*89c4ff92SAndroid Build Coastguard Worker template <type_index_t arg>
234*89c4ff92SAndroid Build Coastguard Worker struct static_max<arg>
235*89c4ff92SAndroid Build Coastguard Worker {
236*89c4ff92SAndroid Build Coastguard Worker     static const type_index_t value = arg;
237*89c4ff92SAndroid Build Coastguard Worker };
238*89c4ff92SAndroid Build Coastguard Worker 
239*89c4ff92SAndroid Build Coastguard Worker template <type_index_t arg1, type_index_t arg2, type_index_t... others>
240*89c4ff92SAndroid Build Coastguard Worker struct static_max<arg1, arg2, others...>
241*89c4ff92SAndroid Build Coastguard Worker {
242*89c4ff92SAndroid Build Coastguard Worker     static const type_index_t value = arg1 >= arg2 ? static_max<arg1, others...>::value : static_max<arg2, others...>::value;
243*89c4ff92SAndroid Build Coastguard Worker };
244*89c4ff92SAndroid Build Coastguard Worker 
245*89c4ff92SAndroid Build Coastguard Worker template <typename... Types>
246*89c4ff92SAndroid Build Coastguard Worker struct variant_helper;
247*89c4ff92SAndroid Build Coastguard Worker 
248*89c4ff92SAndroid Build Coastguard Worker template <typename T, typename... Types>
249*89c4ff92SAndroid Build Coastguard Worker struct variant_helper<T, Types...>
250*89c4ff92SAndroid Build Coastguard Worker {
destroymapbox::util::detail::variant_helper251*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE static void destroy(const type_index_t type_index, void* data)
252*89c4ff92SAndroid Build Coastguard Worker     {
253*89c4ff92SAndroid Build Coastguard Worker         if (type_index == sizeof...(Types))
254*89c4ff92SAndroid Build Coastguard Worker         {
255*89c4ff92SAndroid Build Coastguard Worker             reinterpret_cast<T*>(data)->~T();
256*89c4ff92SAndroid Build Coastguard Worker         }
257*89c4ff92SAndroid Build Coastguard Worker         else
258*89c4ff92SAndroid Build Coastguard Worker         {
259*89c4ff92SAndroid Build Coastguard Worker             variant_helper<Types...>::destroy(type_index, data);
260*89c4ff92SAndroid Build Coastguard Worker         }
261*89c4ff92SAndroid Build Coastguard Worker     }
262*89c4ff92SAndroid Build Coastguard Worker 
movemapbox::util::detail::variant_helper263*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE static void move(const type_index_t old_type_index, void* old_value, void* new_value)
264*89c4ff92SAndroid Build Coastguard Worker     {
265*89c4ff92SAndroid Build Coastguard Worker         if (old_type_index == sizeof...(Types))
266*89c4ff92SAndroid Build Coastguard Worker         {
267*89c4ff92SAndroid Build Coastguard Worker             new (new_value) T(std::move(*reinterpret_cast<T*>(old_value)));
268*89c4ff92SAndroid Build Coastguard Worker         }
269*89c4ff92SAndroid Build Coastguard Worker         else
270*89c4ff92SAndroid Build Coastguard Worker         {
271*89c4ff92SAndroid Build Coastguard Worker             variant_helper<Types...>::move(old_type_index, old_value, new_value);
272*89c4ff92SAndroid Build Coastguard Worker         }
273*89c4ff92SAndroid Build Coastguard Worker     }
274*89c4ff92SAndroid Build Coastguard Worker 
copymapbox::util::detail::variant_helper275*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE static void copy(const type_index_t old_type_index, const void* old_value, void* new_value)
276*89c4ff92SAndroid Build Coastguard Worker     {
277*89c4ff92SAndroid Build Coastguard Worker         if (old_type_index == sizeof...(Types))
278*89c4ff92SAndroid Build Coastguard Worker         {
279*89c4ff92SAndroid Build Coastguard Worker             new (new_value) T(*reinterpret_cast<const T*>(old_value));
280*89c4ff92SAndroid Build Coastguard Worker         }
281*89c4ff92SAndroid Build Coastguard Worker         else
282*89c4ff92SAndroid Build Coastguard Worker         {
283*89c4ff92SAndroid Build Coastguard Worker             variant_helper<Types...>::copy(old_type_index, old_value, new_value);
284*89c4ff92SAndroid Build Coastguard Worker         }
285*89c4ff92SAndroid Build Coastguard Worker     }
286*89c4ff92SAndroid Build Coastguard Worker };
287*89c4ff92SAndroid Build Coastguard Worker 
288*89c4ff92SAndroid Build Coastguard Worker template <>
289*89c4ff92SAndroid Build Coastguard Worker struct variant_helper<>
290*89c4ff92SAndroid Build Coastguard Worker {
destroymapbox::util::detail::variant_helper291*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE static void destroy(const type_index_t, void*) {}
movemapbox::util::detail::variant_helper292*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE static void move(const type_index_t, void*, void*) {}
copymapbox::util::detail::variant_helper293*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE static void copy(const type_index_t, const void*, void*) {}
294*89c4ff92SAndroid Build Coastguard Worker };
295*89c4ff92SAndroid Build Coastguard Worker 
296*89c4ff92SAndroid Build Coastguard Worker template <typename T>
297*89c4ff92SAndroid Build Coastguard Worker struct unwrapper
298*89c4ff92SAndroid Build Coastguard Worker {
299*89c4ff92SAndroid Build Coastguard Worker     using value_type = T;
300*89c4ff92SAndroid Build Coastguard Worker 
301*89c4ff92SAndroid Build Coastguard Worker     template <typename V>
applymapbox::util::detail::unwrapper302*89c4ff92SAndroid Build Coastguard Worker     static auto apply(typename std::remove_reference<V>::type& var)
303*89c4ff92SAndroid Build Coastguard Worker         -> typename std::enable_if<std::is_lvalue_reference<V>::value,
304*89c4ff92SAndroid Build Coastguard Worker                     decltype(var.template get_unchecked<T>())>::type
305*89c4ff92SAndroid Build Coastguard Worker     {
306*89c4ff92SAndroid Build Coastguard Worker         return var.template get_unchecked<T>();
307*89c4ff92SAndroid Build Coastguard Worker     }
308*89c4ff92SAndroid Build Coastguard Worker 
309*89c4ff92SAndroid Build Coastguard Worker     template <typename V>
applymapbox::util::detail::unwrapper310*89c4ff92SAndroid Build Coastguard Worker     static auto apply(typename std::remove_reference<V>::type& var)
311*89c4ff92SAndroid Build Coastguard Worker         -> typename std::enable_if<!std::is_lvalue_reference<V>::value,
312*89c4ff92SAndroid Build Coastguard Worker                     decltype(std::move(var.template get_unchecked<T>()))>::type
313*89c4ff92SAndroid Build Coastguard Worker     {
314*89c4ff92SAndroid Build Coastguard Worker         return std::move(var.template get_unchecked<T>());
315*89c4ff92SAndroid Build Coastguard Worker     }
316*89c4ff92SAndroid Build Coastguard Worker };
317*89c4ff92SAndroid Build Coastguard Worker 
318*89c4ff92SAndroid Build Coastguard Worker template <typename T>
319*89c4ff92SAndroid Build Coastguard Worker struct unwrapper<recursive_wrapper<T>> : unwrapper<T>
320*89c4ff92SAndroid Build Coastguard Worker {};
321*89c4ff92SAndroid Build Coastguard Worker 
322*89c4ff92SAndroid Build Coastguard Worker template <typename T>
323*89c4ff92SAndroid Build Coastguard Worker struct unwrapper<std::reference_wrapper<T>> : unwrapper<T>
324*89c4ff92SAndroid Build Coastguard Worker {};
325*89c4ff92SAndroid Build Coastguard Worker 
326*89c4ff92SAndroid Build Coastguard Worker template <typename R, typename... Types>
327*89c4ff92SAndroid Build Coastguard Worker struct dispatcher;
328*89c4ff92SAndroid Build Coastguard Worker 
329*89c4ff92SAndroid Build Coastguard Worker template <typename R, typename T, typename... Types>
330*89c4ff92SAndroid Build Coastguard Worker struct dispatcher<R, T, Types...>
331*89c4ff92SAndroid Build Coastguard Worker {
332*89c4ff92SAndroid Build Coastguard Worker     template <typename V, typename F>
applymapbox::util::detail::dispatcher333*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE static R apply(V&& v, F&& f)
334*89c4ff92SAndroid Build Coastguard Worker     {
335*89c4ff92SAndroid Build Coastguard Worker         if (v.template is<T>())
336*89c4ff92SAndroid Build Coastguard Worker         {
337*89c4ff92SAndroid Build Coastguard Worker             return std::forward<F>(f)(unwrapper<T>::template apply<V>(v));
338*89c4ff92SAndroid Build Coastguard Worker         }
339*89c4ff92SAndroid Build Coastguard Worker         else
340*89c4ff92SAndroid Build Coastguard Worker         {
341*89c4ff92SAndroid Build Coastguard Worker             return dispatcher<R, Types...>::apply(std::forward<V>(v), std::forward<F>(f));
342*89c4ff92SAndroid Build Coastguard Worker         }
343*89c4ff92SAndroid Build Coastguard Worker     }
344*89c4ff92SAndroid Build Coastguard Worker };
345*89c4ff92SAndroid Build Coastguard Worker 
346*89c4ff92SAndroid Build Coastguard Worker template <typename R, typename T>
347*89c4ff92SAndroid Build Coastguard Worker struct dispatcher<R, T>
348*89c4ff92SAndroid Build Coastguard Worker {
349*89c4ff92SAndroid Build Coastguard Worker     template <typename V, typename F>
applymapbox::util::detail::dispatcher350*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE static R apply(V&& v, F&& f)
351*89c4ff92SAndroid Build Coastguard Worker     {
352*89c4ff92SAndroid Build Coastguard Worker         return std::forward<F>(f)(unwrapper<T>::template apply<V>(v));
353*89c4ff92SAndroid Build Coastguard Worker     }
354*89c4ff92SAndroid Build Coastguard Worker };
355*89c4ff92SAndroid Build Coastguard Worker 
356*89c4ff92SAndroid Build Coastguard Worker template <typename R, typename T, typename... Types>
357*89c4ff92SAndroid Build Coastguard Worker struct binary_dispatcher_rhs;
358*89c4ff92SAndroid Build Coastguard Worker 
359*89c4ff92SAndroid Build Coastguard Worker template <typename R, typename T0, typename T1, typename... Types>
360*89c4ff92SAndroid Build Coastguard Worker struct binary_dispatcher_rhs<R, T0, T1, Types...>
361*89c4ff92SAndroid Build Coastguard Worker {
362*89c4ff92SAndroid Build Coastguard Worker     template <typename V, typename F>
applymapbox::util::detail::binary_dispatcher_rhs363*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE static R apply(V&& lhs, V&& rhs, F&& f)
364*89c4ff92SAndroid Build Coastguard Worker     {
365*89c4ff92SAndroid Build Coastguard Worker         if (rhs.template is<T1>()) // call binary functor
366*89c4ff92SAndroid Build Coastguard Worker         {
367*89c4ff92SAndroid Build Coastguard Worker             return std::forward<F>(f)(unwrapper<T0>::template apply<V>(lhs),
368*89c4ff92SAndroid Build Coastguard Worker                                       unwrapper<T1>::template apply<V>(rhs));
369*89c4ff92SAndroid Build Coastguard Worker         }
370*89c4ff92SAndroid Build Coastguard Worker         else
371*89c4ff92SAndroid Build Coastguard Worker         {
372*89c4ff92SAndroid Build Coastguard Worker             return binary_dispatcher_rhs<R, T0, Types...>::apply(std::forward<V>(lhs),
373*89c4ff92SAndroid Build Coastguard Worker                                                                  std::forward<V>(rhs),
374*89c4ff92SAndroid Build Coastguard Worker                                                                  std::forward<F>(f));
375*89c4ff92SAndroid Build Coastguard Worker         }
376*89c4ff92SAndroid Build Coastguard Worker     }
377*89c4ff92SAndroid Build Coastguard Worker };
378*89c4ff92SAndroid Build Coastguard Worker 
379*89c4ff92SAndroid Build Coastguard Worker template <typename R, typename T0, typename T1>
380*89c4ff92SAndroid Build Coastguard Worker struct binary_dispatcher_rhs<R, T0, T1>
381*89c4ff92SAndroid Build Coastguard Worker {
382*89c4ff92SAndroid Build Coastguard Worker     template <typename V, typename F>
applymapbox::util::detail::binary_dispatcher_rhs383*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE static R apply(V&& lhs, V&& rhs, F&& f)
384*89c4ff92SAndroid Build Coastguard Worker     {
385*89c4ff92SAndroid Build Coastguard Worker         return std::forward<F>(f)(unwrapper<T0>::template apply<V>(lhs),
386*89c4ff92SAndroid Build Coastguard Worker                                   unwrapper<T1>::template apply<V>(rhs));
387*89c4ff92SAndroid Build Coastguard Worker     }
388*89c4ff92SAndroid Build Coastguard Worker };
389*89c4ff92SAndroid Build Coastguard Worker 
390*89c4ff92SAndroid Build Coastguard Worker template <typename R, typename T, typename... Types>
391*89c4ff92SAndroid Build Coastguard Worker struct binary_dispatcher_lhs;
392*89c4ff92SAndroid Build Coastguard Worker 
393*89c4ff92SAndroid Build Coastguard Worker template <typename R, typename T0, typename T1, typename... Types>
394*89c4ff92SAndroid Build Coastguard Worker struct binary_dispatcher_lhs<R, T0, T1, Types...>
395*89c4ff92SAndroid Build Coastguard Worker {
396*89c4ff92SAndroid Build Coastguard Worker     template <typename V, typename F>
applymapbox::util::detail::binary_dispatcher_lhs397*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE static R apply(V&& lhs, V&& rhs, F&& f)
398*89c4ff92SAndroid Build Coastguard Worker     {
399*89c4ff92SAndroid Build Coastguard Worker         if (lhs.template is<T1>()) // call binary functor
400*89c4ff92SAndroid Build Coastguard Worker         {
401*89c4ff92SAndroid Build Coastguard Worker             return std::forward<F>(f)(unwrapper<T1>::template apply<V>(lhs),
402*89c4ff92SAndroid Build Coastguard Worker                                       unwrapper<T0>::template apply<V>(rhs));
403*89c4ff92SAndroid Build Coastguard Worker         }
404*89c4ff92SAndroid Build Coastguard Worker         else
405*89c4ff92SAndroid Build Coastguard Worker         {
406*89c4ff92SAndroid Build Coastguard Worker             return binary_dispatcher_lhs<R, T0, Types...>::apply(std::forward<V>(lhs),
407*89c4ff92SAndroid Build Coastguard Worker                                                                  std::forward<V>(rhs),
408*89c4ff92SAndroid Build Coastguard Worker                                                                  std::forward<F>(f));
409*89c4ff92SAndroid Build Coastguard Worker         }
410*89c4ff92SAndroid Build Coastguard Worker     }
411*89c4ff92SAndroid Build Coastguard Worker };
412*89c4ff92SAndroid Build Coastguard Worker 
413*89c4ff92SAndroid Build Coastguard Worker template <typename R, typename T0, typename T1>
414*89c4ff92SAndroid Build Coastguard Worker struct binary_dispatcher_lhs<R, T0, T1>
415*89c4ff92SAndroid Build Coastguard Worker {
416*89c4ff92SAndroid Build Coastguard Worker     template <typename V, typename F>
applymapbox::util::detail::binary_dispatcher_lhs417*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE static R apply(V&& lhs, V&& rhs, F&& f)
418*89c4ff92SAndroid Build Coastguard Worker     {
419*89c4ff92SAndroid Build Coastguard Worker         return std::forward<F>(f)(unwrapper<T1>::template apply<V>(lhs),
420*89c4ff92SAndroid Build Coastguard Worker                                   unwrapper<T0>::template apply<V>(rhs));
421*89c4ff92SAndroid Build Coastguard Worker     }
422*89c4ff92SAndroid Build Coastguard Worker };
423*89c4ff92SAndroid Build Coastguard Worker 
424*89c4ff92SAndroid Build Coastguard Worker template <typename R, typename... Types>
425*89c4ff92SAndroid Build Coastguard Worker struct binary_dispatcher;
426*89c4ff92SAndroid Build Coastguard Worker 
427*89c4ff92SAndroid Build Coastguard Worker template <typename R, typename T, typename... Types>
428*89c4ff92SAndroid Build Coastguard Worker struct binary_dispatcher<R, T, Types...>
429*89c4ff92SAndroid Build Coastguard Worker {
430*89c4ff92SAndroid Build Coastguard Worker     template <typename V, typename F>
applymapbox::util::detail::binary_dispatcher431*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE static R apply(V&& v0, V&& v1, F&& f)
432*89c4ff92SAndroid Build Coastguard Worker     {
433*89c4ff92SAndroid Build Coastguard Worker         if (v0.template is<T>())
434*89c4ff92SAndroid Build Coastguard Worker         {
435*89c4ff92SAndroid Build Coastguard Worker             if (v1.template is<T>())
436*89c4ff92SAndroid Build Coastguard Worker             {
437*89c4ff92SAndroid Build Coastguard Worker                 return std::forward<F>(f)(unwrapper<T>::template apply<V>(v0),
438*89c4ff92SAndroid Build Coastguard Worker                                           unwrapper<T>::template apply<V>(v1)); // call binary functor
439*89c4ff92SAndroid Build Coastguard Worker             }
440*89c4ff92SAndroid Build Coastguard Worker             else
441*89c4ff92SAndroid Build Coastguard Worker             {
442*89c4ff92SAndroid Build Coastguard Worker                 return binary_dispatcher_rhs<R, T, Types...>::apply(std::forward<V>(v0),
443*89c4ff92SAndroid Build Coastguard Worker                                                                     std::forward<V>(v1),
444*89c4ff92SAndroid Build Coastguard Worker                                                                     std::forward<F>(f));
445*89c4ff92SAndroid Build Coastguard Worker             }
446*89c4ff92SAndroid Build Coastguard Worker         }
447*89c4ff92SAndroid Build Coastguard Worker         else if (v1.template is<T>())
448*89c4ff92SAndroid Build Coastguard Worker         {
449*89c4ff92SAndroid Build Coastguard Worker             return binary_dispatcher_lhs<R, T, Types...>::apply(std::forward<V>(v0),
450*89c4ff92SAndroid Build Coastguard Worker                                                                 std::forward<V>(v1),
451*89c4ff92SAndroid Build Coastguard Worker                                                                 std::forward<F>(f));
452*89c4ff92SAndroid Build Coastguard Worker         }
453*89c4ff92SAndroid Build Coastguard Worker         return binary_dispatcher<R, Types...>::apply(std::forward<V>(v0),
454*89c4ff92SAndroid Build Coastguard Worker                                                      std::forward<V>(v1),
455*89c4ff92SAndroid Build Coastguard Worker                                                      std::forward<F>(f));
456*89c4ff92SAndroid Build Coastguard Worker     }
457*89c4ff92SAndroid Build Coastguard Worker };
458*89c4ff92SAndroid Build Coastguard Worker 
459*89c4ff92SAndroid Build Coastguard Worker template <typename R, typename T>
460*89c4ff92SAndroid Build Coastguard Worker struct binary_dispatcher<R, T>
461*89c4ff92SAndroid Build Coastguard Worker {
462*89c4ff92SAndroid Build Coastguard Worker     template <typename V, typename F>
applymapbox::util::detail::binary_dispatcher463*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE static R apply(V&& v0, V&& v1, F&& f)
464*89c4ff92SAndroid Build Coastguard Worker     {
465*89c4ff92SAndroid Build Coastguard Worker         return std::forward<F>(f)(unwrapper<T>::template apply<V>(v0),
466*89c4ff92SAndroid Build Coastguard Worker                                   unwrapper<T>::template apply<V>(v1)); // call binary functor
467*89c4ff92SAndroid Build Coastguard Worker     }
468*89c4ff92SAndroid Build Coastguard Worker };
469*89c4ff92SAndroid Build Coastguard Worker 
470*89c4ff92SAndroid Build Coastguard Worker // comparator functors
471*89c4ff92SAndroid Build Coastguard Worker struct equal_comp
472*89c4ff92SAndroid Build Coastguard Worker {
473*89c4ff92SAndroid Build Coastguard Worker     template <typename T>
operator ()mapbox::util::detail::equal_comp474*89c4ff92SAndroid Build Coastguard Worker     bool operator()(T const& lhs, T const& rhs) const
475*89c4ff92SAndroid Build Coastguard Worker     {
476*89c4ff92SAndroid Build Coastguard Worker         return lhs == rhs;
477*89c4ff92SAndroid Build Coastguard Worker     }
478*89c4ff92SAndroid Build Coastguard Worker };
479*89c4ff92SAndroid Build Coastguard Worker 
480*89c4ff92SAndroid Build Coastguard Worker struct less_comp
481*89c4ff92SAndroid Build Coastguard Worker {
482*89c4ff92SAndroid Build Coastguard Worker     template <typename T>
operator ()mapbox::util::detail::less_comp483*89c4ff92SAndroid Build Coastguard Worker     bool operator()(T const& lhs, T const& rhs) const
484*89c4ff92SAndroid Build Coastguard Worker     {
485*89c4ff92SAndroid Build Coastguard Worker         return lhs < rhs;
486*89c4ff92SAndroid Build Coastguard Worker     }
487*89c4ff92SAndroid Build Coastguard Worker };
488*89c4ff92SAndroid Build Coastguard Worker 
489*89c4ff92SAndroid Build Coastguard Worker template <typename Variant, typename Comp>
490*89c4ff92SAndroid Build Coastguard Worker class comparer
491*89c4ff92SAndroid Build Coastguard Worker {
492*89c4ff92SAndroid Build Coastguard Worker public:
comparer(Variant const & lhs)493*89c4ff92SAndroid Build Coastguard Worker     explicit comparer(Variant const& lhs) noexcept
494*89c4ff92SAndroid Build Coastguard Worker         : lhs_(lhs) {}
495*89c4ff92SAndroid Build Coastguard Worker     comparer& operator=(comparer const&) = delete;
496*89c4ff92SAndroid Build Coastguard Worker     // visitor
497*89c4ff92SAndroid Build Coastguard Worker     template <typename T>
operator ()(T const & rhs_content) const498*89c4ff92SAndroid Build Coastguard Worker     bool operator()(T const& rhs_content) const
499*89c4ff92SAndroid Build Coastguard Worker     {
500*89c4ff92SAndroid Build Coastguard Worker         T const& lhs_content = lhs_.template get_unchecked<T>();
501*89c4ff92SAndroid Build Coastguard Worker         return Comp()(lhs_content, rhs_content);
502*89c4ff92SAndroid Build Coastguard Worker     }
503*89c4ff92SAndroid Build Coastguard Worker 
504*89c4ff92SAndroid Build Coastguard Worker private:
505*89c4ff92SAndroid Build Coastguard Worker     Variant const& lhs_;
506*89c4ff92SAndroid Build Coastguard Worker };
507*89c4ff92SAndroid Build Coastguard Worker 
508*89c4ff92SAndroid Build Coastguard Worker // hashing visitor
509*89c4ff92SAndroid Build Coastguard Worker struct hasher
510*89c4ff92SAndroid Build Coastguard Worker {
511*89c4ff92SAndroid Build Coastguard Worker     template <typename T>
operator ()mapbox::util::detail::hasher512*89c4ff92SAndroid Build Coastguard Worker     std::size_t operator()(const T& hashable) const
513*89c4ff92SAndroid Build Coastguard Worker     {
514*89c4ff92SAndroid Build Coastguard Worker         return std::hash<T>{}(hashable);
515*89c4ff92SAndroid Build Coastguard Worker     }
516*89c4ff92SAndroid Build Coastguard Worker };
517*89c4ff92SAndroid Build Coastguard Worker 
518*89c4ff92SAndroid Build Coastguard Worker } // namespace detail
519*89c4ff92SAndroid Build Coastguard Worker 
520*89c4ff92SAndroid Build Coastguard Worker struct no_init {};
521*89c4ff92SAndroid Build Coastguard Worker 
522*89c4ff92SAndroid Build Coastguard Worker template <typename... Types>
523*89c4ff92SAndroid Build Coastguard Worker class variant
524*89c4ff92SAndroid Build Coastguard Worker {
525*89c4ff92SAndroid Build Coastguard Worker     static_assert(sizeof...(Types) > 0, "Template parameter type list of variant can not be empty.");
526*89c4ff92SAndroid Build Coastguard Worker     static_assert(!detail::disjunction<std::is_reference<Types>...>::value, "Variant can not hold reference types. Maybe use std::reference_wrapper?");
527*89c4ff92SAndroid Build Coastguard Worker     static_assert(!detail::disjunction<std::is_array<Types>...>::value, "Variant can not hold array types.");
528*89c4ff92SAndroid Build Coastguard Worker     static_assert(sizeof...(Types) < std::numeric_limits<type_index_t>::max(), "Internal index type must be able to accommodate all alternatives.");
529*89c4ff92SAndroid Build Coastguard Worker private:
530*89c4ff92SAndroid Build Coastguard Worker     static const std::size_t data_size = detail::static_max<sizeof(Types)...>::value;
531*89c4ff92SAndroid Build Coastguard Worker     static const std::size_t data_align = detail::static_max<alignof(Types)...>::value;
532*89c4ff92SAndroid Build Coastguard Worker public:
533*89c4ff92SAndroid Build Coastguard Worker     struct adapted_variant_tag;
534*89c4ff92SAndroid Build Coastguard Worker     using types = std::tuple<Types...>;
535*89c4ff92SAndroid Build Coastguard Worker private:
536*89c4ff92SAndroid Build Coastguard Worker     using first_type = typename std::tuple_element<0, types>::type;
537*89c4ff92SAndroid Build Coastguard Worker     using unwrap_first_type = typename detail::unwrapper<first_type>::value_type;
538*89c4ff92SAndroid Build Coastguard Worker     using data_type = typename std::aligned_storage<data_size, data_align>::type;
539*89c4ff92SAndroid Build Coastguard Worker     using helper_type = detail::variant_helper<Types...>;
540*89c4ff92SAndroid Build Coastguard Worker 
541*89c4ff92SAndroid Build Coastguard Worker     template <typename V, typename T = unwrap_first_type>
542*89c4ff92SAndroid Build Coastguard Worker         using alternative_ref = typename detail::copy_cvref<V, T>::type;
543*89c4ff92SAndroid Build Coastguard Worker 
544*89c4ff92SAndroid Build Coastguard Worker     type_index_t type_index;
545*89c4ff92SAndroid Build Coastguard Worker #ifdef __clang_analyzer__
546*89c4ff92SAndroid Build Coastguard Worker     data_type data {};
547*89c4ff92SAndroid Build Coastguard Worker #else
548*89c4ff92SAndroid Build Coastguard Worker     data_type data;
549*89c4ff92SAndroid Build Coastguard Worker #endif
550*89c4ff92SAndroid Build Coastguard Worker 
551*89c4ff92SAndroid Build Coastguard Worker public:
variant()552*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE variant() noexcept(std::is_nothrow_default_constructible<first_type>::value)
553*89c4ff92SAndroid Build Coastguard Worker         : type_index(sizeof...(Types)-1)
554*89c4ff92SAndroid Build Coastguard Worker     {
555*89c4ff92SAndroid Build Coastguard Worker         static_assert(std::is_default_constructible<first_type>::value, "First type in variant must be default constructible to allow default construction of variant.");
556*89c4ff92SAndroid Build Coastguard Worker         new (&data) first_type();
557*89c4ff92SAndroid Build Coastguard Worker     }
558*89c4ff92SAndroid Build Coastguard Worker 
variant(no_init)559*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE variant(no_init) noexcept
560*89c4ff92SAndroid Build Coastguard Worker         : type_index(detail::invalid_value) {}
561*89c4ff92SAndroid Build Coastguard Worker 
562*89c4ff92SAndroid Build Coastguard Worker     // http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers
563*89c4ff92SAndroid Build Coastguard Worker     template <typename T, typename Traits = detail::value_traits<T, Types...>,
564*89c4ff92SAndroid Build Coastguard Worker               typename Enable = typename std::enable_if<Traits::is_valid && !std::is_same<variant<Types...>, typename Traits::value_type>::value>::type >
variant(T && val)565*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE variant(T&& val) noexcept(std::is_nothrow_constructible<typename Traits::target_type, T&&>::value)
566*89c4ff92SAndroid Build Coastguard Worker         : type_index(Traits::index)
567*89c4ff92SAndroid Build Coastguard Worker     {
568*89c4ff92SAndroid Build Coastguard Worker         new (&data) typename Traits::target_type(std::forward<T>(val));
569*89c4ff92SAndroid Build Coastguard Worker     }
570*89c4ff92SAndroid Build Coastguard Worker 
variant(variant<Types...> const & old)571*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE variant(variant<Types...> const& old)
572*89c4ff92SAndroid Build Coastguard Worker         : type_index(old.type_index)
573*89c4ff92SAndroid Build Coastguard Worker     {
574*89c4ff92SAndroid Build Coastguard Worker         helper_type::copy(old.type_index, &old.data, &data);
575*89c4ff92SAndroid Build Coastguard Worker     }
576*89c4ff92SAndroid Build Coastguard Worker 
variant(variant<Types...> && old)577*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE variant(variant<Types...>&& old)
578*89c4ff92SAndroid Build Coastguard Worker         noexcept(detail::conjunction<std::is_nothrow_move_constructible<Types>...>::value)
579*89c4ff92SAndroid Build Coastguard Worker         : type_index(old.type_index)
580*89c4ff92SAndroid Build Coastguard Worker     {
581*89c4ff92SAndroid Build Coastguard Worker         helper_type::move(old.type_index, &old.data, &data);
582*89c4ff92SAndroid Build Coastguard Worker     }
583*89c4ff92SAndroid Build Coastguard Worker 
584*89c4ff92SAndroid Build Coastguard Worker private:
copy_assign(variant<Types...> const & rhs)585*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE void copy_assign(variant<Types...> const& rhs)
586*89c4ff92SAndroid Build Coastguard Worker     {
587*89c4ff92SAndroid Build Coastguard Worker         helper_type::destroy(type_index, &data);
588*89c4ff92SAndroid Build Coastguard Worker         type_index = detail::invalid_value;
589*89c4ff92SAndroid Build Coastguard Worker         helper_type::copy(rhs.type_index, &rhs.data, &data);
590*89c4ff92SAndroid Build Coastguard Worker         type_index = rhs.type_index;
591*89c4ff92SAndroid Build Coastguard Worker     }
592*89c4ff92SAndroid Build Coastguard Worker 
move_assign(variant<Types...> && rhs)593*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE void move_assign(variant<Types...>&& rhs)
594*89c4ff92SAndroid Build Coastguard Worker     {
595*89c4ff92SAndroid Build Coastguard Worker         helper_type::destroy(type_index, &data);
596*89c4ff92SAndroid Build Coastguard Worker         type_index = detail::invalid_value;
597*89c4ff92SAndroid Build Coastguard Worker         helper_type::move(rhs.type_index, &rhs.data, &data);
598*89c4ff92SAndroid Build Coastguard Worker         type_index = rhs.type_index;
599*89c4ff92SAndroid Build Coastguard Worker     }
600*89c4ff92SAndroid Build Coastguard Worker 
601*89c4ff92SAndroid Build Coastguard Worker public:
operator =(variant<Types...> && other)602*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE variant<Types...>& operator=(variant<Types...>&& other)
603*89c4ff92SAndroid Build Coastguard Worker         // note we check for nothrow-constructible, not nothrow-assignable, since
604*89c4ff92SAndroid Build Coastguard Worker         // move_assign uses move-construction via placement new.
605*89c4ff92SAndroid Build Coastguard Worker         noexcept(detail::conjunction<std::is_nothrow_move_constructible<Types>...>::value)
606*89c4ff92SAndroid Build Coastguard Worker     {
607*89c4ff92SAndroid Build Coastguard Worker         if (this == &other) { // playing safe in release mode, hit assertion in debug.
608*89c4ff92SAndroid Build Coastguard Worker             assert(false);
609*89c4ff92SAndroid Build Coastguard Worker             return *this;
610*89c4ff92SAndroid Build Coastguard Worker         }
611*89c4ff92SAndroid Build Coastguard Worker         move_assign(std::move(other));
612*89c4ff92SAndroid Build Coastguard Worker         return *this;
613*89c4ff92SAndroid Build Coastguard Worker     }
614*89c4ff92SAndroid Build Coastguard Worker 
operator =(variant<Types...> const & other)615*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE variant<Types...>& operator=(variant<Types...> const& other)
616*89c4ff92SAndroid Build Coastguard Worker     {
617*89c4ff92SAndroid Build Coastguard Worker         if (this != &other)
618*89c4ff92SAndroid Build Coastguard Worker             copy_assign(other);
619*89c4ff92SAndroid Build Coastguard Worker         return *this;
620*89c4ff92SAndroid Build Coastguard Worker     }
621*89c4ff92SAndroid Build Coastguard Worker 
622*89c4ff92SAndroid Build Coastguard Worker     // conversions
623*89c4ff92SAndroid Build Coastguard Worker     // move-assign
624*89c4ff92SAndroid Build Coastguard Worker     template <typename T, typename Traits = detail::value_traits<T, Types...>,
625*89c4ff92SAndroid Build Coastguard Worker               typename Enable = typename std::enable_if<Traits::is_valid && !std::is_same<variant<Types...>, typename Traits::value_type>::value>::type >
operator =(T && rhs)626*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE variant<Types...>& operator=(T&& rhs)
627*89c4ff92SAndroid Build Coastguard Worker         // not that we check is_nothrow_constructible<T>, not is_nothrow_move_assignable<T>,
628*89c4ff92SAndroid Build Coastguard Worker         // since we construct a temporary
629*89c4ff92SAndroid Build Coastguard Worker         noexcept(std::is_nothrow_constructible<typename Traits::target_type, T&&>::value
630*89c4ff92SAndroid Build Coastguard Worker                  && std::is_nothrow_move_assignable<variant<Types...>>::value)
631*89c4ff92SAndroid Build Coastguard Worker     {
632*89c4ff92SAndroid Build Coastguard Worker         variant<Types...> temp(std::forward<T>(rhs));
633*89c4ff92SAndroid Build Coastguard Worker         move_assign(std::move(temp));
634*89c4ff92SAndroid Build Coastguard Worker         return *this;
635*89c4ff92SAndroid Build Coastguard Worker     }
636*89c4ff92SAndroid Build Coastguard Worker 
637*89c4ff92SAndroid Build Coastguard Worker     // copy-assign
638*89c4ff92SAndroid Build Coastguard Worker     template <typename T>
operator =(T const & rhs)639*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE variant<Types...>& operator=(T const& rhs)
640*89c4ff92SAndroid Build Coastguard Worker     {
641*89c4ff92SAndroid Build Coastguard Worker         variant<Types...> temp(rhs);
642*89c4ff92SAndroid Build Coastguard Worker         copy_assign(temp);
643*89c4ff92SAndroid Build Coastguard Worker         return *this;
644*89c4ff92SAndroid Build Coastguard Worker     }
645*89c4ff92SAndroid Build Coastguard Worker 
646*89c4ff92SAndroid Build Coastguard Worker     template <typename T, typename std::enable_if<
647*89c4ff92SAndroid Build Coastguard Worker                           (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
is() const648*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE bool is() const
649*89c4ff92SAndroid Build Coastguard Worker     {
650*89c4ff92SAndroid Build Coastguard Worker         return type_index == detail::direct_type<T, Types...>::index;
651*89c4ff92SAndroid Build Coastguard Worker     }
652*89c4ff92SAndroid Build Coastguard Worker 
653*89c4ff92SAndroid Build Coastguard Worker     template <typename T,typename std::enable_if<
654*89c4ff92SAndroid Build Coastguard Worker                          (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
is() const655*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE bool is() const
656*89c4ff92SAndroid Build Coastguard Worker     {
657*89c4ff92SAndroid Build Coastguard Worker         return type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index;
658*89c4ff92SAndroid Build Coastguard Worker     }
659*89c4ff92SAndroid Build Coastguard Worker 
valid() const660*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE bool valid() const
661*89c4ff92SAndroid Build Coastguard Worker     {
662*89c4ff92SAndroid Build Coastguard Worker         return type_index != detail::invalid_value;
663*89c4ff92SAndroid Build Coastguard Worker     }
664*89c4ff92SAndroid Build Coastguard Worker 
665*89c4ff92SAndroid Build Coastguard Worker     template <typename T, typename... Args>
set(Args &&...args)666*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE void set(Args&&... args)
667*89c4ff92SAndroid Build Coastguard Worker     {
668*89c4ff92SAndroid Build Coastguard Worker         helper_type::destroy(type_index, &data);
669*89c4ff92SAndroid Build Coastguard Worker         type_index = detail::invalid_value;
670*89c4ff92SAndroid Build Coastguard Worker         new (&data) T(std::forward<Args>(args)...);
671*89c4ff92SAndroid Build Coastguard Worker         type_index = detail::direct_type<T, Types...>::index;
672*89c4ff92SAndroid Build Coastguard Worker     }
673*89c4ff92SAndroid Build Coastguard Worker 
674*89c4ff92SAndroid Build Coastguard Worker     // get_unchecked<T>()
675*89c4ff92SAndroid Build Coastguard Worker     template <typename T, typename std::enable_if<
676*89c4ff92SAndroid Build Coastguard Worker                           (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
get_unchecked()677*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE T& get_unchecked()
678*89c4ff92SAndroid Build Coastguard Worker     {
679*89c4ff92SAndroid Build Coastguard Worker         return *reinterpret_cast<T*>(&data);
680*89c4ff92SAndroid Build Coastguard Worker     }
681*89c4ff92SAndroid Build Coastguard Worker 
682*89c4ff92SAndroid Build Coastguard Worker #ifdef HAS_EXCEPTIONS
683*89c4ff92SAndroid Build Coastguard Worker     // get<T>()
684*89c4ff92SAndroid Build Coastguard Worker     template <typename T, typename std::enable_if<
685*89c4ff92SAndroid Build Coastguard Worker                           (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
get()686*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE T& get()
687*89c4ff92SAndroid Build Coastguard Worker     {
688*89c4ff92SAndroid Build Coastguard Worker         if (type_index == detail::direct_type<T, Types...>::index)
689*89c4ff92SAndroid Build Coastguard Worker         {
690*89c4ff92SAndroid Build Coastguard Worker             return *reinterpret_cast<T*>(&data);
691*89c4ff92SAndroid Build Coastguard Worker         }
692*89c4ff92SAndroid Build Coastguard Worker         else
693*89c4ff92SAndroid Build Coastguard Worker         {
694*89c4ff92SAndroid Build Coastguard Worker             throw bad_variant_access("in get<T>()");
695*89c4ff92SAndroid Build Coastguard Worker         }
696*89c4ff92SAndroid Build Coastguard Worker     }
697*89c4ff92SAndroid Build Coastguard Worker #endif
698*89c4ff92SAndroid Build Coastguard Worker 
699*89c4ff92SAndroid Build Coastguard Worker     template <typename T, typename std::enable_if<
700*89c4ff92SAndroid Build Coastguard Worker                           (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
get_unchecked() const701*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE T const& get_unchecked() const
702*89c4ff92SAndroid Build Coastguard Worker     {
703*89c4ff92SAndroid Build Coastguard Worker         return *reinterpret_cast<T const*>(&data);
704*89c4ff92SAndroid Build Coastguard Worker     }
705*89c4ff92SAndroid Build Coastguard Worker 
706*89c4ff92SAndroid Build Coastguard Worker #ifdef HAS_EXCEPTIONS
707*89c4ff92SAndroid Build Coastguard Worker     template <typename T, typename std::enable_if<
708*89c4ff92SAndroid Build Coastguard Worker                           (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
get() const709*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE T const& get() const
710*89c4ff92SAndroid Build Coastguard Worker     {
711*89c4ff92SAndroid Build Coastguard Worker         if (type_index == detail::direct_type<T, Types...>::index)
712*89c4ff92SAndroid Build Coastguard Worker         {
713*89c4ff92SAndroid Build Coastguard Worker             return *reinterpret_cast<T const*>(&data);
714*89c4ff92SAndroid Build Coastguard Worker         }
715*89c4ff92SAndroid Build Coastguard Worker         else
716*89c4ff92SAndroid Build Coastguard Worker         {
717*89c4ff92SAndroid Build Coastguard Worker             throw bad_variant_access("in get<T>()");
718*89c4ff92SAndroid Build Coastguard Worker         }
719*89c4ff92SAndroid Build Coastguard Worker     }
720*89c4ff92SAndroid Build Coastguard Worker #endif
721*89c4ff92SAndroid Build Coastguard Worker 
722*89c4ff92SAndroid Build Coastguard Worker     // get_unchecked<T>() - T stored as recursive_wrapper<T>
723*89c4ff92SAndroid Build Coastguard Worker     template <typename T, typename std::enable_if<
724*89c4ff92SAndroid Build Coastguard Worker                           (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
get_unchecked()725*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE T& get_unchecked()
726*89c4ff92SAndroid Build Coastguard Worker     {
727*89c4ff92SAndroid Build Coastguard Worker         return (*reinterpret_cast<recursive_wrapper<T>*>(&data)).get();
728*89c4ff92SAndroid Build Coastguard Worker     }
729*89c4ff92SAndroid Build Coastguard Worker 
730*89c4ff92SAndroid Build Coastguard Worker #ifdef HAS_EXCEPTIONS
731*89c4ff92SAndroid Build Coastguard Worker     // get<T>() - T stored as recursive_wrapper<T>
732*89c4ff92SAndroid Build Coastguard Worker     template <typename T, typename std::enable_if<
733*89c4ff92SAndroid Build Coastguard Worker                           (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
get()734*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE T& get()
735*89c4ff92SAndroid Build Coastguard Worker     {
736*89c4ff92SAndroid Build Coastguard Worker         if (type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index)
737*89c4ff92SAndroid Build Coastguard Worker         {
738*89c4ff92SAndroid Build Coastguard Worker             return (*reinterpret_cast<recursive_wrapper<T>*>(&data)).get();
739*89c4ff92SAndroid Build Coastguard Worker         }
740*89c4ff92SAndroid Build Coastguard Worker         else
741*89c4ff92SAndroid Build Coastguard Worker         {
742*89c4ff92SAndroid Build Coastguard Worker             throw bad_variant_access("in get<T>()");
743*89c4ff92SAndroid Build Coastguard Worker         }
744*89c4ff92SAndroid Build Coastguard Worker     }
745*89c4ff92SAndroid Build Coastguard Worker #endif
746*89c4ff92SAndroid Build Coastguard Worker 
747*89c4ff92SAndroid Build Coastguard Worker     template <typename T, typename std::enable_if<
748*89c4ff92SAndroid Build Coastguard Worker                           (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
get_unchecked() const749*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE T const& get_unchecked() const
750*89c4ff92SAndroid Build Coastguard Worker     {
751*89c4ff92SAndroid Build Coastguard Worker         return (*reinterpret_cast<recursive_wrapper<T> const*>(&data)).get();
752*89c4ff92SAndroid Build Coastguard Worker     }
753*89c4ff92SAndroid Build Coastguard Worker 
754*89c4ff92SAndroid Build Coastguard Worker #ifdef HAS_EXCEPTIONS
755*89c4ff92SAndroid Build Coastguard Worker     template <typename T, typename std::enable_if<
756*89c4ff92SAndroid Build Coastguard Worker                           (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
get() const757*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE T const& get() const
758*89c4ff92SAndroid Build Coastguard Worker     {
759*89c4ff92SAndroid Build Coastguard Worker         if (type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index)
760*89c4ff92SAndroid Build Coastguard Worker         {
761*89c4ff92SAndroid Build Coastguard Worker             return (*reinterpret_cast<recursive_wrapper<T> const*>(&data)).get();
762*89c4ff92SAndroid Build Coastguard Worker         }
763*89c4ff92SAndroid Build Coastguard Worker         else
764*89c4ff92SAndroid Build Coastguard Worker         {
765*89c4ff92SAndroid Build Coastguard Worker             throw bad_variant_access("in get<T>()");
766*89c4ff92SAndroid Build Coastguard Worker         }
767*89c4ff92SAndroid Build Coastguard Worker     }
768*89c4ff92SAndroid Build Coastguard Worker #endif
769*89c4ff92SAndroid Build Coastguard Worker 
770*89c4ff92SAndroid Build Coastguard Worker     // get_unchecked<T>() - T stored as std::reference_wrapper<T>
771*89c4ff92SAndroid Build Coastguard Worker     template <typename T, typename std::enable_if<
772*89c4ff92SAndroid Build Coastguard Worker                           (detail::direct_type<std::reference_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
get_unchecked()773*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE T& get_unchecked()
774*89c4ff92SAndroid Build Coastguard Worker     {
775*89c4ff92SAndroid Build Coastguard Worker         return (*reinterpret_cast<std::reference_wrapper<T>*>(&data)).get();
776*89c4ff92SAndroid Build Coastguard Worker     }
777*89c4ff92SAndroid Build Coastguard Worker 
778*89c4ff92SAndroid Build Coastguard Worker #ifdef HAS_EXCEPTIONS
779*89c4ff92SAndroid Build Coastguard Worker     // get<T>() - T stored as std::reference_wrapper<T>
780*89c4ff92SAndroid Build Coastguard Worker     template <typename T, typename std::enable_if<
781*89c4ff92SAndroid Build Coastguard Worker                           (detail::direct_type<std::reference_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
get()782*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE T& get()
783*89c4ff92SAndroid Build Coastguard Worker     {
784*89c4ff92SAndroid Build Coastguard Worker         if (type_index == detail::direct_type<std::reference_wrapper<T>, Types...>::index)
785*89c4ff92SAndroid Build Coastguard Worker         {
786*89c4ff92SAndroid Build Coastguard Worker             return (*reinterpret_cast<std::reference_wrapper<T>*>(&data)).get();
787*89c4ff92SAndroid Build Coastguard Worker         }
788*89c4ff92SAndroid Build Coastguard Worker         else
789*89c4ff92SAndroid Build Coastguard Worker         {
790*89c4ff92SAndroid Build Coastguard Worker             throw bad_variant_access("in get<T>()");
791*89c4ff92SAndroid Build Coastguard Worker         }
792*89c4ff92SAndroid Build Coastguard Worker     }
793*89c4ff92SAndroid Build Coastguard Worker #endif
794*89c4ff92SAndroid Build Coastguard Worker 
795*89c4ff92SAndroid Build Coastguard Worker     template <typename T, typename std::enable_if<
796*89c4ff92SAndroid Build Coastguard Worker                           (detail::direct_type<std::reference_wrapper<T const>, Types...>::index != detail::invalid_value)>::type* = nullptr>
get_unchecked() const797*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE T const& get_unchecked() const
798*89c4ff92SAndroid Build Coastguard Worker     {
799*89c4ff92SAndroid Build Coastguard Worker         return (*reinterpret_cast<std::reference_wrapper<T const> const*>(&data)).get();
800*89c4ff92SAndroid Build Coastguard Worker     }
801*89c4ff92SAndroid Build Coastguard Worker 
802*89c4ff92SAndroid Build Coastguard Worker #ifdef HAS_EXCEPTIONS
803*89c4ff92SAndroid Build Coastguard Worker     template <typename T, typename std::enable_if<
804*89c4ff92SAndroid Build Coastguard Worker                           (detail::direct_type<std::reference_wrapper<T const>, Types...>::index != detail::invalid_value)>::type* = nullptr>
get() const805*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE T const& get() const
806*89c4ff92SAndroid Build Coastguard Worker     {
807*89c4ff92SAndroid Build Coastguard Worker         if (type_index == detail::direct_type<std::reference_wrapper<T const>, Types...>::index)
808*89c4ff92SAndroid Build Coastguard Worker         {
809*89c4ff92SAndroid Build Coastguard Worker             return (*reinterpret_cast<std::reference_wrapper<T const> const*>(&data)).get();
810*89c4ff92SAndroid Build Coastguard Worker         }
811*89c4ff92SAndroid Build Coastguard Worker         else
812*89c4ff92SAndroid Build Coastguard Worker         {
813*89c4ff92SAndroid Build Coastguard Worker             throw bad_variant_access("in get<T>()");
814*89c4ff92SAndroid Build Coastguard Worker         }
815*89c4ff92SAndroid Build Coastguard Worker     }
816*89c4ff92SAndroid Build Coastguard Worker #endif
817*89c4ff92SAndroid Build Coastguard Worker 
818*89c4ff92SAndroid Build Coastguard Worker     // This function is deprecated because it returns an internal index field.
819*89c4ff92SAndroid Build Coastguard Worker     // Use which() instead.
get_type_index() const820*89c4ff92SAndroid Build Coastguard Worker     MAPBOX_VARIANT_DEPRECATED VARIANT_INLINE type_index_t get_type_index() const
821*89c4ff92SAndroid Build Coastguard Worker     {
822*89c4ff92SAndroid Build Coastguard Worker         return type_index;
823*89c4ff92SAndroid Build Coastguard Worker     }
824*89c4ff92SAndroid Build Coastguard Worker 
which() const825*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE int which() const noexcept
826*89c4ff92SAndroid Build Coastguard Worker     {
827*89c4ff92SAndroid Build Coastguard Worker         return static_cast<int>(sizeof...(Types) - type_index - 1);
828*89c4ff92SAndroid Build Coastguard Worker     }
829*89c4ff92SAndroid Build Coastguard Worker 
830*89c4ff92SAndroid Build Coastguard Worker     template <typename T, typename std::enable_if<
831*89c4ff92SAndroid Build Coastguard Worker                           (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
which()832*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE static constexpr int which() noexcept
833*89c4ff92SAndroid Build Coastguard Worker     {
834*89c4ff92SAndroid Build Coastguard Worker         return static_cast<int>(sizeof...(Types)-detail::direct_type<T, Types...>::index - 1);
835*89c4ff92SAndroid Build Coastguard Worker     }
836*89c4ff92SAndroid Build Coastguard Worker 
837*89c4ff92SAndroid Build Coastguard Worker     // visitor
838*89c4ff92SAndroid Build Coastguard Worker     // unary
839*89c4ff92SAndroid Build Coastguard Worker     template <typename F, typename V, typename T0 = alternative_ref<V>,
840*89c4ff92SAndroid Build Coastguard Worker               typename R = detail::result_of_unary_visit<F, T0>>
visit(V && v,F && f)841*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE static R visit(V&& v, F&& f)
842*89c4ff92SAndroid Build Coastguard Worker     {
843*89c4ff92SAndroid Build Coastguard Worker         return detail::dispatcher<R, Types...>::apply(std::forward<V>(v), std::forward<F>(f));
844*89c4ff92SAndroid Build Coastguard Worker     }
845*89c4ff92SAndroid Build Coastguard Worker 
846*89c4ff92SAndroid Build Coastguard Worker     // binary
847*89c4ff92SAndroid Build Coastguard Worker     template <typename F, typename V, typename T0 = alternative_ref<V>,
848*89c4ff92SAndroid Build Coastguard Worker               typename R = detail::result_of_binary_visit<F, T0>>
binary_visit(V && v0,V && v1,F && f)849*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE static R binary_visit(V&& v0, V&& v1, F&& f)
850*89c4ff92SAndroid Build Coastguard Worker     {
851*89c4ff92SAndroid Build Coastguard Worker         return detail::binary_dispatcher<R, Types...>::apply(std::forward<V>(v0),
852*89c4ff92SAndroid Build Coastguard Worker                                                              std::forward<V>(v1),
853*89c4ff92SAndroid Build Coastguard Worker                                                              std::forward<F>(f));
854*89c4ff92SAndroid Build Coastguard Worker     }
855*89c4ff92SAndroid Build Coastguard Worker 
856*89c4ff92SAndroid Build Coastguard Worker     // match
857*89c4ff92SAndroid Build Coastguard Worker     // unary
858*89c4ff92SAndroid Build Coastguard Worker     template <typename... Fs>
match(Fs &&...fs) const859*89c4ff92SAndroid Build Coastguard Worker     auto VARIANT_INLINE match(Fs&&... fs) const&
860*89c4ff92SAndroid Build Coastguard Worker         -> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)))
861*89c4ff92SAndroid Build Coastguard Worker     {
862*89c4ff92SAndroid Build Coastguard Worker         return variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...));
863*89c4ff92SAndroid Build Coastguard Worker     }
864*89c4ff92SAndroid Build Coastguard Worker     // non-const
865*89c4ff92SAndroid Build Coastguard Worker     template <typename... Fs>
match(Fs &&...fs)866*89c4ff92SAndroid Build Coastguard Worker     auto VARIANT_INLINE match(Fs&&... fs) &
867*89c4ff92SAndroid Build Coastguard Worker         -> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)))
868*89c4ff92SAndroid Build Coastguard Worker     {
869*89c4ff92SAndroid Build Coastguard Worker         return variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...));
870*89c4ff92SAndroid Build Coastguard Worker     }
871*89c4ff92SAndroid Build Coastguard Worker     template <typename... Fs>
match(Fs &&...fs)872*89c4ff92SAndroid Build Coastguard Worker     auto VARIANT_INLINE match(Fs&&... fs) &&
873*89c4ff92SAndroid Build Coastguard Worker         -> decltype(variant::visit(std::move(*this), ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)))
874*89c4ff92SAndroid Build Coastguard Worker     {
875*89c4ff92SAndroid Build Coastguard Worker         return variant::visit(std::move(*this), ::mapbox::util::make_visitor(std::forward<Fs>(fs)...));
876*89c4ff92SAndroid Build Coastguard Worker     }
877*89c4ff92SAndroid Build Coastguard Worker 
~variant()878*89c4ff92SAndroid Build Coastguard Worker     ~variant() noexcept // no-throw destructor
879*89c4ff92SAndroid Build Coastguard Worker     {
880*89c4ff92SAndroid Build Coastguard Worker         helper_type::destroy(type_index, &data);
881*89c4ff92SAndroid Build Coastguard Worker     }
882*89c4ff92SAndroid Build Coastguard Worker 
883*89c4ff92SAndroid Build Coastguard Worker     // comparison operators
884*89c4ff92SAndroid Build Coastguard Worker     // equality
operator ==(variant const & rhs) const885*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE bool operator==(variant const& rhs) const
886*89c4ff92SAndroid Build Coastguard Worker     {
887*89c4ff92SAndroid Build Coastguard Worker         assert(valid() && rhs.valid());
888*89c4ff92SAndroid Build Coastguard Worker         if (this->which() != rhs.which())
889*89c4ff92SAndroid Build Coastguard Worker         {
890*89c4ff92SAndroid Build Coastguard Worker             return false;
891*89c4ff92SAndroid Build Coastguard Worker         }
892*89c4ff92SAndroid Build Coastguard Worker         detail::comparer<variant, detail::equal_comp> visitor(*this);
893*89c4ff92SAndroid Build Coastguard Worker         return visit(rhs, visitor);
894*89c4ff92SAndroid Build Coastguard Worker     }
895*89c4ff92SAndroid Build Coastguard Worker 
operator !=(variant const & rhs) const896*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE bool operator!=(variant const& rhs) const
897*89c4ff92SAndroid Build Coastguard Worker     {
898*89c4ff92SAndroid Build Coastguard Worker         return !(*this == rhs);
899*89c4ff92SAndroid Build Coastguard Worker     }
900*89c4ff92SAndroid Build Coastguard Worker 
901*89c4ff92SAndroid Build Coastguard Worker     // less than
operator <(variant const & rhs) const902*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE bool operator<(variant const& rhs) const
903*89c4ff92SAndroid Build Coastguard Worker     {
904*89c4ff92SAndroid Build Coastguard Worker         assert(valid() && rhs.valid());
905*89c4ff92SAndroid Build Coastguard Worker         if (this->which() != rhs.which())
906*89c4ff92SAndroid Build Coastguard Worker         {
907*89c4ff92SAndroid Build Coastguard Worker             return this->which() < rhs.which();
908*89c4ff92SAndroid Build Coastguard Worker         }
909*89c4ff92SAndroid Build Coastguard Worker         detail::comparer<variant, detail::less_comp> visitor(*this);
910*89c4ff92SAndroid Build Coastguard Worker         return visit(rhs, visitor);
911*89c4ff92SAndroid Build Coastguard Worker     }
operator >(variant const & rhs) const912*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE bool operator>(variant const& rhs) const
913*89c4ff92SAndroid Build Coastguard Worker     {
914*89c4ff92SAndroid Build Coastguard Worker         return rhs < *this;
915*89c4ff92SAndroid Build Coastguard Worker     }
operator <=(variant const & rhs) const916*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE bool operator<=(variant const& rhs) const
917*89c4ff92SAndroid Build Coastguard Worker     {
918*89c4ff92SAndroid Build Coastguard Worker         return !(*this > rhs);
919*89c4ff92SAndroid Build Coastguard Worker     }
operator >=(variant const & rhs) const920*89c4ff92SAndroid Build Coastguard Worker     VARIANT_INLINE bool operator>=(variant const& rhs) const
921*89c4ff92SAndroid Build Coastguard Worker     {
922*89c4ff92SAndroid Build Coastguard Worker         return !(*this < rhs);
923*89c4ff92SAndroid Build Coastguard Worker     }
924*89c4ff92SAndroid Build Coastguard Worker };
925*89c4ff92SAndroid Build Coastguard Worker 
926*89c4ff92SAndroid Build Coastguard Worker // unary visitor interface
927*89c4ff92SAndroid Build Coastguard Worker template <typename F, typename V>
apply_visitor(F && f,V && v)928*89c4ff92SAndroid Build Coastguard Worker auto VARIANT_INLINE apply_visitor(F&& f, V&& v)
929*89c4ff92SAndroid Build Coastguard Worker     -> decltype(v.visit(std::forward<V>(v), std::forward<F>(f)))
930*89c4ff92SAndroid Build Coastguard Worker {
931*89c4ff92SAndroid Build Coastguard Worker     return v.visit(std::forward<V>(v), std::forward<F>(f));
932*89c4ff92SAndroid Build Coastguard Worker }
933*89c4ff92SAndroid Build Coastguard Worker 
934*89c4ff92SAndroid Build Coastguard Worker // binary visitor interface
935*89c4ff92SAndroid Build Coastguard Worker template <typename F, typename V>
apply_visitor(F && f,V && v0,V && v1)936*89c4ff92SAndroid Build Coastguard Worker auto VARIANT_INLINE apply_visitor(F&& f, V&& v0, V&& v1)
937*89c4ff92SAndroid Build Coastguard Worker     -> decltype(v0.binary_visit(std::forward<V>(v0), std::forward<V>(v1), std::forward<F>(f)))
938*89c4ff92SAndroid Build Coastguard Worker {
939*89c4ff92SAndroid Build Coastguard Worker     return v0.binary_visit(std::forward<V>(v0), std::forward<V>(v1), std::forward<F>(f));
940*89c4ff92SAndroid Build Coastguard Worker }
941*89c4ff92SAndroid Build Coastguard Worker 
942*89c4ff92SAndroid Build Coastguard Worker // getter interface
943*89c4ff92SAndroid Build Coastguard Worker 
944*89c4ff92SAndroid Build Coastguard Worker #ifdef HAS_EXCEPTIONS
945*89c4ff92SAndroid Build Coastguard Worker template <typename ResultType, typename T>
get(T & var)946*89c4ff92SAndroid Build Coastguard Worker auto get(T& var)->decltype(var.template get<ResultType>())
947*89c4ff92SAndroid Build Coastguard Worker {
948*89c4ff92SAndroid Build Coastguard Worker     return var.template get<ResultType>();
949*89c4ff92SAndroid Build Coastguard Worker }
950*89c4ff92SAndroid Build Coastguard Worker #endif
951*89c4ff92SAndroid Build Coastguard Worker 
952*89c4ff92SAndroid Build Coastguard Worker template <typename ResultType, typename T>
get_unchecked(T & var)953*89c4ff92SAndroid Build Coastguard Worker ResultType& get_unchecked(T& var)
954*89c4ff92SAndroid Build Coastguard Worker {
955*89c4ff92SAndroid Build Coastguard Worker     return var.template get_unchecked<ResultType>();
956*89c4ff92SAndroid Build Coastguard Worker }
957*89c4ff92SAndroid Build Coastguard Worker 
958*89c4ff92SAndroid Build Coastguard Worker #ifdef HAS_EXCEPTIONS
959*89c4ff92SAndroid Build Coastguard Worker template <typename ResultType, typename T>
get(T const & var)960*89c4ff92SAndroid Build Coastguard Worker auto get(T const& var)->decltype(var.template get<ResultType>())
961*89c4ff92SAndroid Build Coastguard Worker {
962*89c4ff92SAndroid Build Coastguard Worker     return var.template get<ResultType>();
963*89c4ff92SAndroid Build Coastguard Worker }
964*89c4ff92SAndroid Build Coastguard Worker #endif
965*89c4ff92SAndroid Build Coastguard Worker 
966*89c4ff92SAndroid Build Coastguard Worker template <typename ResultType, typename T>
get_unchecked(T const & var)967*89c4ff92SAndroid Build Coastguard Worker ResultType const& get_unchecked(T const& var)
968*89c4ff92SAndroid Build Coastguard Worker {
969*89c4ff92SAndroid Build Coastguard Worker     return var.template get_unchecked<ResultType>();
970*89c4ff92SAndroid Build Coastguard Worker }
971*89c4ff92SAndroid Build Coastguard Worker // variant_size
972*89c4ff92SAndroid Build Coastguard Worker template <typename T>
973*89c4ff92SAndroid Build Coastguard Worker struct variant_size;
974*89c4ff92SAndroid Build Coastguard Worker 
975*89c4ff92SAndroid Build Coastguard Worker //variable templates is c++14
976*89c4ff92SAndroid Build Coastguard Worker //template <typename T>
977*89c4ff92SAndroid Build Coastguard Worker //constexpr std::size_t variant_size_v = variant_size<T>::value;
978*89c4ff92SAndroid Build Coastguard Worker 
979*89c4ff92SAndroid Build Coastguard Worker template <typename T>
980*89c4ff92SAndroid Build Coastguard Worker struct variant_size<const T>
981*89c4ff92SAndroid Build Coastguard Worker     : variant_size<T> {};
982*89c4ff92SAndroid Build Coastguard Worker 
983*89c4ff92SAndroid Build Coastguard Worker template <typename T>
984*89c4ff92SAndroid Build Coastguard Worker struct variant_size<volatile T>
985*89c4ff92SAndroid Build Coastguard Worker     : variant_size<T> {};
986*89c4ff92SAndroid Build Coastguard Worker 
987*89c4ff92SAndroid Build Coastguard Worker template <typename T>
988*89c4ff92SAndroid Build Coastguard Worker struct variant_size<const volatile T>
989*89c4ff92SAndroid Build Coastguard Worker     : variant_size<T> {};
990*89c4ff92SAndroid Build Coastguard Worker 
991*89c4ff92SAndroid Build Coastguard Worker template <typename... Types>
992*89c4ff92SAndroid Build Coastguard Worker struct variant_size<variant<Types...>>
993*89c4ff92SAndroid Build Coastguard Worker     : std::integral_constant<std::size_t, sizeof...(Types)> {};
994*89c4ff92SAndroid Build Coastguard Worker 
995*89c4ff92SAndroid Build Coastguard Worker // variant_alternative
996*89c4ff92SAndroid Build Coastguard Worker template <std::size_t Index, typename T>
997*89c4ff92SAndroid Build Coastguard Worker struct variant_alternative;
998*89c4ff92SAndroid Build Coastguard Worker 
999*89c4ff92SAndroid Build Coastguard Worker #if defined(__clang__)
1000*89c4ff92SAndroid Build Coastguard Worker #if __has_builtin(__type_pack_element)
1001*89c4ff92SAndroid Build Coastguard Worker #define has_type_pack_element
1002*89c4ff92SAndroid Build Coastguard Worker #endif
1003*89c4ff92SAndroid Build Coastguard Worker #endif
1004*89c4ff92SAndroid Build Coastguard Worker 
1005*89c4ff92SAndroid Build Coastguard Worker #if defined(has_type_pack_element)
1006*89c4ff92SAndroid Build Coastguard Worker template <std::size_t Index, typename ...Types>
1007*89c4ff92SAndroid Build Coastguard Worker struct variant_alternative<Index, variant<Types...>>
1008*89c4ff92SAndroid Build Coastguard Worker {
1009*89c4ff92SAndroid Build Coastguard Worker     static_assert(sizeof...(Types) > Index , "Index out of range");
1010*89c4ff92SAndroid Build Coastguard Worker     using type = __type_pack_element<Index, Types...>;
1011*89c4ff92SAndroid Build Coastguard Worker };
1012*89c4ff92SAndroid Build Coastguard Worker #else
1013*89c4ff92SAndroid Build Coastguard Worker template <std::size_t Index, typename First, typename...Types>
1014*89c4ff92SAndroid Build Coastguard Worker struct variant_alternative<Index, variant<First, Types...>>
1015*89c4ff92SAndroid Build Coastguard Worker     : variant_alternative<Index - 1, variant<Types...>>
1016*89c4ff92SAndroid Build Coastguard Worker {
1017*89c4ff92SAndroid Build Coastguard Worker     static_assert(sizeof...(Types) > Index -1 , "Index out of range");
1018*89c4ff92SAndroid Build Coastguard Worker };
1019*89c4ff92SAndroid Build Coastguard Worker 
1020*89c4ff92SAndroid Build Coastguard Worker template <typename First, typename...Types>
1021*89c4ff92SAndroid Build Coastguard Worker struct variant_alternative<0, variant<First, Types...>>
1022*89c4ff92SAndroid Build Coastguard Worker {
1023*89c4ff92SAndroid Build Coastguard Worker     using type = First;
1024*89c4ff92SAndroid Build Coastguard Worker };
1025*89c4ff92SAndroid Build Coastguard Worker 
1026*89c4ff92SAndroid Build Coastguard Worker #endif
1027*89c4ff92SAndroid Build Coastguard Worker 
1028*89c4ff92SAndroid Build Coastguard Worker template <size_t Index, typename T>
1029*89c4ff92SAndroid Build Coastguard Worker using variant_alternative_t = typename variant_alternative<Index, T>::type;
1030*89c4ff92SAndroid Build Coastguard Worker 
1031*89c4ff92SAndroid Build Coastguard Worker template <size_t Index, typename T>
1032*89c4ff92SAndroid Build Coastguard Worker struct variant_alternative<Index, const T>
1033*89c4ff92SAndroid Build Coastguard Worker     : std::add_const<variant_alternative<Index, T>> {};
1034*89c4ff92SAndroid Build Coastguard Worker 
1035*89c4ff92SAndroid Build Coastguard Worker template <size_t Index, typename T>
1036*89c4ff92SAndroid Build Coastguard Worker struct variant_alternative<Index, volatile T>
1037*89c4ff92SAndroid Build Coastguard Worker     : std::add_volatile<variant_alternative<Index, T>> {};
1038*89c4ff92SAndroid Build Coastguard Worker 
1039*89c4ff92SAndroid Build Coastguard Worker template <size_t Index, typename T>
1040*89c4ff92SAndroid Build Coastguard Worker struct variant_alternative<Index, const volatile T>
1041*89c4ff92SAndroid Build Coastguard Worker     : std::add_cv<variant_alternative<Index, T>> {};
1042*89c4ff92SAndroid Build Coastguard Worker 
1043*89c4ff92SAndroid Build Coastguard Worker } // namespace util
1044*89c4ff92SAndroid Build Coastguard Worker } // namespace mapbox
1045*89c4ff92SAndroid Build Coastguard Worker 
1046*89c4ff92SAndroid Build Coastguard Worker // hashable iff underlying types are hashable
1047*89c4ff92SAndroid Build Coastguard Worker namespace std {
1048*89c4ff92SAndroid Build Coastguard Worker template <typename... Types>
1049*89c4ff92SAndroid Build Coastguard Worker struct hash< ::mapbox::util::variant<Types...>> {
operator ()std::hash1050*89c4ff92SAndroid Build Coastguard Worker     std::size_t operator()(const ::mapbox::util::variant<Types...>& v) const noexcept
1051*89c4ff92SAndroid Build Coastguard Worker     {
1052*89c4ff92SAndroid Build Coastguard Worker         return ::mapbox::util::apply_visitor(::mapbox::util::detail::hasher{}, v);
1053*89c4ff92SAndroid Build Coastguard Worker     }
1054*89c4ff92SAndroid Build Coastguard Worker };
1055*89c4ff92SAndroid Build Coastguard Worker 
1056*89c4ff92SAndroid Build Coastguard Worker }
1057*89c4ff92SAndroid Build Coastguard Worker 
1058*89c4ff92SAndroid Build Coastguard Worker #endif // MAPBOX_UTIL_VARIANT_HPP
1059