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