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