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