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

source code of qtlocation/src/3rdparty/mapbox-gl-native/deps/variant/1.1.4/include/mapbox/variant.hpp