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