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