1 // MPark.Variant
2 //
3 // Copyright Michael Park, 2015-2017
4 //
5 // Distributed under the Boost Software License, Version 1.0.
6 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
7 
8 // We cannot keep the header guard from mpark variant because
9 // this can conflict with other libraries that depend on or embed
10 // mpark variant.
11 #ifndef XTL_MPARK_VARIANT_HPP
12 #define XTL_MPARK_VARIANT_HPP
13 
14 /*
15    variant synopsis
16 
17 namespace std {
18 
19   // 20.7.2, class template variant
20   template <class... Types>
21   class variant {
22   public:
23 
24     // 20.7.2.1, constructors
25     constexpr variant() noexcept(see below);
26     variant(const variant&);
27     variant(variant&&) noexcept(see below);
28 
29     template <class T> constexpr variant(T&&) noexcept(see below);
30 
31     template <class T, class... Args>
32     constexpr explicit variant(in_place_type_t<T>, Args&&...);
33 
34     template <class T, class U, class... Args>
35     constexpr explicit variant(
36         in_place_type_t<T>, initializer_list<U>, Args&&...);
37 
38     template <size_t I, class... Args>
39     constexpr explicit variant(in_place_index_t<I>, Args&&...);
40 
41     template <size_t I, class U, class... Args>
42     constexpr explicit variant(
43         in_place_index_t<I>, initializer_list<U>, Args&&...);
44 
45     // 20.7.2.2, destructor
46     ~variant();
47 
48     // 20.7.2.3, assignment
49     variant& operator=(const variant&);
50     variant& operator=(variant&&) noexcept(see below);
51 
52     template <class T> variant& operator=(T&&) noexcept(see below);
53 
54     // 20.7.2.4, modifiers
55     template <class T, class... Args>
56     T& emplace(Args&&...);
57 
58     template <class T, class U, class... Args>
59     T& emplace(initializer_list<U>, Args&&...);
60 
61     template <size_t I, class... Args>
62     variant_alternative<I, variant>& emplace(Args&&...);
63 
64     template <size_t I, class U, class...  Args>
65     variant_alternative<I, variant>& emplace(initializer_list<U>, Args&&...);
66 
67     // 20.7.2.5, value status
68     constexpr bool valueless_by_exception() const noexcept;
69     constexpr size_t index() const noexcept;
70 
71     // 20.7.2.6, swap
72     void swap(variant&) noexcept(see below);
73   };
74 
75   // 20.7.3, variant helper classes
76   template <class T> struct variant_size; // undefined
77 
78   template <class T>
79   constexpr size_t variant_size_v = variant_size<T>::value;
80 
81   template <class T> struct variant_size<const T>;
82   template <class T> struct variant_size<volatile T>;
83   template <class T> struct variant_size<const volatile T>;
84 
85   template <class... Types>
86   struct variant_size<variant<Types...>>;
87 
88   template <size_t I, class T> struct variant_alternative; // undefined
89 
90   template <size_t I, class T>
91   using variant_alternative_t = typename variant_alternative<I, T>::type;
92 
93   template <size_t I, class T> struct variant_alternative<I, const T>;
94   template <size_t I, class T> struct variant_alternative<I, volatile T>;
95   template <size_t I, class T> struct variant_alternative<I, const volatile T>;
96 
97   template <size_t I, class... Types>
98   struct variant_alternative<I, variant<Types...>>;
99 
100   constexpr size_t variant_npos = -1;
101 
102   // 20.7.4, value access
103   template <class T, class... Types>
104   constexpr bool holds_alternative(const variant<Types...>&) noexcept;
105 
106   template <size_t I, class... Types>
107   constexpr variant_alternative_t<I, variant<Types...>>&
108   get(variant<Types...>&);
109 
110   template <size_t I, class... Types>
111   constexpr variant_alternative_t<I, variant<Types...>>&&
112   get(variant<Types...>&&);
113 
114   template <size_t I, class... Types>
115   constexpr variant_alternative_t<I, variant<Types...>> const&
116   get(const variant<Types...>&);
117 
118   template <size_t I, class... Types>
119   constexpr variant_alternative_t<I, variant<Types...>> const&&
120   get(const variant<Types...>&&);
121 
122   template <class T, class...  Types>
123   constexpr T& get(variant<Types...>&);
124 
125   template <class T, class... Types>
126   constexpr T&& get(variant<Types...>&&);
127 
128   template <class T, class... Types>
129   constexpr const T& get(const variant<Types...>&);
130 
131   template <class T, class... Types>
132   constexpr const T&& get(const variant<Types...>&&);
133 
134   template <size_t I, class... Types>
135   constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>>
136   get_if(variant<Types...>*) noexcept;
137 
138   template <size_t I, class... Types>
139   constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
140   get_if(const variant<Types...>*) noexcept;
141 
142   template <class T, class... Types>
143   constexpr add_pointer_t<T>
144   get_if(variant<Types...>*) noexcept;
145 
146   template <class T, class... Types>
147   constexpr add_pointer_t<const T>
148   get_if(const variant<Types...>*) noexcept;
149 
150   // 20.7.5, relational operators
151   template <class... Types>
152   constexpr bool operator==(const variant<Types...>&, const variant<Types...>&);
153 
154   template <class... Types>
155   constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&);
156 
157   template <class... Types>
158   constexpr bool operator<(const variant<Types...>&, const variant<Types...>&);
159 
160   template <class... Types>
161   constexpr bool operator>(const variant<Types...>&, const variant<Types...>&);
162 
163   template <class... Types>
164   constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&);
165 
166   template <class... Types>
167   constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&);
168 
169   // 20.7.6, visitation
170   template <class Visitor, class... Variants>
171   constexpr see below visit(Visitor&&, Variants&&...);
172 
173   // 20.7.7, class monostate
174   struct monostate;
175 
176   // 20.7.8, monostate relational operators
177   constexpr bool operator<(monostate, monostate) noexcept;
178   constexpr bool operator>(monostate, monostate) noexcept;
179   constexpr bool operator<=(monostate, monostate) noexcept;
180   constexpr bool operator>=(monostate, monostate) noexcept;
181   constexpr bool operator==(monostate, monostate) noexcept;
182   constexpr bool operator!=(monostate, monostate) noexcept;
183 
184   // 20.7.9, specialized algorithms
185   template <class... Types>
186   void swap(variant<Types...>&, variant<Types...>&) noexcept(see below);
187 
188   // 20.7.10, class bad_variant_access
189   class bad_variant_access;
190 
191   // 20.7.11, hash support
192   template <class T> struct hash;
193   template <class... Types> struct hash<variant<Types...>>;
194   template <> struct hash<monostate>;
195 
196 } // namespace std
197 
198 */
199 
200 #include <cstddef>
201 #include <exception>
202 #include <functional>
203 #include <initializer_list>
204 #include <new>
205 #include <type_traits>
206 #include <utility>
207 
208 // MPark.Variant
209 //
210 // Copyright Michael Park, 2015-2017
211 //
212 // Distributed under the Boost Software License, Version 1.0.
213 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
214 
215 #ifndef XTL_MPARK_CONFIG_HPP
216 #define XTL_MPARK_CONFIG_HPP
217 
218 // MSVC 2015 Update 3.
219 #if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_FULL_VER < 190024210)
220 #error "MPark.Variant requires C++11 support."
221 #endif
222 
223 #ifndef __has_attribute
224 #define __has_attribute(x) 0
225 #endif
226 
227 #ifndef __has_builtin
228 #define __has_builtin(x) 0
229 #endif
230 
231 #ifndef __has_include
232 #define __has_include(x) 0
233 #endif
234 
235 #ifndef __has_feature
236 #define __has_feature(x) 0
237 #endif
238 
239 #if __has_attribute(always_inline) || defined(__GNUC__)
240 #define MPARK_ALWAYS_INLINE __attribute__((__always_inline__)) inline
241 #elif defined(_MSC_VER)
242 #define MPARK_ALWAYS_INLINE __forceinline
243 #else
244 #define MPARK_ALWAYS_INLINE inline
245 #endif
246 
247 #if __has_builtin(__builtin_addressof) || \
248     (defined(__GNUC__) && __GNUC__ >= 7) || defined(_MSC_VER)
249 #define MPARK_BUILTIN_ADDRESSOF
250 #endif
251 
252 #if __has_builtin(__builtin_unreachable) || defined(__GNUC__)
253 #define MPARK_BUILTIN_UNREACHABLE __builtin_unreachable()
254 #elif defined(_MSC_VER)
255 #define MPARK_BUILTIN_UNREACHABLE __assume(false)
256 #else
257 #define MPARK_BUILTIN_UNREACHABLE
258 #endif
259 
260 #if __has_builtin(__type_pack_element)
261 #define MPARK_TYPE_PACK_ELEMENT
262 #endif
263 
264 #if defined(__cpp_constexpr) && __cpp_constexpr >= 200704 && \
265     !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 9)
266 #define MPARK_CPP11_CONSTEXPR
267 #endif
268 
269 #if defined(__cpp_constexpr) && __cpp_constexpr >= 201304
270 #define MPARK_CPP14_CONSTEXPR
271 #endif
272 
273 #if !defined(MPARK_NO_EXCEPTIONS) && \
274     (__has_feature(cxx_exceptions) || defined(__cpp_exceptions) || \
275     defined(__EXCEPTIONS) || (defined(_MSC_VER) && defined(_CPPUNWIND)))
276 // Exceptions are enabled.
277 #define MPARK_EXCEPTIONS
278 #endif
279 
280 #if defined(__cpp_generic_lambdas) || defined(_MSC_VER)
281 #define MPARK_GENERIC_LAMBDAS
282 #endif
283 
284 #if defined(__cpp_lib_integer_sequence)
285 #define MPARK_INTEGER_SEQUENCE
286 #endif
287 
288 #if defined(__cpp_return_type_deduction) || defined(_MSC_VER)
289 #define MPARK_RETURN_TYPE_DEDUCTION
290 #endif
291 
292 #if defined(__cpp_lib_transparent_operators) || defined(_MSC_VER)
293 #define MPARK_TRANSPARENT_OPERATORS
294 #endif
295 
296 #if defined(__cpp_variable_templates) || defined(_MSC_VER)
297 #define MPARK_VARIABLE_TEMPLATES
298 #endif
299 
300 #if !defined(__GLIBCXX__) || __has_include(<codecvt>)  // >= libstdc++-5
301 #define MPARK_TRIVIALITY_TYPE_TRAITS
302 #define MPARK_INCOMPLETE_TYPE_TRAITS
303 #endif
304 
305 #endif  // XTL_MPARK_CONFIG_HPP
306 
307 // MPark.Variant
308 //
309 // Copyright Michael Park, 2015-2017
310 //
311 // Distributed under the Boost Software License, Version 1.0.
312 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
313 
314 #ifndef XTL_MPARK_IN_PLACE_HPP
315 #define XTL_MPARK_IN_PLACE_HPP
316 
317 #include <cstddef>
318 
319 
320 namespace mpark {
321 
322   struct in_place_t { explicit in_place_t() = default; };
323 
324   template <std::size_t I>
325   struct in_place_index_t { explicit in_place_index_t() = default; };
326 
327   template <typename T>
328   struct in_place_type_t { explicit in_place_type_t() = default; };
329 
330 #ifdef MPARK_VARIABLE_TEMPLATES
331   constexpr in_place_t in_place{};
332 
333   template <std::size_t I> constexpr in_place_index_t<I> in_place_index{};
334 
335   template <typename T> constexpr in_place_type_t<T> in_place_type{};
336 #endif
337 
338 }  // namespace mpark
339 
340 #endif  // XTL_MPARK_IN_PLACE_HPP
341 
342 // MPark.Variant
343 //
344 // Copyright Michael Park, 2015-2017
345 //
346 // Distributed under the Boost Software License, Version 1.0.
347 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
348 
349 #ifndef XTL_MPARK_LIB_HPP
350 #define XTL_MPARK_LIB_HPP
351 
352 #include <memory>
353 #include <functional>
354 #include <type_traits>
355 #include <utility>
356 
357 
358 #define MPARK_RETURN(...) \
359   noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
360 
361 namespace mpark {
362   namespace lib {
363     template <typename T>
364     struct identity { using type = T; };
365 
366     inline namespace cpp14 {
367       template <typename T, std::size_t N>
368       struct array {
operator []mpark::lib::cpp14::array369         constexpr const T &operator[](std::size_t index) const {
370           return data[index];
371         }
372 
373         T data[N == 0 ? 1 : N];
374       };
375 
376       template <typename T>
377       using add_pointer_t = typename std::add_pointer<T>::type;
378 
379       template <typename... Ts>
380       using common_type_t = typename std::common_type<Ts...>::type;
381 
382       template <typename T>
383       using decay_t = typename std::decay<T>::type;
384 
385       template <bool B, typename T = void>
386       using enable_if_t = typename std::enable_if<B, T>::type;
387 
388       template <typename T>
389       using remove_const_t = typename std::remove_const<T>::type;
390 
391       template <typename T>
392       using remove_reference_t = typename std::remove_reference<T>::type;
393 
394       template <typename T>
forward(remove_reference_t<T> & t)395       inline constexpr T &&forward(remove_reference_t<T> &t) noexcept {
396         return static_cast<T &&>(t);
397       }
398 
399       template <typename T>
forward(remove_reference_t<T> && t)400       inline constexpr T &&forward(remove_reference_t<T> &&t) noexcept {
401         static_assert(!std::is_lvalue_reference<T>::value,
402                       "can not forward an rvalue as an lvalue");
403         return static_cast<T &&>(t);
404       }
405 
406       template <typename T>
move(T && t)407       inline constexpr remove_reference_t<T> &&move(T &&t) noexcept {
408         return static_cast<remove_reference_t<T> &&>(t);
409       }
410 
411 #ifdef MPARK_INTEGER_SEQUENCE
412       using std::integer_sequence;
413       using std::index_sequence;
414       using std::make_index_sequence;
415       using std::index_sequence_for;
416 #else
417       template <typename T, T... Is>
418       struct integer_sequence {
419         using value_type = T;
sizempark::lib::cpp14::integer_sequence420         static constexpr std::size_t size() noexcept { return sizeof...(Is); }
421       };
422 
423       template <std::size_t... Is>
424       using index_sequence = integer_sequence<std::size_t, Is...>;
425 
426       template <typename Lhs, typename Rhs>
427       struct make_index_sequence_concat;
428 
429       template <std::size_t... Lhs, std::size_t... Rhs>
430       struct make_index_sequence_concat<index_sequence<Lhs...>,
431                                         index_sequence<Rhs...>>
432           : identity<index_sequence<Lhs..., (sizeof...(Lhs) + Rhs)...>> {};
433 
434       template <std::size_t N>
435       struct make_index_sequence_impl;
436 
437       template <std::size_t N>
438       using make_index_sequence = typename make_index_sequence_impl<N>::type;
439 
440       template <std::size_t N>
441       struct make_index_sequence_impl
442           : make_index_sequence_concat<make_index_sequence<N / 2>,
443                                        make_index_sequence<N - (N / 2)>> {};
444 
445       template <>
446       struct make_index_sequence_impl<0> : identity<index_sequence<>> {};
447 
448       template <>
449       struct make_index_sequence_impl<1> : identity<index_sequence<0>> {};
450 
451       template <typename... Ts>
452       using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
453 #endif
454 
455       // <functional>
456 #ifdef MPARK_TRANSPARENT_OPERATORS
457       using equal_to = std::equal_to<>;
458 #else
459       struct equal_to {
460         template <typename Lhs, typename Rhs>
461         inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
462           MPARK_RETURN(lib::forward<Lhs>(lhs) == lib::forward<Rhs>(rhs))
463       };
464 #endif
465 
466 #ifdef MPARK_TRANSPARENT_OPERATORS
467       using not_equal_to = std::not_equal_to<>;
468 #else
469       struct not_equal_to {
470         template <typename Lhs, typename Rhs>
471         inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
472           MPARK_RETURN(lib::forward<Lhs>(lhs) != lib::forward<Rhs>(rhs))
473       };
474 #endif
475 
476 #ifdef MPARK_TRANSPARENT_OPERATORS
477       using less = std::less<>;
478 #else
479       struct less {
480         template <typename Lhs, typename Rhs>
481         inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
482           MPARK_RETURN(lib::forward<Lhs>(lhs) < lib::forward<Rhs>(rhs))
483       };
484 #endif
485 
486 #ifdef MPARK_TRANSPARENT_OPERATORS
487       using greater = std::greater<>;
488 #else
489       struct greater {
490         template <typename Lhs, typename Rhs>
491         inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
492           MPARK_RETURN(lib::forward<Lhs>(lhs) > lib::forward<Rhs>(rhs))
493       };
494 #endif
495 
496 #ifdef MPARK_TRANSPARENT_OPERATORS
497       using less_equal = std::less_equal<>;
498 #else
499       struct less_equal {
500         template <typename Lhs, typename Rhs>
501         inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
502           MPARK_RETURN(lib::forward<Lhs>(lhs) <= lib::forward<Rhs>(rhs))
503       };
504 #endif
505 
506 #ifdef MPARK_TRANSPARENT_OPERATORS
507       using greater_equal = std::greater_equal<>;
508 #else
509       struct greater_equal {
510         template <typename Lhs, typename Rhs>
511         inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
512           MPARK_RETURN(lib::forward<Lhs>(lhs) >= lib::forward<Rhs>(rhs))
513       };
514 #endif
515     }  // namespace cpp14
516 
517     inline namespace cpp17 {
518 
519       // <type_traits>
520       template <bool B>
521       using bool_constant = std::integral_constant<bool, B>;
522 
523       template <typename...>
524       struct voider : identity<void> {};
525 
526       template <typename... Ts>
527       using void_t = typename voider<Ts...>::type;
528 
529       namespace detail {
530         namespace swappable {
531 
532           using std::swap;
533 
534           template <typename T>
535           struct is_swappable {
536             private:
537             template <typename U,
538                       typename = decltype(swap(std::declval<U &>(),
539                                                std::declval<U &>()))>
540             inline static std::true_type test(int);
541 
542             template <typename U>
543             inline static std::false_type test(...);
544 
545             public:
546             static constexpr bool value = decltype(test<T>(0))::value;
547           };
548 
549           template <bool IsSwappable, typename T>
550           struct is_nothrow_swappable {
551             static constexpr bool value =
552                 noexcept(swap(std::declval<T &>(), std::declval<T &>()));
553           };
554 
555           template <typename T>
556           struct is_nothrow_swappable<false, T> : std::false_type {};
557 
558         }  // namespace swappable
559       }  // namespace detail
560 
561       using detail::swappable::is_swappable;
562 
563       template <typename T>
564       using is_nothrow_swappable =
565           detail::swappable::is_nothrow_swappable<is_swappable<T>::value, T>;
566 
567       // <functional>
568       namespace detail {
569 
570         template <typename T>
571         struct is_reference_wrapper : std::false_type {};
572 
573         template <typename T>
574         struct is_reference_wrapper<std::reference_wrapper<T>>
575             : std::true_type {};
576 
577         template <bool, int>
578         struct Invoke;
579 
580         template <>
581         struct Invoke<true /* pmf */, 0 /* is_base_of */> {
582           template <typename R, typename T, typename Arg, typename... Args>
583           inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
584             MPARK_RETURN((lib::forward<Arg>(arg).*pmf)(lib::forward<Args>(args)...))
585         };
586 
587         template <>
588         struct Invoke<true /* pmf */, 1 /* is_reference_wrapper */> {
589           template <typename R, typename T, typename Arg, typename... Args>
590           inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
591             MPARK_RETURN((lib::forward<Arg>(arg).get().*pmf)(lib::forward<Args>(args)...))
592         };
593 
594         template <>
595         struct Invoke<true /* pmf */, 2 /* otherwise */> {
596           template <typename R, typename T, typename Arg, typename... Args>
597           inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
598             MPARK_RETURN(((*lib::forward<Arg>(arg)).*pmf)(lib::forward<Args>(args)...))
599         };
600 
601         template <>
602         struct Invoke<false /* pmo */, 0 /* is_base_of */> {
603           template <typename R, typename T, typename Arg>
604           inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
605             MPARK_RETURN(lib::forward<Arg>(arg).*pmo)
606         };
607 
608         template <>
609         struct Invoke<false /* pmo */, 1 /* is_reference_wrapper */> {
610           template <typename R, typename T, typename Arg>
611           inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
612             MPARK_RETURN(lib::forward<Arg>(arg).get().*pmo)
613         };
614 
615         template <>
616         struct Invoke<false /* pmo */, 2 /* otherwise */> {
617           template <typename R, typename T, typename Arg>
618           inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
619               MPARK_RETURN((*lib::forward<Arg>(arg)).*pmo)
620         };
621 
622         template <typename R, typename T, typename Arg, typename... Args>
623         inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args)
624           MPARK_RETURN(
625               Invoke<std::is_function<R>::value,
626                      (std::is_base_of<T, lib::decay_t<Arg>>::value
627                           ? 0
628                           : is_reference_wrapper<lib::decay_t<Arg>>::value
629                                 ? 1
630                                 : 2)>::invoke(f,
631                                               lib::forward<Arg>(arg),
632                                               lib::forward<Args>(args)...))
633 
634 #ifdef _MSC_VER
635 #pragma warning(push)
636 #pragma warning(disable : 4100)
637 #endif
638         template <typename F, typename... Args>
639         inline constexpr auto invoke(F &&f, Args &&... args)
640           MPARK_RETURN(lib::forward<F>(f)(lib::forward<Args>(args)...))
641 #ifdef _MSC_VER
642 #pragma warning(pop)
643 #endif
644       }  // namespace detail
645 
646       template <typename F, typename... Args>
647       inline constexpr auto invoke(F &&f, Args &&... args)
648         MPARK_RETURN(detail::invoke(lib::forward<F>(f),
649                                     lib::forward<Args>(args)...))
650 
651       namespace detail {
652 
653         template <typename Void, typename, typename...>
654         struct invoke_result {};
655 
656         template <typename F, typename... Args>
657         struct invoke_result<void_t<decltype(lib::invoke(
658                                  std::declval<F>(), std::declval<Args>()...))>,
659                              F,
660                              Args...>
661             : identity<decltype(
662                   lib::invoke(std::declval<F>(), std::declval<Args>()...))> {};
663 
664       }  // namespace detail
665 
666       template <typename F, typename... Args>
667       using invoke_result = detail::invoke_result<void, F, Args...>;
668 
669       template <typename F, typename... Args>
670       using invoke_result_t = typename invoke_result<F, Args...>::type;
671 
672       namespace detail {
673 
674         template <typename Void, typename, typename...>
675         struct is_invocable : std::false_type {};
676 
677         template <typename F, typename... Args>
678         struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...>
679             : std::true_type {};
680 
681         template <typename Void, typename, typename, typename...>
682         struct is_invocable_r : std::false_type {};
683 
684         template <typename R, typename F, typename... Args>
685         struct is_invocable_r<void_t<invoke_result_t<F, Args...>>,
686                               R,
687                               F,
688                               Args...>
689             : std::is_convertible<invoke_result_t<F, Args...>, R> {};
690 
691       }  // namespace detail
692 
693       template <typename F, typename... Args>
694       using is_invocable = detail::is_invocable<void, F, Args...>;
695 
696       template <typename R, typename F, typename... Args>
697       using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>;
698 
699       namespace detail {
700 
701         template <bool Invocable, typename F, typename... Args>
702         struct is_nothrow_invocable {
703           static constexpr bool value =
704               noexcept(lib::invoke(std::declval<F>(), std::declval<Args>()...));
705         };
706 
707         template <typename F, typename... Args>
708         struct is_nothrow_invocable<false, F, Args...> : std::false_type {};
709 
710         template <bool Invocable, typename R, typename F, typename... Args>
711         struct is_nothrow_invocable_r {
712           private:
implmpark::lib::cpp17::detail::is_nothrow_invocable_r713           inline static R impl() {
714             return lib::invoke(std::declval<F>(), std::declval<Args>()...);
715           }
716 
717           public:
718           static constexpr bool value = noexcept(impl());
719         };
720 
721         template <typename R, typename F, typename... Args>
722         struct is_nothrow_invocable_r<false, R, F, Args...> : std::false_type {};
723 
724       }  // namespace detail
725 
726       template <typename F, typename... Args>
727       using is_nothrow_invocable = detail::
728           is_nothrow_invocable<is_invocable<F, Args...>::value, F, Args...>;
729 
730       template <typename R, typename F, typename... Args>
731       using is_nothrow_invocable_r =
732           detail::is_nothrow_invocable_r<is_invocable_r<R, F, Args...>::value,
733                                          R,
734                                          F,
735                                          Args...>;
736 
737       // <memory>
738 #ifdef MPARK_BUILTIN_ADDRESSOF
739       template <typename T>
addressof(T & arg)740       inline constexpr T *addressof(T &arg) noexcept {
741         return __builtin_addressof(arg);
742       }
743 #else
744       namespace detail {
745 
746         namespace has_addressof_impl {
747 
748           struct fail;
749 
750           template <typename T>
751           inline fail operator&(T &&);
752 
753           template <typename T>
impl()754           inline static constexpr bool impl() {
755             return (std::is_class<T>::value || std::is_union<T>::value) &&
756                    !std::is_same<decltype(&std::declval<T &>()), fail>::value;
757           }
758 
759         }  // namespace has_addressof_impl
760 
761         template <typename T>
762         using has_addressof = bool_constant<has_addressof_impl::impl<T>()>;
763 
764         template <typename T>
addressof(T & arg,std::true_type)765         inline constexpr T *addressof(T &arg, std::true_type) noexcept {
766           return std::addressof(arg);
767         }
768 
769         template <typename T>
addressof(T & arg,std::false_type)770         inline constexpr T *addressof(T &arg, std::false_type) noexcept {
771           return &arg;
772         }
773 
774       }  // namespace detail
775 
776       template <typename T>
addressof(T & arg)777       inline constexpr T *addressof(T &arg) noexcept {
778         return detail::addressof(arg, detail::has_addressof<T>{});
779       }
780 #endif
781 
782       template <typename T>
783       inline constexpr T *addressof(const T &&) = delete;
784 
785     }  // namespace cpp17
786 
787     template <typename T>
788     struct remove_all_extents : identity<T> {};
789 
790     template <typename T, std::size_t N>
791     struct remove_all_extents<array<T, N>> : remove_all_extents<T> {};
792 
793     template <typename T>
794     using remove_all_extents_t = typename remove_all_extents<T>::type;
795 
796     template <std::size_t N>
797     using size_constant = std::integral_constant<std::size_t, N>;
798 
799     template <std::size_t I, typename T>
800     struct indexed_type : size_constant<I> { using type = T; };
801 
802     template <bool... Bs>
803     using all = std::is_same<integer_sequence<bool, true, Bs...>,
804                              integer_sequence<bool, Bs..., true>>;
805 
806 #ifdef MPARK_TYPE_PACK_ELEMENT
807     template <std::size_t I, typename... Ts>
808     using type_pack_element_t = __type_pack_element<I, Ts...>;
809 #else
810     template <std::size_t I, typename... Ts>
811     struct type_pack_element_impl {
812       private:
813       template <typename>
814       struct set;
815 
816       template <std::size_t... Is>
817       struct set<index_sequence<Is...>> : indexed_type<Is, Ts>... {};
818 
819       template <typename T>
820       inline static std::enable_if<true, T> impl(indexed_type<I, T>);
821 
822       inline static std::enable_if<false> impl(...);
823 
824       public:
825       using type = decltype(impl(set<index_sequence_for<Ts...>>{}));
826     };
827 
828     template <std::size_t I, typename... Ts>
829     using type_pack_element = typename type_pack_element_impl<I, Ts...>::type;
830 
831     template <std::size_t I, typename... Ts>
832     using type_pack_element_t = typename type_pack_element<I, Ts...>::type;
833 #endif
834 
835 #ifdef MPARK_TRIVIALITY_TYPE_TRAITS
836     using std::is_trivially_copy_constructible;
837     using std::is_trivially_move_constructible;
838     using std::is_trivially_copy_assignable;
839     using std::is_trivially_move_assignable;
840 #else
841     template <typename T>
842     struct is_trivially_copy_constructible
843         : bool_constant<
844               std::is_copy_constructible<T>::value && __has_trivial_copy(T)> {};
845 
846     template <typename T>
847     struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {};
848 
849     template <typename T>
850     struct is_trivially_copy_assignable
851         : bool_constant<
852               std::is_copy_assignable<T>::value && __has_trivial_assign(T)> {};
853 
854     template <typename T>
855     struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {};
856 #endif
857 
858     template <typename T, bool>
859     struct dependent_type : T {};
860 
861     template <typename Is, std::size_t J>
862     struct push_back;
863 
864     template <typename Is, std::size_t J>
865     using push_back_t = typename push_back<Is, J>::type;
866 
867     template <std::size_t... Is, std::size_t J>
868     struct push_back<index_sequence<Is...>, J> {
869       using type = index_sequence<Is..., J>;
870     };
871 
872   }  // namespace lib
873 }  // namespace mpark
874 
875 #undef MPARK_RETURN
876 
877 #endif  // MPARK_LIB_HPP
878 
879 
880 namespace mpark {
881 
882 #ifdef MPARK_RETURN_TYPE_DEDUCTION
883 
884 #define AUTO auto
885 #define AUTO_RETURN(...) { return __VA_ARGS__; }
886 
887 #define AUTO_REFREF auto &&
888 #define AUTO_REFREF_RETURN(...) { return __VA_ARGS__; }
889 
890 #define DECLTYPE_AUTO decltype(auto)
891 #define DECLTYPE_AUTO_RETURN(...) { return __VA_ARGS__; }
892 
893 #else
894 
895 #define AUTO auto
896 #define AUTO_RETURN(...) \
897   -> lib::decay_t<decltype(__VA_ARGS__)> { return __VA_ARGS__; }
898 
899 #define AUTO_REFREF auto
900 #define AUTO_REFREF_RETURN(...)                                           \
901   -> decltype((__VA_ARGS__)) {                                            \
902     static_assert(std::is_reference<decltype((__VA_ARGS__))>::value, ""); \
903     return __VA_ARGS__;                                                   \
904   }
905 
906 #define DECLTYPE_AUTO auto
907 #define DECLTYPE_AUTO_RETURN(...) \
908   -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
909 
910 #endif
911 
912   class bad_variant_access : public std::exception {
913     public:
what() const914     virtual const char *what() const noexcept override { return "bad_variant_access"; }
915   };
916 
throw_bad_variant_access()917   [[noreturn]] inline void throw_bad_variant_access() {
918 #ifdef MPARK_EXCEPTIONS
919     throw bad_variant_access{};
920 #else
921     std::terminate();
922     MPARK_BUILTIN_UNREACHABLE;
923 #endif
924   }
925 
926   template <typename... Ts>
927   class variant;
928 
929   template <typename T>
930   struct variant_size;
931 
932 #ifdef MPARK_VARIABLE_TEMPLATES
933   template <typename T>
934   constexpr std::size_t variant_size_v = variant_size<T>::value;
935 #endif
936 
937   template <typename T>
938   struct variant_size<const T> : variant_size<T> {};
939 
940   template <typename T>
941   struct variant_size<volatile T> : variant_size<T> {};
942 
943   template <typename T>
944   struct variant_size<const volatile T> : variant_size<T> {};
945 
946   template <typename... Ts>
947   struct variant_size<variant<Ts...>> : lib::size_constant<sizeof...(Ts)> {};
948 
949   template <std::size_t I, typename T>
950   struct variant_alternative;
951 
952   template <std::size_t I, typename T>
953   using variant_alternative_t = typename variant_alternative<I, T>::type;
954 
955   template <std::size_t I, typename T>
956   struct variant_alternative<I, const T>
957       : std::add_const<variant_alternative_t<I, T>> {};
958 
959   template <std::size_t I, typename T>
960   struct variant_alternative<I, volatile T>
961       : std::add_volatile<variant_alternative_t<I, T>> {};
962 
963   template <std::size_t I, typename T>
964   struct variant_alternative<I, const volatile T>
965       : std::add_cv<variant_alternative_t<I, T>> {};
966 
967   template <std::size_t I, typename... Ts>
968   struct variant_alternative<I, variant<Ts...>> {
969     static_assert(I < sizeof...(Ts),
970                   "index out of bounds in `std::variant_alternative<>`");
971     using type = lib::type_pack_element_t<I, Ts...>;
972   };
973 
974   constexpr std::size_t variant_npos = static_cast<std::size_t>(-1);
975 
976   namespace detail {
977 
978     constexpr std::size_t not_found = static_cast<std::size_t>(-1);
979     constexpr std::size_t ambiguous = static_cast<std::size_t>(-2);
980 
981 #ifdef MPARK_CPP14_CONSTEXPR
982     template <typename T, typename... Ts>
find_index()983     inline constexpr std::size_t find_index() {
984       constexpr lib::array<bool, sizeof...(Ts)> matches = {
985           {std::is_same<T, Ts>::value...}
986       };
987       std::size_t result = not_found;
988       for (std::size_t i = 0; i < sizeof...(Ts); ++i) {
989         if (matches[i]) {
990           if (result != not_found) {
991             return ambiguous;
992           }
993           result = i;
994         }
995       }
996       return result;
997     }
998 #else
find_index_impl(std::size_t result,std::size_t)999     inline constexpr std::size_t find_index_impl(std::size_t result,
1000                                                  std::size_t) {
1001       return result;
1002     }
1003 
1004     template <typename... Bs>
find_index_impl(std::size_t result,std::size_t idx,bool b,Bs...bs)1005     inline constexpr std::size_t find_index_impl(std::size_t result,
1006                                                  std::size_t idx,
1007                                                  bool b,
1008                                                  Bs... bs) {
1009       return b ? (result != not_found ? ambiguous
1010                                       : find_index_impl(idx, idx + 1, bs...))
1011                : find_index_impl(result, idx + 1, bs...);
1012     }
1013 
1014     template <typename T, typename... Ts>
find_index()1015     inline constexpr std::size_t find_index() {
1016       return find_index_impl(not_found, 0, std::is_same<T, Ts>::value...);
1017     }
1018 #endif
1019 
1020     template <std::size_t I>
1021     using find_index_sfinae_impl =
1022         lib::enable_if_t<I != not_found && I != ambiguous,
1023                          lib::size_constant<I>>;
1024 
1025     template <typename T, typename... Ts>
1026     using find_index_sfinae = find_index_sfinae_impl<find_index<T, Ts...>()>;
1027 
1028     template <std::size_t I>
1029     struct find_index_checked_impl : lib::size_constant<I> {
1030       static_assert(I != not_found, "the specified type is not found.");
1031       static_assert(I != ambiguous, "the specified type is ambiguous.");
1032     };
1033 
1034     template <typename T, typename... Ts>
1035     using find_index_checked = find_index_checked_impl<find_index<T, Ts...>()>;
1036 
1037     struct valueless_t {};
1038 
1039     enum class Trait { TriviallyAvailable, Available, Unavailable };
1040 
1041     template <typename T,
1042               template <typename> class IsTriviallyAvailable,
1043               template <typename> class IsAvailable>
trait()1044     inline constexpr Trait trait() {
1045       return IsTriviallyAvailable<T>::value
1046                  ? Trait::TriviallyAvailable
1047                  : IsAvailable<T>::value ? Trait::Available
1048                                          : Trait::Unavailable;
1049     }
1050 
1051 #ifdef MPARK_CPP14_CONSTEXPR
1052     template <typename... Traits>
common_trait(Traits...traits_)1053     inline constexpr Trait common_trait(Traits... traits_) {
1054       Trait result = Trait::TriviallyAvailable;
1055       lib::array<Trait, sizeof...(Traits)> traits = {{traits_...}};
1056       for (std::size_t i = 0; i < sizeof...(Traits); ++i) {
1057         Trait t = traits[i];
1058         if (static_cast<int>(t) > static_cast<int>(result)) {
1059           result = t;
1060         }
1061       }
1062       return result;
1063     }
1064 #else
common_trait_impl(Trait result)1065     inline constexpr Trait common_trait_impl(Trait result) { return result; }
1066 
1067     template <typename... Traits>
common_trait_impl(Trait result,Trait t,Traits...ts)1068     inline constexpr Trait common_trait_impl(Trait result,
1069                                              Trait t,
1070                                              Traits... ts) {
1071       return static_cast<int>(t) > static_cast<int>(result)
1072                  ? common_trait_impl(t, ts...)
1073                  : common_trait_impl(result, ts...);
1074     }
1075 
1076     template <typename... Traits>
common_trait(Traits...ts)1077     inline constexpr Trait common_trait(Traits... ts) {
1078       return common_trait_impl(Trait::TriviallyAvailable, ts...);
1079     }
1080 #endif
1081 
1082     template <typename... Ts>
1083     struct traits {
1084       static constexpr Trait copy_constructible_trait =
1085           common_trait(trait<Ts,
1086                              lib::is_trivially_copy_constructible,
1087                              std::is_copy_constructible>()...);
1088 
1089       static constexpr Trait move_constructible_trait =
1090           common_trait(trait<Ts,
1091                              lib::is_trivially_move_constructible,
1092                              std::is_move_constructible>()...);
1093 
1094       static constexpr Trait copy_assignable_trait =
1095           common_trait(copy_constructible_trait,
1096                        trait<Ts,
1097                              lib::is_trivially_copy_assignable,
1098                              std::is_copy_assignable>()...);
1099 
1100       static constexpr Trait move_assignable_trait =
1101           common_trait(move_constructible_trait,
1102                        trait<Ts,
1103                              lib::is_trivially_move_assignable,
1104                              std::is_move_assignable>()...);
1105 
1106       static constexpr Trait destructible_trait =
1107           common_trait(trait<Ts,
1108                              std::is_trivially_destructible,
1109                              std::is_destructible>()...);
1110     };
1111 
1112     namespace access {
1113 
1114       struct recursive_union {
1115 #ifdef MPARK_RETURN_TYPE_DEDUCTION
1116         template <typename V>
get_altmpark::detail::access::recursive_union1117         inline static constexpr auto &&get_alt(V &&v, in_place_index_t<0>) {
1118           return lib::forward<V>(v).head_;
1119         }
1120 
1121         template <typename V, std::size_t I>
get_altmpark::detail::access::recursive_union1122         inline static constexpr auto &&get_alt(V &&v, in_place_index_t<I>) {
1123           return get_alt(lib::forward<V>(v).tail_, in_place_index_t<I - 1>{});
1124         }
1125 #else
1126         template <std::size_t I, bool Dummy = true>
1127         struct get_alt_impl {
1128           template <typename V>
1129           inline constexpr AUTO_REFREF operator()(V &&v) const
1130             AUTO_REFREF_RETURN(get_alt_impl<I - 1>{}(lib::forward<V>(v).tail_))
1131         };
1132 
1133         template <bool Dummy>
1134         struct get_alt_impl<0, Dummy> {
1135           template <typename V>
1136           inline constexpr AUTO_REFREF operator()(V &&v) const
1137             AUTO_REFREF_RETURN(lib::forward<V>(v).head_)
1138         };
1139 
1140         template <typename V, std::size_t I>
1141         inline static constexpr AUTO_REFREF get_alt(V &&v, in_place_index_t<I>)
1142           AUTO_REFREF_RETURN(get_alt_impl<I>{}(lib::forward<V>(v)))
1143 #endif
1144       };
1145 
1146       struct base {
1147         template <std::size_t I, typename V>
1148         inline static constexpr AUTO_REFREF get_alt(V &&v)
1149 #ifdef _MSC_VER
1150           AUTO_REFREF_RETURN(recursive_union::get_alt(
1151               lib::forward<V>(v).data_, in_place_index_t<I>{}))
1152 #else
1153           AUTO_REFREF_RETURN(recursive_union::get_alt(
1154               data(lib::forward<V>(v)), in_place_index_t<I>{}))
1155 #endif
1156       };
1157 
1158       struct variant {
1159         template <std::size_t I, typename V>
1160         inline static constexpr AUTO_REFREF get_alt(V &&v)
1161           AUTO_REFREF_RETURN(base::get_alt<I>(lib::forward<V>(v).impl_))
1162       };
1163 
1164     }  // namespace access
1165 
1166     namespace visitation {
1167 
1168 #if defined(MPARK_CPP14_CONSTEXPR) && !defined(_MSC_VER)
1169 #define MPARK_VARIANT_SWITCH_VISIT
1170 #endif
1171 
1172       struct base {
1173         template <typename Visitor, typename... Vs>
1174         using dispatch_result_t = decltype(
1175             lib::invoke(std::declval<Visitor>(),
1176                         access::base::get_alt<0>(std::declval<Vs>())...));
1177 
1178         template <typename Expected>
1179         struct expected {
1180           template <typename Actual>
but_gotmpark::detail::visitation::base::expected1181           inline static constexpr bool but_got() {
1182             return std::is_same<Expected, Actual>::value;
1183           }
1184         };
1185 
1186         template <typename Expected, typename Actual>
1187         struct visit_return_type_check {
1188           static_assert(
1189               expected<Expected>::template but_got<Actual>(),
1190               "`visit` requires the visitor to have a single return type");
1191 
1192           template <typename Visitor, typename... Alts>
1193           inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor,
1194                                                        Alts &&... alts)
1195             DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward<Visitor>(visitor),
1196                                              lib::forward<Alts>(alts)...))
1197         };
1198 
1199 #ifdef MPARK_VARIANT_SWITCH_VISIT
1200         template <bool B, typename R, typename... ITs>
1201         struct dispatcher;
1202 
1203         template <typename R, typename... ITs>
1204         struct dispatcher<false, R, ITs...> {
1205           template <std::size_t B, typename F, typename... Vs>
dispatchmpark::detail::visitation::base::dispatcher1206           MPARK_ALWAYS_INLINE static constexpr R dispatch(
1207               F &&, typename ITs::type &&..., Vs &&...) {
1208             MPARK_BUILTIN_UNREACHABLE;
1209           }
1210 
1211           template <std::size_t I, typename F, typename... Vs>
dispatch_casempark::detail::visitation::base::dispatcher1212           MPARK_ALWAYS_INLINE static constexpr R dispatch_case(F &&, Vs &&...) {
1213             MPARK_BUILTIN_UNREACHABLE;
1214           }
1215 
1216           template <std::size_t B, typename F, typename... Vs>
dispatch_atmpark::detail::visitation::base::dispatcher1217           MPARK_ALWAYS_INLINE static constexpr R dispatch_at(std::size_t,
1218                                                              F &&,
1219                                                              Vs &&...) {
1220             MPARK_BUILTIN_UNREACHABLE;
1221           }
1222         };
1223 
1224         template <typename R, typename... ITs>
1225         struct dispatcher<true, R, ITs...> {
1226           template <std::size_t B, typename F>
dispatchmpark::detail::visitation::base::dispatcher1227           MPARK_ALWAYS_INLINE static constexpr R dispatch(
1228               F &&f, typename ITs::type &&... visited_vs) {
1229             using Expected = R;
1230             using Actual = decltype(lib::invoke(
1231                 lib::forward<F>(f),
1232                 access::base::get_alt<ITs::value>(
1233                     lib::forward<typename ITs::type>(visited_vs))...));
1234             return visit_return_type_check<Expected, Actual>::invoke(
1235                 lib::forward<F>(f),
1236                 access::base::get_alt<ITs::value>(
1237                     lib::forward<typename ITs::type>(visited_vs))...);
1238           }
1239 
1240           template <std::size_t B, typename F, typename V, typename... Vs>
dispatchmpark::detail::visitation::base::dispatcher1241           MPARK_ALWAYS_INLINE static constexpr R dispatch(
1242               F &&f, typename ITs::type &&... visited_vs, V &&v, Vs &&... vs) {
1243 #define MPARK_DISPATCH(I)                                                   \
1244   dispatcher<(I < lib::decay_t<V>::size()),                                 \
1245              R,                                                             \
1246              ITs...,                                                        \
1247              lib::indexed_type<I, V>>::                                     \
1248       template dispatch<0>(lib::forward<F>(f),                              \
1249                            lib::forward<typename ITs::type>(visited_vs)..., \
1250                            lib::forward<V>(v),                              \
1251                            lib::forward<Vs>(vs)...)
1252 
1253 #define MPARK_DEFAULT(I)                                                      \
1254   dispatcher<(I < lib::decay_t<V>::size()), R, ITs...>::template dispatch<I>( \
1255       lib::forward<F>(f),                                                     \
1256       lib::forward<typename ITs::type>(visited_vs)...,                        \
1257       lib::forward<V>(v),                                                     \
1258       lib::forward<Vs>(vs)...)
1259 
1260             switch (v.index()) {
1261               case B + 0: return MPARK_DISPATCH(B + 0);
1262               case B + 1: return MPARK_DISPATCH(B + 1);
1263               case B + 2: return MPARK_DISPATCH(B + 2);
1264               case B + 3: return MPARK_DISPATCH(B + 3);
1265               case B + 4: return MPARK_DISPATCH(B + 4);
1266               case B + 5: return MPARK_DISPATCH(B + 5);
1267               case B + 6: return MPARK_DISPATCH(B + 6);
1268               case B + 7: return MPARK_DISPATCH(B + 7);
1269               case B + 8: return MPARK_DISPATCH(B + 8);
1270               case B + 9: return MPARK_DISPATCH(B + 9);
1271               case B + 10: return MPARK_DISPATCH(B + 10);
1272               case B + 11: return MPARK_DISPATCH(B + 11);
1273               case B + 12: return MPARK_DISPATCH(B + 12);
1274               case B + 13: return MPARK_DISPATCH(B + 13);
1275               case B + 14: return MPARK_DISPATCH(B + 14);
1276               case B + 15: return MPARK_DISPATCH(B + 15);
1277               case B + 16: return MPARK_DISPATCH(B + 16);
1278               case B + 17: return MPARK_DISPATCH(B + 17);
1279               case B + 18: return MPARK_DISPATCH(B + 18);
1280               case B + 19: return MPARK_DISPATCH(B + 19);
1281               case B + 20: return MPARK_DISPATCH(B + 20);
1282               case B + 21: return MPARK_DISPATCH(B + 21);
1283               case B + 22: return MPARK_DISPATCH(B + 22);
1284               case B + 23: return MPARK_DISPATCH(B + 23);
1285               case B + 24: return MPARK_DISPATCH(B + 24);
1286               case B + 25: return MPARK_DISPATCH(B + 25);
1287               case B + 26: return MPARK_DISPATCH(B + 26);
1288               case B + 27: return MPARK_DISPATCH(B + 27);
1289               case B + 28: return MPARK_DISPATCH(B + 28);
1290               case B + 29: return MPARK_DISPATCH(B + 29);
1291               case B + 30: return MPARK_DISPATCH(B + 30);
1292               case B + 31: return MPARK_DISPATCH(B + 31);
1293               default: return MPARK_DEFAULT(B + 32);
1294             }
1295 
1296 #undef MPARK_DEFAULT
1297 #undef MPARK_DISPATCH
1298           }
1299 
1300           template <std::size_t I, typename F, typename... Vs>
dispatch_casempark::detail::visitation::base::dispatcher1301           MPARK_ALWAYS_INLINE static constexpr R dispatch_case(F &&f,
1302                                                                Vs &&... vs) {
1303             using Expected = R;
1304             using Actual = decltype(
1305                 lib::invoke(lib::forward<F>(f),
1306                             access::base::get_alt<I>(lib::forward<Vs>(vs))...));
1307             return visit_return_type_check<Expected, Actual>::invoke(
1308                 lib::forward<F>(f),
1309                 access::base::get_alt<I>(lib::forward<Vs>(vs))...);
1310           }
1311 
1312           template <std::size_t B, typename F, typename V, typename... Vs>
dispatch_atmpark::detail::visitation::base::dispatcher1313           MPARK_ALWAYS_INLINE static constexpr R dispatch_at(std::size_t index,
1314                                                              F &&f,
1315                                                              V &&v,
1316                                                              Vs &&... vs) {
1317             static_assert(lib::all<(lib::decay_t<V>::size() ==
1318                                     lib::decay_t<Vs>::size())...>::value,
1319                           "all of the variants must be the same size.");
1320 #define MPARK_DISPATCH_AT(I)                                               \
1321   dispatcher<(I < lib::decay_t<V>::size()), R>::template dispatch_case<I>( \
1322       lib::forward<F>(f), lib::forward<V>(v), lib::forward<Vs>(vs)...)
1323 
1324 #define MPARK_DEFAULT(I)                                                 \
1325   dispatcher<(I < lib::decay_t<V>::size()), R>::template dispatch_at<I>( \
1326       index, lib::forward<F>(f), lib::forward<V>(v), lib::forward<Vs>(vs)...)
1327 
1328             switch (index) {
1329               case B + 0: return MPARK_DISPATCH_AT(B + 0);
1330               case B + 1: return MPARK_DISPATCH_AT(B + 1);
1331               case B + 2: return MPARK_DISPATCH_AT(B + 2);
1332               case B + 3: return MPARK_DISPATCH_AT(B + 3);
1333               case B + 4: return MPARK_DISPATCH_AT(B + 4);
1334               case B + 5: return MPARK_DISPATCH_AT(B + 5);
1335               case B + 6: return MPARK_DISPATCH_AT(B + 6);
1336               case B + 7: return MPARK_DISPATCH_AT(B + 7);
1337               case B + 8: return MPARK_DISPATCH_AT(B + 8);
1338               case B + 9: return MPARK_DISPATCH_AT(B + 9);
1339               case B + 10: return MPARK_DISPATCH_AT(B + 10);
1340               case B + 11: return MPARK_DISPATCH_AT(B + 11);
1341               case B + 12: return MPARK_DISPATCH_AT(B + 12);
1342               case B + 13: return MPARK_DISPATCH_AT(B + 13);
1343               case B + 14: return MPARK_DISPATCH_AT(B + 14);
1344               case B + 15: return MPARK_DISPATCH_AT(B + 15);
1345               case B + 16: return MPARK_DISPATCH_AT(B + 16);
1346               case B + 17: return MPARK_DISPATCH_AT(B + 17);
1347               case B + 18: return MPARK_DISPATCH_AT(B + 18);
1348               case B + 19: return MPARK_DISPATCH_AT(B + 19);
1349               case B + 20: return MPARK_DISPATCH_AT(B + 20);
1350               case B + 21: return MPARK_DISPATCH_AT(B + 21);
1351               case B + 22: return MPARK_DISPATCH_AT(B + 22);
1352               case B + 23: return MPARK_DISPATCH_AT(B + 23);
1353               case B + 24: return MPARK_DISPATCH_AT(B + 24);
1354               case B + 25: return MPARK_DISPATCH_AT(B + 25);
1355               case B + 26: return MPARK_DISPATCH_AT(B + 26);
1356               case B + 27: return MPARK_DISPATCH_AT(B + 27);
1357               case B + 28: return MPARK_DISPATCH_AT(B + 28);
1358               case B + 29: return MPARK_DISPATCH_AT(B + 29);
1359               case B + 30: return MPARK_DISPATCH_AT(B + 30);
1360               case B + 31: return MPARK_DISPATCH_AT(B + 31);
1361               default: return MPARK_DEFAULT(B + 32);
1362             }
1363 
1364 #undef MPARK_DEFAULT
1365 #undef MPARK_DISPATCH_AT
1366           }
1367         };
1368 #else
1369         template <typename T>
atmpark::detail::visitation::base1370         inline static constexpr const T &at(const T &elem) noexcept {
1371           return elem;
1372         }
1373 
1374         template <typename T, std::size_t N, typename... Is>
atmpark::detail::visitation::base1375         inline static constexpr const lib::remove_all_extents_t<T> &at(
1376             const lib::array<T, N> &elems, std::size_t i, Is... is) noexcept {
1377           return at(elems[i], is...);
1378         }
1379 
1380         template <typename F, typename... Fs>
1381         inline static constexpr lib::array<lib::decay_t<F>, sizeof...(Fs) + 1>
make_farraympark::detail::visitation::base1382         make_farray(F &&f, Fs &&... fs) {
1383           return {{lib::forward<F>(f), lib::forward<Fs>(fs)...}};
1384         }
1385 
1386         template <typename F, typename... Vs>
1387         struct make_fmatrix_impl {
1388 
1389           template <std::size_t... Is>
dispatchmpark::detail::visitation::base::make_fmatrix_impl1390           inline static constexpr dispatch_result_t<F, Vs...> dispatch(
1391               F &&f, Vs &&... vs) {
1392             using Expected = dispatch_result_t<F, Vs...>;
1393             using Actual = decltype(lib::invoke(
1394                 lib::forward<F>(f),
1395                 access::base::get_alt<Is>(lib::forward<Vs>(vs))...));
1396             return visit_return_type_check<Expected, Actual>::invoke(
1397                 lib::forward<F>(f),
1398                 access::base::get_alt<Is>(lib::forward<Vs>(vs))...);
1399           }
1400 
1401 #ifdef MPARK_RETURN_TYPE_DEDUCTION
1402           template <std::size_t... Is>
implmpark::detail::visitation::base::make_fmatrix_impl1403           inline static constexpr auto impl(lib::index_sequence<Is...>) {
1404             return &dispatch<Is...>;
1405           }
1406 
1407           template <typename Is, std::size_t... Js, typename... Ls>
implmpark::detail::visitation::base::make_fmatrix_impl1408           inline static constexpr auto impl(Is,
1409                                             lib::index_sequence<Js...>,
1410                                             Ls... ls) {
1411             return make_farray(impl(lib::push_back_t<Is, Js>{}, ls...)...);
1412           }
1413 #else
1414           template <typename...>
1415           struct impl;
1416 
1417           template <std::size_t... Is>
1418           struct impl<lib::index_sequence<Is...>> {
1419             inline constexpr AUTO operator()() const
1420               AUTO_RETURN(&dispatch<Is...>)
1421           };
1422 
1423           template <typename Is, std::size_t... Js, typename... Ls>
1424           struct impl<Is, lib::index_sequence<Js...>, Ls...> {
1425             inline constexpr AUTO operator()() const
1426               AUTO_RETURN(
1427                   make_farray(impl<lib::push_back_t<Is, Js>, Ls...>{}()...))
1428           };
1429 #endif
1430         };
1431 
1432 #ifdef MPARK_RETURN_TYPE_DEDUCTION
1433         template <typename F, typename... Vs>
make_fmatrixmpark::detail::visitation::base1434         inline static constexpr auto make_fmatrix() {
1435           return make_fmatrix_impl<F, Vs...>::impl(
1436               lib::index_sequence<>{},
1437               lib::make_index_sequence<lib::decay_t<Vs>::size()>{}...);
1438         }
1439 #else
1440         template <typename F, typename... Vs>
1441         inline static constexpr AUTO make_fmatrix()
1442           AUTO_RETURN(
1443               typename make_fmatrix_impl<F, Vs...>::template impl<
1444                   lib::index_sequence<>,
1445                   lib::make_index_sequence<lib::decay_t<Vs>::size()>...>{}())
1446 #endif
1447 
1448         template <typename F, typename... Vs>
1449         struct make_fdiagonal_impl {
1450           template <std::size_t I>
dispatchmpark::detail::visitation::base::make_fdiagonal_impl1451           inline static constexpr dispatch_result_t<F, Vs...> dispatch(
1452               F &&f, Vs &&... vs) {
1453             using Expected = dispatch_result_t<F, Vs...>;
1454             using Actual = decltype(
1455                 lib::invoke(lib::forward<F>(f),
1456                             access::base::get_alt<I>(lib::forward<Vs>(vs))...));
1457             return visit_return_type_check<Expected, Actual>::invoke(
1458                 lib::forward<F>(f),
1459                 access::base::get_alt<I>(lib::forward<Vs>(vs))...);
1460           }
1461 
1462           template <std::size_t... Is>
1463           inline static constexpr AUTO impl(lib::index_sequence<Is...>)
1464             AUTO_RETURN(make_farray(&dispatch<Is>...))
1465         };
1466 
1467         template <typename F, typename V, typename... Vs>
make_fdiagonalmpark::detail::visitation::base1468         inline static constexpr auto make_fdiagonal()
1469             -> decltype(make_fdiagonal_impl<F, V, Vs...>::impl(
1470                 lib::make_index_sequence<lib::decay_t<V>::size()>{})) {
1471           static_assert(lib::all<(lib::decay_t<V>::size() ==
1472                                   lib::decay_t<Vs>::size())...>::value,
1473                         "all of the variants must be the same size.");
1474           return make_fdiagonal_impl<F, V, Vs...>::impl(
1475               lib::make_index_sequence<lib::decay_t<V>::size()>{});
1476         }
1477 #endif
1478       };
1479 
1480 #if !defined(MPARK_VARIANT_SWITCH_VISIT) && \
1481     (!defined(_MSC_VER) || _MSC_VER >= 1910)
1482       template <typename F, typename... Vs>
1483       using fmatrix_t = decltype(base::make_fmatrix<F, Vs...>());
1484 
1485       template <typename F, typename... Vs>
1486       struct fmatrix {
1487         static constexpr fmatrix_t<F, Vs...> value =
1488             base::make_fmatrix<F, Vs...>();
1489       };
1490 
1491       template <typename F, typename... Vs>
1492       constexpr fmatrix_t<F, Vs...> fmatrix<F, Vs...>::value;
1493 
1494       template <typename F, typename... Vs>
1495       using fdiagonal_t = decltype(base::make_fdiagonal<F, Vs...>());
1496 
1497       template <typename F, typename... Vs>
1498       struct fdiagonal {
1499         static constexpr fdiagonal_t<F, Vs...> value =
1500             base::make_fdiagonal<F, Vs...>();
1501       };
1502 
1503       template <typename F, typename... Vs>
1504       constexpr fdiagonal_t<F, Vs...> fdiagonal<F, Vs...>::value;
1505 #endif
1506 
1507       struct alt {
1508         template <typename Visitor, typename... Vs>
1509         inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor,
1510                                                         Vs &&... vs)
1511 #ifdef MPARK_VARIANT_SWITCH_VISIT
1512           DECLTYPE_AUTO_RETURN(
1513               base::dispatcher<
1514                   true,
1515                   base::dispatch_result_t<Visitor,
1516                                           decltype(as_base(
1517                                               lib::forward<Vs>(vs)))...>>::
1518                   template dispatch<0>(lib::forward<Visitor>(visitor),
1519                                        as_base(lib::forward<Vs>(vs))...))
1520 #elif !defined(_MSC_VER) || _MSC_VER >= 1910
1521           DECLTYPE_AUTO_RETURN(base::at(
1522               fmatrix<Visitor &&,
1523                       decltype(as_base(lib::forward<Vs>(vs)))...>::value,
1524               vs.index()...)(lib::forward<Visitor>(visitor),
1525                              as_base(lib::forward<Vs>(vs))...))
1526 #else
1527           DECLTYPE_AUTO_RETURN(base::at(
1528               base::make_fmatrix<Visitor &&,
1529                       decltype(as_base(lib::forward<Vs>(vs)))...>(),
1530               vs.index()...)(lib::forward<Visitor>(visitor),
1531                              as_base(lib::forward<Vs>(vs))...))
1532 #endif
1533 
1534         template <typename Visitor, typename... Vs>
1535         inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index,
1536                                                            Visitor &&visitor,
1537                                                            Vs &&... vs)
1538 #ifdef MPARK_VARIANT_SWITCH_VISIT
1539           DECLTYPE_AUTO_RETURN(
1540               base::dispatcher<
1541                   true,
1542                   base::dispatch_result_t<Visitor,
1543                                           decltype(as_base(
1544                                               lib::forward<Vs>(vs)))...>>::
1545                   template dispatch_at<0>(index,
1546                                           lib::forward<Visitor>(visitor),
1547                                           as_base(lib::forward<Vs>(vs))...))
1548 #elif !defined(_MSC_VER) || _MSC_VER >= 1910
1549           DECLTYPE_AUTO_RETURN(base::at(
1550               fdiagonal<Visitor &&,
1551                         decltype(as_base(lib::forward<Vs>(vs)))...>::value,
1552               index)(lib::forward<Visitor>(visitor),
1553                      as_base(lib::forward<Vs>(vs))...))
1554 #else
1555           DECLTYPE_AUTO_RETURN(base::at(
1556               base::make_fdiagonal<Visitor &&,
1557                         decltype(as_base(lib::forward<Vs>(vs)))...>(),
1558               index)(lib::forward<Visitor>(visitor),
1559                      as_base(lib::forward<Vs>(vs))...))
1560 #endif
1561       };
1562 
1563       struct variant {
1564         private:
1565         template <typename Visitor>
1566         struct visitor {
1567           template <typename... Values>
does_not_handlempark::detail::visitation::variant::visitor1568           inline static constexpr bool does_not_handle() {
1569             return lib::is_invocable<Visitor, Values...>::value;
1570           }
1571         };
1572 
1573         template <typename Visitor, typename... Values>
1574         struct visit_exhaustiveness_check {
1575           static_assert(visitor<Visitor>::template does_not_handle<Values...>(),
1576                         "`visit` requires the visitor to be exhaustive.");
1577 
1578           inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor,
1579                                                        Values &&... values)
1580             DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward<Visitor>(visitor),
1581                                              lib::forward<Values>(values)...))
1582         };
1583 
1584         template <typename Visitor>
1585         struct value_visitor {
1586           Visitor &&visitor_;
1587 
1588           template <typename... Alts>
1589           inline constexpr DECLTYPE_AUTO operator()(Alts &&... alts) const
1590             DECLTYPE_AUTO_RETURN(
1591                 visit_exhaustiveness_check<
1592                     Visitor,
1593                     decltype((lib::forward<Alts>(alts).value))...>::
1594                     invoke(lib::forward<Visitor>(visitor_),
1595                            lib::forward<Alts>(alts).value...))
1596         };
1597 
1598         template <typename Visitor>
1599         inline static constexpr AUTO make_value_visitor(Visitor &&visitor)
1600           AUTO_RETURN(value_visitor<Visitor>{lib::forward<Visitor>(visitor)})
1601 
1602         public:
1603         template <typename Visitor, typename... Vs>
1604         inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor,
1605                                                         Vs &&... vs)
1606           DECLTYPE_AUTO_RETURN(alt::visit_alt(lib::forward<Visitor>(visitor),
1607                                               lib::forward<Vs>(vs).impl_...))
1608 
1609         template <typename Visitor, typename... Vs>
1610         inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index,
1611                                                            Visitor &&visitor,
1612                                                            Vs &&... vs)
1613           DECLTYPE_AUTO_RETURN(
1614               alt::visit_alt_at(index,
1615                                 lib::forward<Visitor>(visitor),
1616                                 lib::forward<Vs>(vs).impl_...))
1617 
1618         template <typename Visitor, typename... Vs>
1619         inline static constexpr DECLTYPE_AUTO visit_value(Visitor &&visitor,
1620                                                           Vs &&... vs)
1621           DECLTYPE_AUTO_RETURN(
1622               visit_alt(make_value_visitor(lib::forward<Visitor>(visitor)),
1623                         lib::forward<Vs>(vs)...))
1624 
1625         template <typename Visitor, typename... Vs>
1626         inline static constexpr DECLTYPE_AUTO visit_value_at(std::size_t index,
1627                                                              Visitor &&visitor,
1628                                                              Vs &&... vs)
1629           DECLTYPE_AUTO_RETURN(
1630               visit_alt_at(index,
1631                            make_value_visitor(lib::forward<Visitor>(visitor)),
1632                            lib::forward<Vs>(vs)...))
1633       };
1634 
1635     }  // namespace visitation
1636 
1637     template <std::size_t Index, typename T>
1638     struct alt {
1639       using value_type = T;
1640 
1641 #ifdef _MSC_VER
1642 #pragma warning(push)
1643 #pragma warning(disable : 4244)
1644 #endif
1645       template <typename... Args>
altmpark::detail::alt1646       inline explicit constexpr alt(in_place_t, Args &&... args)
1647           : value(lib::forward<Args>(args)...) {}
1648 #ifdef _MSC_VER
1649 #pragma warning(pop)
1650 #endif
1651 
1652       T value;
1653     };
1654 
1655     template <Trait DestructibleTrait, std::size_t Index, typename... Ts>
1656     union recursive_union;
1657 
1658     template <Trait DestructibleTrait, std::size_t Index>
1659     union recursive_union<DestructibleTrait, Index> {};
1660 
1661 #define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor)      \
1662   template <std::size_t Index, typename T, typename... Ts>                 \
1663   union recursive_union<destructible_trait, Index, T, Ts...> {             \
1664     public:                                                                \
1665     inline explicit constexpr recursive_union(valueless_t) noexcept        \
1666         : dummy_{} {}                                                      \
1667                                                                            \
1668     template <typename... Args>                                            \
1669     inline explicit constexpr recursive_union(in_place_index_t<0>,         \
1670                                               Args &&... args)             \
1671         : head_(in_place_t{}, lib::forward<Args>(args)...) {}              \
1672                                                                            \
1673     template <std::size_t I, typename... Args>                             \
1674     inline explicit constexpr recursive_union(in_place_index_t<I>,         \
1675                                               Args &&... args)             \
1676         : tail_(in_place_index_t<I - 1>{}, lib::forward<Args>(args)...) {} \
1677                                                                            \
1678     recursive_union(const recursive_union &) = default;                    \
1679     recursive_union(recursive_union &&) = default;                         \
1680                                                                            \
1681     destructor                                                             \
1682                                                                            \
1683     recursive_union &operator=(const recursive_union &) = default;         \
1684     recursive_union &operator=(recursive_union &&) = default;              \
1685                                                                            \
1686     private:                                                               \
1687     char dummy_;                                                           \
1688     alt<Index, T> head_;                                                   \
1689     recursive_union<destructible_trait, Index + 1, Ts...> tail_;           \
1690                                                                            \
1691     friend struct access::recursive_union;                                 \
1692   }
1693 
1694     MPARK_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable,
1695                                   ~recursive_union() = default;);
1696     MPARK_VARIANT_RECURSIVE_UNION(Trait::Available,
1697                                   ~recursive_union() {});
1698     MPARK_VARIANT_RECURSIVE_UNION(Trait::Unavailable,
1699                                   ~recursive_union() = delete;);
1700 
1701 #undef MPARK_VARIANT_RECURSIVE_UNION
1702 
1703     using index_t = unsigned int;
1704 
1705     template <Trait DestructibleTrait, typename... Ts>
1706     class base {
1707       public:
base(valueless_t tag)1708       inline explicit constexpr base(valueless_t tag) noexcept
1709           : data_(tag), index_(static_cast<index_t>(-1)) {}
1710 
1711       template <std::size_t I, typename... Args>
base(in_place_index_t<I>,Args &&...args)1712       inline explicit constexpr base(in_place_index_t<I>, Args &&... args)
1713           : data_(in_place_index_t<I>{}, lib::forward<Args>(args)...),
1714             index_(I) {}
1715 
valueless_by_exception() const1716       inline constexpr bool valueless_by_exception() const noexcept {
1717         return index_ == static_cast<index_t>(-1);
1718       }
1719 
index() const1720       inline constexpr std::size_t index() const noexcept {
1721         return valueless_by_exception() ? variant_npos : index_;
1722       }
1723 
1724       protected:
1725       using data_t = recursive_union<DestructibleTrait, 0, Ts...>;
1726 
as_base(base & b)1727       friend inline constexpr base &as_base(base &b) { return b; }
as_base(const base & b)1728       friend inline constexpr const base &as_base(const base &b) { return b; }
as_base(base && b)1729       friend inline constexpr base &&as_base(base &&b) { return lib::move(b); }
as_base(const base && b)1730       friend inline constexpr const base &&as_base(const base &&b) { return lib::move(b); }
1731 
data(base & b)1732       friend inline constexpr data_t &data(base &b) { return b.data_; }
data(const base & b)1733       friend inline constexpr const data_t &data(const base &b) { return b.data_; }
data(base && b)1734       friend inline constexpr data_t &&data(base &&b) { return lib::move(b).data_; }
data(const base && b)1735       friend inline constexpr const data_t &&data(const base &&b) { return lib::move(b).data_; }
1736 
size()1737       inline static constexpr std::size_t size() { return sizeof...(Ts); }
1738 
1739       data_t data_;
1740       index_t index_;
1741 
1742       friend struct access::base;
1743       friend struct visitation::base;
1744     };
1745 
1746     struct dtor {
1747 #ifdef _MSC_VER
1748 #pragma warning(push)
1749 #pragma warning(disable : 4100)
1750 #endif
1751       template <typename Alt>
operator ()mpark::detail::dtor1752       inline void operator()(Alt &alt) const noexcept { alt.~Alt(); }
1753 #ifdef _MSC_VER
1754 #pragma warning(pop)
1755 #endif
1756     };
1757 
1758 #if !defined(_MSC_VER) || _MSC_VER >= 1910
1759 #define MPARK_INHERITING_CTOR(type, base) using base::base;
1760 #else
1761 #define MPARK_INHERITING_CTOR(type, base)         \
1762   template <typename... Args>                     \
1763   inline explicit constexpr type(Args &&... args) \
1764       : base(lib::forward<Args>(args)...) {}
1765 #endif
1766 
1767     template <typename Traits, Trait = Traits::destructible_trait>
1768     class destructor;
1769 
1770 #define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \
1771   template <typename... Ts>                                               \
1772   class destructor<traits<Ts...>, destructible_trait>                     \
1773       : public base<destructible_trait, Ts...> {                          \
1774     using super = base<destructible_trait, Ts...>;                        \
1775                                                                           \
1776     public:                                                               \
1777     MPARK_INHERITING_CTOR(destructor, super)                              \
1778     using super::operator=;                                               \
1779                                                                           \
1780     destructor(const destructor &) = default;                             \
1781     destructor(destructor &&) = default;                                  \
1782     definition                                                            \
1783     destructor &operator=(const destructor &) = default;                  \
1784     destructor &operator=(destructor &&) = default;                       \
1785                                                                           \
1786     protected:                                                            \
1787     destroy                                                               \
1788   }
1789 
1790     MPARK_VARIANT_DESTRUCTOR(
1791         Trait::TriviallyAvailable,
1792         ~destructor() = default;,
1793         inline void destroy() noexcept {
1794           this->index_ = static_cast<index_t>(-1);
1795         });
1796 
1797     MPARK_VARIANT_DESTRUCTOR(
1798         Trait::Available,
1799         ~destructor() { destroy(); },
1800         inline void destroy() noexcept {
1801           if (!this->valueless_by_exception()) {
1802             visitation::alt::visit_alt(dtor{}, *this);
1803           }
1804           this->index_ = static_cast<index_t>(-1);
1805         });
1806 
1807     MPARK_VARIANT_DESTRUCTOR(
1808         Trait::Unavailable,
1809         ~destructor() = delete;,
1810         inline void destroy() noexcept = delete;);
1811 
1812 #undef MPARK_VARIANT_DESTRUCTOR
1813 
1814     template <typename Traits>
1815     class constructor : public destructor<Traits> {
1816       using super = destructor<Traits>;
1817 
1818       public:
1819       MPARK_INHERITING_CTOR(constructor, super)
1820       using super::operator=;
1821 
1822       protected:
1823 #ifndef MPARK_GENERIC_LAMBDAS
1824       struct ctor {
1825         template <typename LhsAlt, typename RhsAlt>
operator ()mpark::detail::constructor::ctor1826         inline void operator()(LhsAlt &lhs_alt, RhsAlt &&rhs_alt) const {
1827           constructor::construct_alt(lhs_alt,
1828                                      lib::forward<RhsAlt>(rhs_alt).value);
1829         }
1830       };
1831 #endif
1832 
1833       template <std::size_t I, typename T, typename... Args>
construct_alt(alt<I,T> & a,Args &&...args)1834       inline static T &construct_alt(alt<I, T> &a, Args &&... args) {
1835         auto *result = ::new (static_cast<void *>(lib::addressof(a)))
1836             alt<I, T>(in_place_t{}, lib::forward<Args>(args)...);
1837         return result->value;
1838       }
1839 
1840       template <typename Rhs>
generic_construct(constructor & lhs,Rhs && rhs)1841       inline static void generic_construct(constructor &lhs, Rhs &&rhs) {
1842         lhs.destroy();
1843         if (!rhs.valueless_by_exception()) {
1844           visitation::alt::visit_alt_at(
1845               rhs.index(),
1846 #ifdef MPARK_GENERIC_LAMBDAS
1847               [](auto &lhs_alt, auto &&rhs_alt) {
1848                 constructor::construct_alt(
1849                     lhs_alt, lib::forward<decltype(rhs_alt)>(rhs_alt).value);
1850               }
1851 #else
1852               ctor{}
1853 #endif
1854               ,
1855               lhs,
1856               lib::forward<Rhs>(rhs));
1857           lhs.index_ = rhs.index_;
1858         }
1859       }
1860     };
1861 
1862     template <typename Traits, Trait = Traits::move_constructible_trait>
1863     class move_constructor;
1864 
1865 #define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \
1866   template <typename... Ts>                                                  \
1867   class move_constructor<traits<Ts...>, move_constructible_trait>            \
1868       : public constructor<traits<Ts...>> {                                  \
1869     using super = constructor<traits<Ts...>>;                                \
1870                                                                              \
1871     public:                                                                  \
1872     MPARK_INHERITING_CTOR(move_constructor, super)                           \
1873     using super::operator=;                                                  \
1874                                                                              \
1875     move_constructor(const move_constructor &) = default;                    \
1876     definition                                                               \
1877     ~move_constructor() = default;                                           \
1878     move_constructor &operator=(const move_constructor &) = default;         \
1879     move_constructor &operator=(move_constructor &&) = default;              \
1880   }
1881 
1882     MPARK_VARIANT_MOVE_CONSTRUCTOR(
1883         Trait::TriviallyAvailable,
1884         move_constructor(move_constructor &&that) = default;);
1885 
1886     MPARK_VARIANT_MOVE_CONSTRUCTOR(
1887         Trait::Available,
1888         move_constructor(move_constructor &&that) noexcept(
1889             lib::all<std::is_nothrow_move_constructible<Ts>::value...>::value)
1890             : move_constructor(valueless_t{}) {
1891           this->generic_construct(*this, lib::move(that));
1892         });
1893 
1894     MPARK_VARIANT_MOVE_CONSTRUCTOR(
1895         Trait::Unavailable,
1896         move_constructor(move_constructor &&) = delete;);
1897 
1898 #undef MPARK_VARIANT_MOVE_CONSTRUCTOR
1899 
1900     template <typename Traits, Trait = Traits::copy_constructible_trait>
1901     class copy_constructor;
1902 
1903 #define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \
1904   template <typename... Ts>                                                  \
1905   class copy_constructor<traits<Ts...>, copy_constructible_trait>            \
1906       : public move_constructor<traits<Ts...>> {                             \
1907     using super = move_constructor<traits<Ts...>>;                           \
1908                                                                              \
1909     public:                                                                  \
1910     MPARK_INHERITING_CTOR(copy_constructor, super)                           \
1911     using super::operator=;                                                  \
1912                                                                              \
1913     definition                                                               \
1914     copy_constructor(copy_constructor &&) = default;                         \
1915     ~copy_constructor() = default;                                           \
1916     copy_constructor &operator=(const copy_constructor &) = default;         \
1917     copy_constructor &operator=(copy_constructor &&) = default;              \
1918   }
1919 
1920     MPARK_VARIANT_COPY_CONSTRUCTOR(
1921         Trait::TriviallyAvailable,
1922         copy_constructor(const copy_constructor &that) = default;);
1923 
1924     MPARK_VARIANT_COPY_CONSTRUCTOR(
1925         Trait::Available,
1926         copy_constructor(const copy_constructor &that)
1927             : copy_constructor(valueless_t{}) {
1928           this->generic_construct(*this, that);
1929         });
1930 
1931     MPARK_VARIANT_COPY_CONSTRUCTOR(
1932         Trait::Unavailable,
1933         copy_constructor(const copy_constructor &) = delete;);
1934 
1935 #undef MPARK_VARIANT_COPY_CONSTRUCTOR
1936 
1937     template <typename Traits>
1938     class assignment : public copy_constructor<Traits> {
1939       using super = copy_constructor<Traits>;
1940 
1941       public:
1942       MPARK_INHERITING_CTOR(assignment, super)
1943       using super::operator=;
1944 
1945       template <std::size_t I, typename... Args>
emplace(Args &&...args)1946       inline /* auto & */ auto emplace(Args &&... args)
1947           -> decltype(this->construct_alt(access::base::get_alt<I>(*this),
1948                                           lib::forward<Args>(args)...)) {
1949         this->destroy();
1950         auto &result = this->construct_alt(access::base::get_alt<I>(*this),
1951                                            lib::forward<Args>(args)...);
1952         this->index_ = I;
1953         return result;
1954       }
1955 
1956       protected:
1957 #ifndef MPARK_GENERIC_LAMBDAS
1958       template <typename That>
1959       struct assigner {
1960         template <typename ThisAlt, typename ThatAlt>
operator ()mpark::detail::assignment::assigner1961         inline void operator()(ThisAlt &this_alt, ThatAlt &&that_alt) const {
1962           self->assign_alt(this_alt, lib::forward<ThatAlt>(that_alt).value);
1963         }
1964         assignment *self;
1965       };
1966 #endif
1967 
1968       template <std::size_t I, typename T, typename Arg>
assign_alt(alt<I,T> & a,Arg && arg)1969       inline void assign_alt(alt<I, T> &a, Arg &&arg) {
1970         if (this->index() == I) {
1971 #ifdef _MSC_VER
1972 #pragma warning(push)
1973 #pragma warning(disable : 4244)
1974 #endif
1975           a.value = lib::forward<Arg>(arg);
1976 #ifdef _MSC_VER
1977 #pragma warning(pop)
1978 #endif
1979         } else {
1980           struct {
1981             void operator()(std::true_type) const {
1982               this_->emplace<I>(lib::forward<Arg>(arg_));
1983             }
1984             void operator()(std::false_type) const {
1985               this_->emplace<I>(T(lib::forward<Arg>(arg_)));
1986             }
1987             assignment *this_;
1988             Arg &&arg_;
1989           } impl{this, lib::forward<Arg>(arg)};
1990           impl(lib::bool_constant<
1991                    std::is_nothrow_constructible<T, Arg>::value ||
1992                    !std::is_nothrow_move_constructible<T>::value>{});
1993         }
1994       }
1995 
1996       template <typename That>
generic_assign(That && that)1997       inline void generic_assign(That &&that) {
1998         if (this->valueless_by_exception() && that.valueless_by_exception()) {
1999           // do nothing.
2000         } else if (that.valueless_by_exception()) {
2001           this->destroy();
2002         } else {
2003           visitation::alt::visit_alt_at(
2004               that.index(),
2005 #ifdef MPARK_GENERIC_LAMBDAS
2006               [this](auto &this_alt, auto &&that_alt) {
2007                 this->assign_alt(
2008                     this_alt, lib::forward<decltype(that_alt)>(that_alt).value);
2009               }
2010 #else
2011               assigner<That>{this}
2012 #endif
2013               ,
2014               *this,
2015               lib::forward<That>(that));
2016         }
2017       }
2018     };
2019 
2020     template <typename Traits, Trait = Traits::move_assignable_trait>
2021     class move_assignment;
2022 
2023 #define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \
2024   template <typename... Ts>                                              \
2025   class move_assignment<traits<Ts...>, move_assignable_trait>            \
2026       : public assignment<traits<Ts...>> {                               \
2027     using super = assignment<traits<Ts...>>;                             \
2028                                                                          \
2029     public:                                                              \
2030     MPARK_INHERITING_CTOR(move_assignment, super)                        \
2031     using super::operator=;                                              \
2032                                                                          \
2033     move_assignment(const move_assignment &) = default;                  \
2034     move_assignment(move_assignment &&) = default;                       \
2035     ~move_assignment() = default;                                        \
2036     move_assignment &operator=(const move_assignment &) = default;       \
2037     definition                                                           \
2038   }
2039 
2040     MPARK_VARIANT_MOVE_ASSIGNMENT(
2041         Trait::TriviallyAvailable,
2042         move_assignment &operator=(move_assignment &&that) = default;);
2043 
2044     MPARK_VARIANT_MOVE_ASSIGNMENT(
2045         Trait::Available,
2046         move_assignment &
2047         operator=(move_assignment &&that) noexcept(
2048             lib::all<(std::is_nothrow_move_constructible<Ts>::value &&
2049                       std::is_nothrow_move_assignable<Ts>::value)...>::value) {
2050           this->generic_assign(lib::move(that));
2051           return *this;
2052         });
2053 
2054     MPARK_VARIANT_MOVE_ASSIGNMENT(
2055         Trait::Unavailable,
2056         move_assignment &operator=(move_assignment &&) = delete;);
2057 
2058 #undef MPARK_VARIANT_MOVE_ASSIGNMENT
2059 
2060     template <typename Traits, Trait = Traits::copy_assignable_trait>
2061     class copy_assignment;
2062 
2063 #define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \
2064   template <typename... Ts>                                              \
2065   class copy_assignment<traits<Ts...>, copy_assignable_trait>            \
2066       : public move_assignment<traits<Ts...>> {                          \
2067     using super = move_assignment<traits<Ts...>>;                        \
2068                                                                          \
2069     public:                                                              \
2070     MPARK_INHERITING_CTOR(copy_assignment, super)                        \
2071     using super::operator=;                                              \
2072                                                                          \
2073     copy_assignment(const copy_assignment &) = default;                  \
2074     copy_assignment(copy_assignment &&) = default;                       \
2075     ~copy_assignment() = default;                                        \
2076     definition                                                           \
2077     copy_assignment &operator=(copy_assignment &&) = default;            \
2078   }
2079 
2080     MPARK_VARIANT_COPY_ASSIGNMENT(
2081         Trait::TriviallyAvailable,
2082         copy_assignment &operator=(const copy_assignment &that) = default;);
2083 
2084     MPARK_VARIANT_COPY_ASSIGNMENT(
2085         Trait::Available,
2086         copy_assignment &operator=(const copy_assignment &that) {
2087           this->generic_assign(that);
2088           return *this;
2089         });
2090 
2091     MPARK_VARIANT_COPY_ASSIGNMENT(
2092         Trait::Unavailable,
2093         copy_assignment &operator=(const copy_assignment &) = delete;);
2094 
2095 #undef MPARK_VARIANT_COPY_ASSIGNMENT
2096 
2097     template <typename... Ts>
2098     class impl : public copy_assignment<traits<Ts...>> {
2099       using super = copy_assignment<traits<Ts...>>;
2100 
2101       public:
2102       MPARK_INHERITING_CTOR(impl, super)
2103       using super::operator=;
2104 
2105       template <std::size_t I, typename Arg>
assign(Arg && arg)2106       inline void assign(Arg &&arg) {
2107         this->assign_alt(access::base::get_alt<I>(*this),
2108                          lib::forward<Arg>(arg));
2109       }
2110 
swap(impl & that)2111       inline void swap(impl &that) {
2112         if (this->valueless_by_exception() && that.valueless_by_exception()) {
2113           // do nothing.
2114         } else if (this->index() == that.index()) {
2115           visitation::alt::visit_alt_at(this->index(),
2116 #ifdef MPARK_GENERIC_LAMBDAS
2117                                         [](auto &this_alt, auto &that_alt) {
2118                                           using std::swap;
2119                                           swap(this_alt.value,
2120                                                that_alt.value);
2121                                         }
2122 #else
2123                                         swapper{}
2124 #endif
2125                                         ,
2126                                         *this,
2127                                         that);
2128         } else {
2129           impl *lhs = this;
2130           impl *rhs = lib::addressof(that);
2131           if (lhs->move_nothrow() && !rhs->move_nothrow()) {
2132             std::swap(lhs, rhs);
2133           }
2134           impl tmp(lib::move(*rhs));
2135 #ifdef MPARK_EXCEPTIONS
2136           // EXTENSION: When the move construction of `lhs` into `rhs` throws
2137           // and `tmp` is nothrow move constructible then we move `tmp` back
2138           // into `rhs` and provide the strong exception safety guarantee.
2139           try {
2140             this->generic_construct(*rhs, lib::move(*lhs));
2141           } catch (...) {
2142             if (tmp.move_nothrow()) {
2143               this->generic_construct(*rhs, lib::move(tmp));
2144             }
2145             throw;
2146           }
2147 #else
2148           this->generic_construct(*rhs, lib::move(*lhs));
2149 #endif
2150           this->generic_construct(*lhs, lib::move(tmp));
2151         }
2152       }
2153 
2154       private:
2155 #ifndef MPARK_GENERIC_LAMBDAS
2156       struct swapper {
2157         template <typename ThisAlt, typename ThatAlt>
operator ()mpark::detail::impl::swapper2158         inline void operator()(ThisAlt &this_alt, ThatAlt &that_alt) const {
2159           using std::swap;
2160           swap(this_alt.value, that_alt.value);
2161         }
2162       };
2163 #endif
2164 
move_nothrow() const2165       inline constexpr bool move_nothrow() const {
2166         return this->valueless_by_exception() ||
2167                lib::array<bool, sizeof...(Ts)>{
2168                    {std::is_nothrow_move_constructible<Ts>::value...}
2169                }[this->index()];
2170       }
2171     };
2172 
2173 #undef MPARK_INHERITING_CTOR
2174 
2175     template <std::size_t I, typename T>
2176     struct overload_leaf {
2177       using F = lib::size_constant<I> (*)(T);
operator Fmpark::detail::overload_leaf2178       operator F() const { return nullptr; }
2179     };
2180 
2181     template <typename... Ts>
2182     struct overload_impl {
2183       private:
2184       template <typename>
2185       struct impl;
2186 
2187       template <std::size_t... Is>
2188       struct impl<lib::index_sequence<Is...>> : overload_leaf<Is, Ts>... {};
2189 
2190       public:
2191       using type = impl<lib::index_sequence_for<Ts...>>;
2192     };
2193 
2194     template <typename... Ts>
2195     using overload = typename overload_impl<Ts...>::type;
2196 
2197     template <typename T, typename... Ts>
2198     using best_match = lib::invoke_result_t<overload<Ts...>, T &&>;
2199 
2200     template <typename T>
2201     struct is_in_place_index : std::false_type {};
2202 
2203     template <std::size_t I>
2204     struct is_in_place_index<in_place_index_t<I>> : std::true_type {};
2205 
2206     template <typename T>
2207     struct is_in_place_type : std::false_type {};
2208 
2209     template <typename T>
2210     struct is_in_place_type<in_place_type_t<T>> : std::true_type {};
2211 
2212   }  // detail
2213 
2214   template <typename... Ts>
2215   class variant {
2216     static_assert(0 < sizeof...(Ts),
2217                   "variant must consist of at least one alternative.");
2218 
2219     static_assert(lib::all<!std::is_array<Ts>::value...>::value,
2220                   "variant can not have an array type as an alternative.");
2221 
2222     static_assert(lib::all<!std::is_reference<Ts>::value...>::value,
2223                   "variant can not have a reference type as an alternative.");
2224 
2225     static_assert(lib::all<!std::is_void<Ts>::value...>::value,
2226                   "variant can not have a void type as an alternative.");
2227 
2228     public:
2229     template <
2230         typename Front = lib::type_pack_element_t<0, Ts...>,
2231         lib::enable_if_t<std::is_default_constructible<Front>::value, int> = 0>
variant()2232     inline constexpr variant() noexcept(
2233         std::is_nothrow_default_constructible<Front>::value)
2234         : impl_(in_place_index_t<0>{}) {}
2235 
2236     variant(const variant &) = default;
2237     variant(variant &&) = default;
2238 
2239     template <
2240         typename Arg,
2241         typename Decayed = lib::decay_t<Arg>,
2242         lib::enable_if_t<!std::is_same<Decayed, variant>::value, int> = 0,
2243         lib::enable_if_t<!detail::is_in_place_index<Decayed>::value, int> = 0,
2244         lib::enable_if_t<!detail::is_in_place_type<Decayed>::value, int> = 0,
2245         std::size_t I = detail::best_match<Arg, Ts...>::value,
2246         typename T = lib::type_pack_element_t<I, Ts...>,
2247         lib::enable_if_t<std::is_constructible<T, Arg>::value, int> = 0>
variant(Arg && arg)2248     inline constexpr variant(Arg &&arg) noexcept(
2249         std::is_nothrow_constructible<T, Arg>::value)
2250         : impl_(in_place_index_t<I>{}, lib::forward<Arg>(arg)) {}
2251 
2252     template <
2253         std::size_t I,
2254         typename... Args,
2255         typename T = lib::type_pack_element_t<I, Ts...>,
2256         lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
variant(in_place_index_t<I>,Args &&...args)2257     inline explicit constexpr variant(
2258         in_place_index_t<I>,
2259         Args &&... args) noexcept(std::is_nothrow_constructible<T,
2260                                                                 Args...>::value)
2261         : impl_(in_place_index_t<I>{}, lib::forward<Args>(args)...) {}
2262 
2263     template <
2264         std::size_t I,
2265         typename Up,
2266         typename... Args,
2267         typename T = lib::type_pack_element_t<I, Ts...>,
2268         lib::enable_if_t<std::is_constructible<T,
2269                                                std::initializer_list<Up> &,
2270                                                Args...>::value,
2271                          int> = 0>
variant(in_place_index_t<I>,std::initializer_list<Up> il,Args &&...args)2272     inline explicit constexpr variant(
2273         in_place_index_t<I>,
2274         std::initializer_list<Up> il,
2275         Args &&... args) noexcept(std::
2276                                       is_nothrow_constructible<
2277                                           T,
2278                                           std::initializer_list<Up> &,
2279                                           Args...>::value)
2280         : impl_(in_place_index_t<I>{}, il, lib::forward<Args>(args)...) {}
2281 
2282     template <
2283         typename T,
2284         typename... Args,
2285         std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
2286         lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
variant(in_place_type_t<T>,Args &&...args)2287     inline explicit constexpr variant(
2288         in_place_type_t<T>,
2289         Args &&... args) noexcept(std::is_nothrow_constructible<T,
2290                                                                 Args...>::value)
2291         : impl_(in_place_index_t<I>{}, lib::forward<Args>(args)...) {}
2292 
2293     template <
2294         typename T,
2295         typename Up,
2296         typename... Args,
2297         std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
2298         lib::enable_if_t<std::is_constructible<T,
2299                                                std::initializer_list<Up> &,
2300                                                Args...>::value,
2301                          int> = 0>
variant(in_place_type_t<T>,std::initializer_list<Up> il,Args &&...args)2302     inline explicit constexpr variant(
2303         in_place_type_t<T>,
2304         std::initializer_list<Up> il,
2305         Args &&... args) noexcept(std::
2306                                       is_nothrow_constructible<
2307                                           T,
2308                                           std::initializer_list<Up> &,
2309                                           Args...>::value)
2310         : impl_(in_place_index_t<I>{}, il, lib::forward<Args>(args)...) {}
2311 
2312     ~variant() = default;
2313 
2314     variant &operator=(const variant &) = default;
2315     variant &operator=(variant &&) = default;
2316 
2317     template <typename Arg,
2318               lib::enable_if_t<!std::is_same<lib::decay_t<Arg>, variant>::value,
2319                                int> = 0,
2320               std::size_t I = detail::best_match<Arg, Ts...>::value,
2321               typename T = lib::type_pack_element_t<I, Ts...>,
2322               lib::enable_if_t<(std::is_assignable<T &, Arg>::value &&
2323                                 std::is_constructible<T, Arg>::value),
2324                                int> = 0>
operator =(Arg && arg)2325     inline variant &operator=(Arg &&arg) noexcept(
2326         (std::is_nothrow_assignable<T &, Arg>::value &&
2327          std::is_nothrow_constructible<T, Arg>::value)) {
2328       impl_.template assign<I>(lib::forward<Arg>(arg));
2329       return *this;
2330     }
2331 
2332     template <
2333         std::size_t I,
2334         typename... Args,
2335         typename T = lib::type_pack_element_t<I, Ts...>,
2336         lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
emplace(Args &&...args)2337     inline T &emplace(Args &&... args) {
2338       return impl_.template emplace<I>(lib::forward<Args>(args)...);
2339     }
2340 
2341     template <
2342         std::size_t I,
2343         typename Up,
2344         typename... Args,
2345         typename T = lib::type_pack_element_t<I, Ts...>,
2346         lib::enable_if_t<std::is_constructible<T,
2347                                                std::initializer_list<Up> &,
2348                                                Args...>::value,
2349                          int> = 0>
emplace(std::initializer_list<Up> il,Args &&...args)2350     inline T &emplace(std::initializer_list<Up> il, Args &&... args) {
2351       return impl_.template emplace<I>(il, lib::forward<Args>(args)...);
2352     }
2353 
2354     template <
2355         typename T,
2356         typename... Args,
2357         std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
2358         lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
emplace(Args &&...args)2359     inline T &emplace(Args &&... args) {
2360       return impl_.template emplace<I>(lib::forward<Args>(args)...);
2361     }
2362 
2363     template <
2364         typename T,
2365         typename Up,
2366         typename... Args,
2367         std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
2368         lib::enable_if_t<std::is_constructible<T,
2369                                                std::initializer_list<Up> &,
2370                                                Args...>::value,
2371                          int> = 0>
emplace(std::initializer_list<Up> il,Args &&...args)2372     inline T &emplace(std::initializer_list<Up> il, Args &&... args) {
2373       return impl_.template emplace<I>(il, lib::forward<Args>(args)...);
2374     }
2375 
valueless_by_exception() const2376     inline constexpr bool valueless_by_exception() const noexcept {
2377       return impl_.valueless_by_exception();
2378     }
2379 
index() const2380     inline constexpr std::size_t index() const noexcept {
2381       return impl_.index();
2382     }
2383 
2384     template <bool Dummy = true,
2385               lib::enable_if_t<
2386                   lib::all<Dummy,
2387                            (lib::dependent_type<std::is_move_constructible<Ts>,
2388                                                 Dummy>::value &&
2389                             lib::dependent_type<lib::is_swappable<Ts>,
2390                                                 Dummy>::value)...>::value,
2391                   int> = 0>
swap(variant & that)2392     inline void swap(variant &that) noexcept(
2393         lib::all<(std::is_nothrow_move_constructible<Ts>::value &&
2394                   lib::is_nothrow_swappable<Ts>::value)...>::value) {
2395       impl_.swap(that.impl_);
2396     }
2397 
2398     private:
2399     detail::impl<Ts...> impl_;
2400 
2401     friend struct detail::access::variant;
2402     friend struct detail::visitation::variant;
2403   };
2404 
2405   template <std::size_t I, typename... Ts>
holds_alternative(const variant<Ts...> & v)2406   inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept {
2407     return v.index() == I;
2408   }
2409 
2410   template <typename T, typename... Ts>
holds_alternative(const variant<Ts...> & v)2411   inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept {
2412     return holds_alternative<detail::find_index_checked<T, Ts...>::value>(v);
2413   }
2414 
2415   namespace detail {
2416     template <std::size_t I, typename V>
2417     struct generic_get_impl {
generic_get_implmpark::detail::generic_get_impl2418       constexpr generic_get_impl(int) noexcept {}
2419 
2420       constexpr AUTO_REFREF operator()(V &&v) const
2421         AUTO_REFREF_RETURN(
2422             access::variant::get_alt<I>(lib::forward<V>(v)).value)
2423     };
2424 
2425     template <std::size_t I, typename V>
2426     inline constexpr AUTO_REFREF generic_get(V &&v)
2427       AUTO_REFREF_RETURN(generic_get_impl<I, V>(
2428           holds_alternative<I>(v) ? 0 : (throw_bad_variant_access(), 0))(
2429           lib::forward<V>(v)))
2430   }  // namespace detail
2431 
2432   template <std::size_t I, typename... Ts>
get(variant<Ts...> & v)2433   inline constexpr variant_alternative_t<I, variant<Ts...>> &get(
2434       variant<Ts...> &v) {
2435     return detail::generic_get<I>(v);
2436   }
2437 
2438   template <std::size_t I, typename... Ts>
get(variant<Ts...> && v)2439   inline constexpr variant_alternative_t<I, variant<Ts...>> &&get(
2440       variant<Ts...> &&v) {
2441     return detail::generic_get<I>(lib::move(v));
2442   }
2443 
2444   template <std::size_t I, typename... Ts>
get(const variant<Ts...> & v)2445   inline constexpr const variant_alternative_t<I, variant<Ts...>> &get(
2446       const variant<Ts...> &v) {
2447     return detail::generic_get<I>(v);
2448   }
2449 
2450   template <std::size_t I, typename... Ts>
get(const variant<Ts...> && v)2451   inline constexpr const variant_alternative_t<I, variant<Ts...>> &&get(
2452       const variant<Ts...> &&v) {
2453     return detail::generic_get<I>(lib::move(v));
2454   }
2455 
2456   template <typename T, typename... Ts>
get(variant<Ts...> & v)2457   inline constexpr T &get(variant<Ts...> &v) {
2458     return get<detail::find_index_checked<T, Ts...>::value>(v);
2459   }
2460 
2461   template <typename T, typename... Ts>
get(variant<Ts...> && v)2462   inline constexpr T &&get(variant<Ts...> &&v) {
2463     return get<detail::find_index_checked<T, Ts...>::value>(lib::move(v));
2464   }
2465 
2466   template <typename T, typename... Ts>
get(const variant<Ts...> & v)2467   inline constexpr const T &get(const variant<Ts...> &v) {
2468     return get<detail::find_index_checked<T, Ts...>::value>(v);
2469   }
2470 
2471   template <typename T, typename... Ts>
get(const variant<Ts...> && v)2472   inline constexpr const T &&get(const variant<Ts...> &&v) {
2473     return get<detail::find_index_checked<T, Ts...>::value>(lib::move(v));
2474   }
2475 
2476   namespace detail {
2477 
2478     template <std::size_t I, typename V>
2479     inline constexpr /* auto * */ AUTO generic_get_if(V *v) noexcept
2480       AUTO_RETURN(v && holds_alternative<I>(*v)
2481                       ? lib::addressof(access::variant::get_alt<I>(*v).value)
2482                       : nullptr)
2483 
2484   }  // namespace detail
2485 
2486   template <std::size_t I, typename... Ts>
2487   inline constexpr lib::add_pointer_t<variant_alternative_t<I, variant<Ts...>>>
get_if(variant<Ts...> * v)2488   get_if(variant<Ts...> *v) noexcept {
2489     return detail::generic_get_if<I>(v);
2490   }
2491 
2492   template <std::size_t I, typename... Ts>
2493   inline constexpr lib::add_pointer_t<
2494       const variant_alternative_t<I, variant<Ts...>>>
get_if(const variant<Ts...> * v)2495   get_if(const variant<Ts...> *v) noexcept {
2496     return detail::generic_get_if<I>(v);
2497   }
2498 
2499   template <typename T, typename... Ts>
2500   inline constexpr lib::add_pointer_t<T>
get_if(variant<Ts...> * v)2501   get_if(variant<Ts...> *v) noexcept {
2502     return get_if<detail::find_index_checked<T, Ts...>::value>(v);
2503   }
2504 
2505   template <typename T, typename... Ts>
2506   inline constexpr lib::add_pointer_t<const T>
get_if(const variant<Ts...> * v)2507   get_if(const variant<Ts...> *v) noexcept {
2508     return get_if<detail::find_index_checked<T, Ts...>::value>(v);
2509   }
2510 
2511   namespace detail {
2512     template <typename RelOp>
2513     struct convert_to_bool {
2514       template <typename Lhs, typename Rhs>
operator ()mpark::detail::convert_to_bool2515       inline constexpr bool operator()(Lhs &&lhs, Rhs &&rhs) const {
2516         static_assert(std::is_convertible<lib::invoke_result_t<RelOp, Lhs, Rhs>,
2517                                           bool>::value,
2518                       "relational operators must return a type"
2519                       " implicitly convertible to bool");
2520         return lib::invoke(
2521             RelOp{}, lib::forward<Lhs>(lhs), lib::forward<Rhs>(rhs));
2522       }
2523     };
2524   }  // namespace detail
2525 
2526   template <typename... Ts>
operator ==(const variant<Ts...> & lhs,const variant<Ts...> & rhs)2527   inline constexpr bool operator==(const variant<Ts...> &lhs,
2528                                    const variant<Ts...> &rhs) {
2529     using detail::visitation::variant;
2530     using equal_to = detail::convert_to_bool<lib::equal_to>;
2531 #ifdef MPARK_CPP14_CONSTEXPR
2532     if (lhs.index() != rhs.index()) return false;
2533     if (lhs.valueless_by_exception()) return true;
2534     return variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs);
2535 #else
2536     return lhs.index() == rhs.index() &&
2537            (lhs.valueless_by_exception() ||
2538             variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs));
2539 #endif
2540   }
2541 
2542   template <typename... Ts>
operator !=(const variant<Ts...> & lhs,const variant<Ts...> & rhs)2543   inline constexpr bool operator!=(const variant<Ts...> &lhs,
2544                                    const variant<Ts...> &rhs) {
2545     using detail::visitation::variant;
2546     using not_equal_to = detail::convert_to_bool<lib::not_equal_to>;
2547 #ifdef MPARK_CPP14_CONSTEXPR
2548     if (lhs.index() != rhs.index()) return true;
2549     if (lhs.valueless_by_exception()) return false;
2550     return variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs);
2551 #else
2552     return lhs.index() != rhs.index() ||
2553            (!lhs.valueless_by_exception() &&
2554             variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs));
2555 #endif
2556   }
2557 
2558   template <typename... Ts>
operator <(const variant<Ts...> & lhs,const variant<Ts...> & rhs)2559   inline constexpr bool operator<(const variant<Ts...> &lhs,
2560                                   const variant<Ts...> &rhs) {
2561     using detail::visitation::variant;
2562     using less = detail::convert_to_bool<lib::less>;
2563 #ifdef MPARK_CPP14_CONSTEXPR
2564     if (rhs.valueless_by_exception()) return false;
2565     if (lhs.valueless_by_exception()) return true;
2566     if (lhs.index() < rhs.index()) return true;
2567     if (lhs.index() > rhs.index()) return false;
2568     return variant::visit_value_at(lhs.index(), less{}, lhs, rhs);
2569 #else
2570     return !rhs.valueless_by_exception() &&
2571            (lhs.valueless_by_exception() || lhs.index() < rhs.index() ||
2572             (lhs.index() == rhs.index() &&
2573              variant::visit_value_at(lhs.index(), less{}, lhs, rhs)));
2574 #endif
2575   }
2576 
2577   template <typename... Ts>
operator >(const variant<Ts...> & lhs,const variant<Ts...> & rhs)2578   inline constexpr bool operator>(const variant<Ts...> &lhs,
2579                                   const variant<Ts...> &rhs) {
2580     using detail::visitation::variant;
2581     using greater = detail::convert_to_bool<lib::greater>;
2582 #ifdef MPARK_CPP14_CONSTEXPR
2583     if (lhs.valueless_by_exception()) return false;
2584     if (rhs.valueless_by_exception()) return true;
2585     if (lhs.index() > rhs.index()) return true;
2586     if (lhs.index() < rhs.index()) return false;
2587     return variant::visit_value_at(lhs.index(), greater{}, lhs, rhs);
2588 #else
2589     return !lhs.valueless_by_exception() &&
2590            (rhs.valueless_by_exception() || lhs.index() > rhs.index() ||
2591             (lhs.index() == rhs.index() &&
2592              variant::visit_value_at(lhs.index(), greater{}, lhs, rhs)));
2593 #endif
2594   }
2595 
2596   template <typename... Ts>
operator <=(const variant<Ts...> & lhs,const variant<Ts...> & rhs)2597   inline constexpr bool operator<=(const variant<Ts...> &lhs,
2598                                    const variant<Ts...> &rhs) {
2599     using detail::visitation::variant;
2600     using less_equal = detail::convert_to_bool<lib::less_equal>;
2601 #ifdef MPARK_CPP14_CONSTEXPR
2602     if (lhs.valueless_by_exception()) return true;
2603     if (rhs.valueless_by_exception()) return false;
2604     if (lhs.index() < rhs.index()) return true;
2605     if (lhs.index() > rhs.index()) return false;
2606     return variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs);
2607 #else
2608     return lhs.valueless_by_exception() ||
2609            (!rhs.valueless_by_exception() &&
2610             (lhs.index() < rhs.index() ||
2611              (lhs.index() == rhs.index() &&
2612               variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs))));
2613 #endif
2614   }
2615 
2616   template <typename... Ts>
operator >=(const variant<Ts...> & lhs,const variant<Ts...> & rhs)2617   inline constexpr bool operator>=(const variant<Ts...> &lhs,
2618                                    const variant<Ts...> &rhs) {
2619     using detail::visitation::variant;
2620     using greater_equal = detail::convert_to_bool<lib::greater_equal>;
2621 #ifdef MPARK_CPP14_CONSTEXPR
2622     if (rhs.valueless_by_exception()) return true;
2623     if (lhs.valueless_by_exception()) return false;
2624     if (lhs.index() > rhs.index()) return true;
2625     if (lhs.index() < rhs.index()) return false;
2626     return variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs);
2627 #else
2628     return rhs.valueless_by_exception() ||
2629            (!lhs.valueless_by_exception() &&
2630             (lhs.index() > rhs.index() ||
2631              (lhs.index() == rhs.index() &&
2632               variant::visit_value_at(
2633                   lhs.index(), greater_equal{}, lhs, rhs))));
2634 #endif
2635   }
2636 
2637   struct monostate {};
2638 
operator <(monostate,monostate)2639   inline constexpr bool operator<(monostate, monostate) noexcept {
2640     return false;
2641   }
2642 
operator >(monostate,monostate)2643   inline constexpr bool operator>(monostate, monostate) noexcept {
2644     return false;
2645   }
2646 
operator <=(monostate,monostate)2647   inline constexpr bool operator<=(monostate, monostate) noexcept {
2648     return true;
2649   }
2650 
operator >=(monostate,monostate)2651   inline constexpr bool operator>=(monostate, monostate) noexcept {
2652     return true;
2653   }
2654 
operator ==(monostate,monostate)2655   inline constexpr bool operator==(monostate, monostate) noexcept {
2656     return true;
2657   }
2658 
operator !=(monostate,monostate)2659   inline constexpr bool operator!=(monostate, monostate) noexcept {
2660     return false;
2661   }
2662 
2663 #ifdef MPARK_CPP14_CONSTEXPR
2664   namespace detail {
2665 
any(std::initializer_list<bool> bs)2666     inline constexpr bool any(std::initializer_list<bool> bs) {
2667       for (bool b : bs) {
2668         if (b) {
2669           return true;
2670         }
2671       }
2672       return false;
2673     }
2674 
2675   }  // namespace detail
2676 
2677   template <typename Visitor, typename... Vs>
visit(Visitor && visitor,Vs &&...vs)2678   inline constexpr decltype(auto) visit(Visitor &&visitor, Vs &&... vs) {
2679     return (!detail::any({vs.valueless_by_exception()...})
2680                 ? (void)0
2681                 : throw_bad_variant_access()),
2682            detail::visitation::variant::visit_value(
2683                lib::forward<Visitor>(visitor), lib::forward<Vs>(vs)...);
2684   }
2685 #else
2686   namespace detail {
2687 
2688     template <std::size_t N>
all_impl(const lib::array<bool,N> & bs,std::size_t idx)2689     inline constexpr bool all_impl(const lib::array<bool, N> &bs,
2690                                    std::size_t idx) {
2691       return idx >= N || (bs[idx] && all_impl(bs, idx + 1));
2692     }
2693 
2694     template <std::size_t N>
all(const lib::array<bool,N> & bs)2695     inline constexpr bool all(const lib::array<bool, N> &bs) {
2696       return all_impl(bs, 0);
2697     }
2698 
2699   }  // namespace detail
2700 
2701   template <typename Visitor, typename... Vs>
visit(Visitor && visitor,Vs &&...vs)2702   inline constexpr DECLTYPE_AUTO visit(Visitor &&visitor, Vs &&... vs)
2703     DECLTYPE_AUTO_RETURN(
2704         (detail::all(
2705              lib::array<bool, sizeof...(Vs)>{{!vs.valueless_by_exception()...}})
2706              ? (void)0
2707              : throw_bad_variant_access()),
2708         detail::visitation::variant::visit_value(lib::forward<Visitor>(visitor),
2709                                                  lib::forward<Vs>(vs)...))
2710 #endif
2711 
2712   template <typename... Ts>
2713   inline auto swap(variant<Ts...> &lhs,
2714                    variant<Ts...> &rhs) noexcept(noexcept(lhs.swap(rhs)))
2715       -> decltype(lhs.swap(rhs)) {
2716     lhs.swap(rhs);
2717   }
2718 
2719   namespace detail {
2720 
2721     template <typename T, typename...>
2722     using enabled_type = T;
2723 
2724     namespace hash {
2725 
2726       template <typename H, typename K>
meets_requirements()2727       constexpr bool meets_requirements() noexcept {
2728         return std::is_copy_constructible<H>::value &&
2729                std::is_move_constructible<H>::value &&
2730                lib::is_invocable_r<std::size_t, H, const K &>::value;
2731       }
2732 
2733       template <typename K>
is_enabled()2734       constexpr bool is_enabled() noexcept {
2735         using H = std::hash<K>;
2736         return meets_requirements<H, K>() &&
2737                std::is_default_constructible<H>::value &&
2738                std::is_copy_assignable<H>::value &&
2739                std::is_move_assignable<H>::value;
2740       }
2741 
2742     }  // namespace hash
2743 
2744   }  // namespace detail
2745 
2746 #undef AUTO
2747 #undef AUTO_RETURN
2748 
2749 #undef AUTO_REFREF
2750 #undef AUTO_REFREF_RETURN
2751 
2752 #undef DECLTYPE_AUTO
2753 #undef DECLTYPE_AUTO_RETURN
2754 
2755 }  // namespace mpark
2756 
2757 namespace std {
2758 
2759   template <typename... Ts>
2760   struct hash<mpark::detail::enabled_type<
2761       mpark::variant<Ts...>,
2762       mpark::lib::enable_if_t<mpark::lib::all<mpark::detail::hash::is_enabled<
2763           mpark::lib::remove_const_t<Ts>>()...>::value>>> {
2764     using argument_type = mpark::variant<Ts...>;
2765     using result_type = std::size_t;
2766 
2767     inline result_type operator()(const argument_type &v) const {
2768       using mpark::detail::visitation::variant;
2769       std::size_t result =
2770           v.valueless_by_exception()
2771               ? 299792458  // Random value chosen by the universe upon creation
2772               : variant::visit_alt(
2773 #ifdef MPARK_GENERIC_LAMBDAS
__anonc9c845e20502(const auto &alt) 2774                     [](const auto &alt) {
2775                       using alt_type = mpark::lib::decay_t<decltype(alt)>;
2776                       using value_type = mpark::lib::remove_const_t<
2777                           typename alt_type::value_type>;
2778                       return hash<value_type>{}(alt.value);
2779                     }
2780 #else
2781                     hasher{}
2782 #endif
2783                     ,
2784                     v);
2785       return hash_combine(result, hash<std::size_t>{}(v.index()));
2786     }
2787 
2788     private:
2789 #ifndef MPARK_GENERIC_LAMBDAS
2790     struct hasher {
2791       template <typename Alt>
2792       inline std::size_t operator()(const Alt &alt) const {
2793         using alt_type = mpark::lib::decay_t<Alt>;
2794         using value_type =
2795             mpark::lib::remove_const_t<typename alt_type::value_type>;
2796         return hash<value_type>{}(alt.value);
2797       }
2798     };
2799 #endif
2800 
2801     static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) {
2802       return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
2803     }
2804   };
2805 
2806   template <>
2807   struct hash<mpark::monostate> {
2808     using argument_type = mpark::monostate;
2809     using result_type = std::size_t;
2810 
operator ()std::hash2811     inline result_type operator()(const argument_type &) const noexcept {
2812       return 66740831;  // return a fundamentally attractive random value.
2813     }
2814   };
2815 
2816 }  // namespace std
2817 
2818 #endif  // MPARK_VARIANT_HPP
2819