blob: b0ea73de0767090e543addfa8067df18312e3257 [file] [log] [blame]
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001// -*- C++ -*-
2//===------------------------------ variant -------------------------------===//
3//
Chandler Carruthd2012102019-01-19 10:56:40 +00004// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Eric Fiselier94cdacc2016-12-02 23:00:05 +00007//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_VARIANT
11#define _LIBCPP_VARIANT
12
13/*
14 variant synopsis
15
16namespace std {
17
18 // 20.7.2, class template variant
19 template <class... Types>
20 class variant {
21 public:
22
23 // 20.7.2.1, constructors
24 constexpr variant() noexcept(see below);
Louis Dionnecee59012019-01-10 20:06:11 +000025 variant(const variant&); // constexpr in C++20
26 variant(variant&&) noexcept(see below); // constexpr in C++20
Eric Fiselier94cdacc2016-12-02 23:00:05 +000027
28 template <class T> constexpr variant(T&&) noexcept(see below);
29
30 template <class T, class... Args>
31 constexpr explicit variant(in_place_type_t<T>, Args&&...);
32
33 template <class T, class U, class... Args>
34 constexpr explicit variant(
35 in_place_type_t<T>, initializer_list<U>, Args&&...);
36
37 template <size_t I, class... Args>
38 constexpr explicit variant(in_place_index_t<I>, Args&&...);
39
40 template <size_t I, class U, class... Args>
41 constexpr explicit variant(
42 in_place_index_t<I>, initializer_list<U>, Args&&...);
43
44 // 20.7.2.2, destructor
45 ~variant();
46
47 // 20.7.2.3, assignment
Louis Dionnecee59012019-01-10 20:06:11 +000048 variant& operator=(const variant&); // constexpr in C++20
49 variant& operator=(variant&&) noexcept(see below); // constexpr in C++20
Eric Fiselier94cdacc2016-12-02 23:00:05 +000050
51 template <class T> variant& operator=(T&&) noexcept(see below);
52
53 // 20.7.2.4, modifiers
54 template <class T, class... Args>
Eric Fiselier62928442017-04-15 19:32:02 +000055 T& emplace(Args&&...);
Eric Fiselier94cdacc2016-12-02 23:00:05 +000056
57 template <class T, class U, class... Args>
Eric Fiselier62928442017-04-15 19:32:02 +000058 T& emplace(initializer_list<U>, Args&&...);
Eric Fiselier94cdacc2016-12-02 23:00:05 +000059
60 template <size_t I, class... Args>
Eric Fiselier62928442017-04-15 19:32:02 +000061 variant_alternative_t<I, variant>& emplace(Args&&...);
Eric Fiselier94cdacc2016-12-02 23:00:05 +000062
63 template <size_t I, class U, class... Args>
Eric Fiselier62928442017-04-15 19:32:02 +000064 variant_alternative_t<I, variant>& emplace(initializer_list<U>, Args&&...);
Eric Fiselier94cdacc2016-12-02 23:00:05 +000065
66 // 20.7.2.5, value status
67 constexpr bool valueless_by_exception() const noexcept;
68 constexpr size_t index() const noexcept;
69
70 // 20.7.2.6, swap
71 void swap(variant&) noexcept(see below);
72 };
73
74 // 20.7.3, variant helper classes
75 template <class T> struct variant_size; // undefined
76
77 template <class T>
Marshall Clowf1bf62f2018-01-02 17:17:01 +000078 inline constexpr size_t variant_size_v = variant_size<T>::value;
Eric Fiselier94cdacc2016-12-02 23:00:05 +000079
80 template <class T> struct variant_size<const T>;
81 template <class T> struct variant_size<volatile T>;
82 template <class T> struct variant_size<const volatile T>;
83
84 template <class... Types>
85 struct variant_size<variant<Types...>>;
86
87 template <size_t I, class T> struct variant_alternative; // undefined
88
89 template <size_t I, class T>
90 using variant_alternative_t = typename variant_alternative<I, T>::type;
91
92 template <size_t I, class T> struct variant_alternative<I, const T>;
93 template <size_t I, class T> struct variant_alternative<I, volatile T>;
94 template <size_t I, class T> struct variant_alternative<I, const volatile T>;
95
96 template <size_t I, class... Types>
97 struct variant_alternative<I, variant<Types...>>;
98
Marshall Clowf1bf62f2018-01-02 17:17:01 +000099 inline constexpr size_t variant_npos = -1;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000100
101 // 20.7.4, value access
102 template <class T, class... Types>
103 constexpr bool holds_alternative(const variant<Types...>&) noexcept;
104
105 template <size_t I, class... Types>
106 constexpr variant_alternative_t<I, variant<Types...>>&
107 get(variant<Types...>&);
108
109 template <size_t I, class... Types>
110 constexpr variant_alternative_t<I, variant<Types...>>&&
111 get(variant<Types...>&&);
112
113 template <size_t I, class... Types>
114 constexpr variant_alternative_t<I, variant<Types...>> const&
115 get(const variant<Types...>&);
116
117 template <size_t I, class... Types>
118 constexpr variant_alternative_t<I, variant<Types...>> const&&
119 get(const variant<Types...>&&);
120
121 template <class T, class... Types>
122 constexpr T& get(variant<Types...>&);
123
124 template <class T, class... Types>
125 constexpr T&& get(variant<Types...>&&);
126
127 template <class T, class... Types>
128 constexpr const T& get(const variant<Types...>&);
129
130 template <class T, class... Types>
131 constexpr const T&& get(const variant<Types...>&&);
132
133 template <size_t I, class... Types>
134 constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>>
135 get_if(variant<Types...>*) noexcept;
136
137 template <size_t I, class... Types>
138 constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
139 get_if(const variant<Types...>*) noexcept;
140
141 template <class T, class... Types>
142 constexpr add_pointer_t<T>
143 get_if(variant<Types...>*) noexcept;
144
145 template <class T, class... Types>
146 constexpr add_pointer_t<const T>
147 get_if(const variant<Types...>*) noexcept;
148
149 // 20.7.5, relational operators
150 template <class... Types>
151 constexpr bool operator==(const variant<Types...>&, const variant<Types...>&);
152
153 template <class... Types>
154 constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&);
155
156 template <class... Types>
157 constexpr bool operator<(const variant<Types...>&, const variant<Types...>&);
158
159 template <class... Types>
160 constexpr bool operator>(const variant<Types...>&, const variant<Types...>&);
161
162 template <class... Types>
163 constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&);
164
165 template <class... Types>
166 constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&);
167
168 // 20.7.6, visitation
169 template <class Visitor, class... Variants>
170 constexpr see below visit(Visitor&&, Variants&&...);
171
Ruslan Arutyunyan33f34732021-01-25 11:12:25 -0500172 template <class R, class Visitor, class... Variants>
173 constexpr R visit(Visitor&&, Variants&&...); // since C++20
174
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000175 // 20.7.7, class monostate
176 struct monostate;
177
178 // 20.7.8, monostate relational operators
179 constexpr bool operator<(monostate, monostate) noexcept;
180 constexpr bool operator>(monostate, monostate) noexcept;
181 constexpr bool operator<=(monostate, monostate) noexcept;
182 constexpr bool operator>=(monostate, monostate) noexcept;
183 constexpr bool operator==(monostate, monostate) noexcept;
184 constexpr bool operator!=(monostate, monostate) noexcept;
185
186 // 20.7.9, specialized algorithms
187 template <class... Types>
188 void swap(variant<Types...>&, variant<Types...>&) noexcept(see below);
189
190 // 20.7.10, class bad_variant_access
191 class bad_variant_access;
192
193 // 20.7.11, hash support
194 template <class T> struct hash;
195 template <class... Types> struct hash<variant<Types...>>;
196 template <> struct hash<monostate>;
197
198} // namespace std
199
200*/
201
Louis Dionne73912b22020-11-04 15:01:25 -0500202#include <__availability>
Arthur O'Dwyeref181602021-05-19 11:57:04 -0400203#include <__config>
zoecarver6eb71a92021-05-27 09:23:19 -0700204#include <__functional/hash.h>
205#include <__tuple>
Christopher Di Bella41f26e82021-06-05 02:47:47 +0000206#include <__utility/forward.h>
Mark de Wever3b269752021-07-07 21:27:27 +0200207#include <__variant/monostate.h>
Arthur O'Dwyer7deec122021-03-24 18:19:12 -0400208#include <compare>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000209#include <exception>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000210#include <initializer_list>
Arthur O'Dwyeref181602021-05-19 11:57:04 -0400211#include <limits>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000212#include <new>
213#include <tuple>
214#include <type_traits>
215#include <utility>
Marshall Clow0a1e7502018-09-12 19:41:40 +0000216#include <version>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000217
218#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
219#pragma GCC system_header
220#endif
221
Eric Fiselier8625d332017-11-19 04:57:22 +0000222_LIBCPP_PUSH_MACROS
223#include <__undef_macros>
224
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000225namespace std { // explicitly not using versioning namespace
226
Louis Dionnecef92e62018-11-19 15:37:04 +0000227class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS bad_variant_access : public exception {
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000228public:
Saleem Abdulrasool5ee83382016-12-31 17:34:26 +0000229 virtual const char* what() const _NOEXCEPT;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000230};
231
232} // namespace std
233
234_LIBCPP_BEGIN_NAMESPACE_STD
235
Louis Dionne7202cd62020-07-22 15:24:16 -0400236// TODO: GCC 5 lies about its support for C++17 (it says it supports it but it
237// really doesn't). That breaks variant, which uses some C++17 features.
238// Remove this once we drop support for GCC 5.
Louis Dionne129391d2020-07-22 15:59:09 -0400239#if _LIBCPP_STD_VER > 14 && !(defined(_LIBCPP_COMPILER_GCC) && _GNUC_VER_NEW < 6000)
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000240
zoecarver647e31c2021-07-07 15:25:53 -0700241// Light N-dimensional array of function pointers. Used in place of std::array to avoid
242// adding a dependency.
243template<class _Tp, size_t _Size>
244struct __farray {
245 static_assert(_Size > 0, "N-dimensional array should never be empty in std::visit");
246 _Tp __buf_[_Size] = {};
247
248 _LIBCPP_INLINE_VISIBILITY constexpr
249 const _Tp &operator[](size_t __n) const noexcept {
250 return __buf_[__n];
251 }
252};
253
Eric Fiselier10642ea2016-12-03 01:58:07 +0000254_LIBCPP_NORETURN
255inline _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000256_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
Eric Fiselier10642ea2016-12-03 01:58:07 +0000257void __throw_bad_variant_access() {
258#ifndef _LIBCPP_NO_EXCEPTIONS
259 throw bad_variant_access();
260#else
261 _VSTD::abort();
262#endif
263}
264
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000265template <class... _Types>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000266class _LIBCPP_TEMPLATE_VIS variant;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000267
268template <class _Tp>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000269struct _LIBCPP_TEMPLATE_VIS variant_size;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000270
271template <class _Tp>
Marshall Clowf1bf62f2018-01-02 17:17:01 +0000272_LIBCPP_INLINE_VAR constexpr size_t variant_size_v = variant_size<_Tp>::value;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000273
274template <class _Tp>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000275struct _LIBCPP_TEMPLATE_VIS variant_size<const _Tp> : variant_size<_Tp> {};
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000276
277template <class _Tp>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000278struct _LIBCPP_TEMPLATE_VIS variant_size<volatile _Tp> : variant_size<_Tp> {};
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000279
280template <class _Tp>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000281struct _LIBCPP_TEMPLATE_VIS variant_size<const volatile _Tp>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000282 : variant_size<_Tp> {};
283
284template <class... _Types>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000285struct _LIBCPP_TEMPLATE_VIS variant_size<variant<_Types...>>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000286 : integral_constant<size_t, sizeof...(_Types)> {};
287
288template <size_t _Ip, class _Tp>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000289struct _LIBCPP_TEMPLATE_VIS variant_alternative;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000290
291template <size_t _Ip, class _Tp>
292using variant_alternative_t = typename variant_alternative<_Ip, _Tp>::type;
293
294template <size_t _Ip, class _Tp>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000295struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, const _Tp>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000296 : add_const<variant_alternative_t<_Ip, _Tp>> {};
297
298template <size_t _Ip, class _Tp>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000299struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, volatile _Tp>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000300 : add_volatile<variant_alternative_t<_Ip, _Tp>> {};
301
302template <size_t _Ip, class _Tp>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000303struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, const volatile _Tp>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000304 : add_cv<variant_alternative_t<_Ip, _Tp>> {};
305
306template <size_t _Ip, class... _Types>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000307struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, variant<_Types...>> {
Marshall Clow185577f2017-06-12 16:13:17 +0000308 static_assert(_Ip < sizeof...(_Types), "Index out of bounds in std::variant_alternative<>");
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000309 using type = __type_pack_element<_Ip, _Types...>;
310};
311
Marshall Clowf1bf62f2018-01-02 17:17:01 +0000312_LIBCPP_INLINE_VAR constexpr size_t variant_npos = static_cast<size_t>(-1);
Eric Fiseliercaccc7b2017-11-19 04:19:44 +0000313
314constexpr int __choose_index_type(unsigned int __num_elem) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -0500315 if (__num_elem < numeric_limits<unsigned char>::max())
Eric Fiseliercaccc7b2017-11-19 04:19:44 +0000316 return 0;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -0500317 if (__num_elem < numeric_limits<unsigned short>::max())
Eric Fiseliercaccc7b2017-11-19 04:19:44 +0000318 return 1;
319 return 2;
320}
321
322template <size_t _NumAlts>
323using __variant_index_t =
324#ifndef _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION
325 unsigned int;
326#else
327 std::tuple_element_t<
328 __choose_index_type(_NumAlts),
329 std::tuple<unsigned char, unsigned short, unsigned int>
330 >;
331#endif
332
333template <class _IndexType>
334constexpr _IndexType __variant_npos = static_cast<_IndexType>(-1);
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000335
Marek Kurdej2f5ec002021-03-25 18:09:11 +0100336template <class... _Types>
337class _LIBCPP_TEMPLATE_VIS variant;
338
339template <class... _Types>
340_LIBCPP_INLINE_VISIBILITY constexpr variant<_Types...>&
341__as_variant(variant<_Types...>& __vs) noexcept {
342 return __vs;
343}
344
345template <class... _Types>
346_LIBCPP_INLINE_VISIBILITY constexpr const variant<_Types...>&
347__as_variant(const variant<_Types...>& __vs) noexcept {
348 return __vs;
349}
350
351template <class... _Types>
352_LIBCPP_INLINE_VISIBILITY constexpr variant<_Types...>&&
353__as_variant(variant<_Types...>&& __vs) noexcept {
354 return _VSTD::move(__vs);
355}
356
357template <class... _Types>
358_LIBCPP_INLINE_VISIBILITY constexpr const variant<_Types...>&&
359__as_variant(const variant<_Types...>&& __vs) noexcept {
360 return _VSTD::move(__vs);
361}
362
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000363namespace __find_detail {
364
365template <class _Tp, class... _Types>
366inline _LIBCPP_INLINE_VISIBILITY
367constexpr size_t __find_index() {
368 constexpr bool __matches[] = {is_same_v<_Tp, _Types>...};
369 size_t __result = __not_found;
370 for (size_t __i = 0; __i < sizeof...(_Types); ++__i) {
371 if (__matches[__i]) {
372 if (__result != __not_found) {
373 return __ambiguous;
374 }
375 __result = __i;
376 }
377 }
378 return __result;
379}
380
381template <size_t _Index>
382struct __find_unambiguous_index_sfinae_impl
383 : integral_constant<size_t, _Index> {};
384
385template <>
386struct __find_unambiguous_index_sfinae_impl<__not_found> {};
387
388template <>
389struct __find_unambiguous_index_sfinae_impl<__ambiguous> {};
390
391template <class _Tp, class... _Types>
392struct __find_unambiguous_index_sfinae
393 : __find_unambiguous_index_sfinae_impl<__find_index<_Tp, _Types...>()> {};
394
395} // namespace __find_detail
396
397namespace __variant_detail {
398
399struct __valueless_t {};
400
401enum class _Trait { _TriviallyAvailable, _Available, _Unavailable };
402
Eric Fiselier87994112020-11-17 17:34:23 -0500403template <typename _Tp,
404 template <typename> class _IsTriviallyAvailable,
405 template <typename> class _IsAvailable>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000406constexpr _Trait __trait =
407 _IsTriviallyAvailable<_Tp>::value
408 ? _Trait::_TriviallyAvailable
409 : _IsAvailable<_Tp>::value ? _Trait::_Available : _Trait::_Unavailable;
410
411inline _LIBCPP_INLINE_VISIBILITY
412constexpr _Trait __common_trait(initializer_list<_Trait> __traits) {
413 _Trait __result = _Trait::_TriviallyAvailable;
414 for (_Trait __t : __traits) {
415 if (static_cast<int>(__t) > static_cast<int>(__result)) {
416 __result = __t;
417 }
418 }
419 return __result;
420}
421
Eric Fiselier87994112020-11-17 17:34:23 -0500422template <typename... _Types>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000423struct __traits {
424 static constexpr _Trait __copy_constructible_trait =
425 __common_trait({__trait<_Types,
426 is_trivially_copy_constructible,
427 is_copy_constructible>...});
428
429 static constexpr _Trait __move_constructible_trait =
430 __common_trait({__trait<_Types,
431 is_trivially_move_constructible,
432 is_move_constructible>...});
433
434 static constexpr _Trait __copy_assignable_trait = __common_trait(
435 {__copy_constructible_trait,
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000436 __trait<_Types, is_trivially_copy_assignable, is_copy_assignable>...});
437
438 static constexpr _Trait __move_assignable_trait = __common_trait(
439 {__move_constructible_trait,
440 __trait<_Types, is_trivially_move_assignable, is_move_assignable>...});
441
442 static constexpr _Trait __destructible_trait = __common_trait(
443 {__trait<_Types, is_trivially_destructible, is_destructible>...});
444};
445
446namespace __access {
447
448struct __union {
449 template <class _Vp>
450 inline _LIBCPP_INLINE_VISIBILITY
451 static constexpr auto&& __get_alt(_Vp&& __v, in_place_index_t<0>) {
452 return _VSTD::forward<_Vp>(__v).__head;
453 }
454
455 template <class _Vp, size_t _Ip>
456 inline _LIBCPP_INLINE_VISIBILITY
457 static constexpr auto&& __get_alt(_Vp&& __v, in_place_index_t<_Ip>) {
458 return __get_alt(_VSTD::forward<_Vp>(__v).__tail, in_place_index<_Ip - 1>);
459 }
460};
461
462struct __base {
463 template <size_t _Ip, class _Vp>
464 inline _LIBCPP_INLINE_VISIBILITY
465 static constexpr auto&& __get_alt(_Vp&& __v) {
466 return __union::__get_alt(_VSTD::forward<_Vp>(__v).__data,
467 in_place_index<_Ip>);
468 }
469};
470
471struct __variant {
472 template <size_t _Ip, class _Vp>
473 inline _LIBCPP_INLINE_VISIBILITY
474 static constexpr auto&& __get_alt(_Vp&& __v) {
475 return __base::__get_alt<_Ip>(_VSTD::forward<_Vp>(__v).__impl);
476 }
477};
478
479} // namespace __access
480
481namespace __visitation {
482
483struct __base {
Eric Fiselier87994112020-11-17 17:34:23 -0500484 template <class _Visitor, class... _Vs>
485 inline _LIBCPP_INLINE_VISIBILITY
486 static constexpr decltype(auto)
487 __visit_alt_at(size_t __index, _Visitor&& __visitor, _Vs&&... __vs) {
488 constexpr auto __fdiagonal =
489 __make_fdiagonal<_Visitor&&,
490 decltype(_VSTD::forward<_Vs>(__vs).__as_base())...>();
491 return __fdiagonal[__index](_VSTD::forward<_Visitor>(__visitor),
492 _VSTD::forward<_Vs>(__vs).__as_base()...);
493 }
494
495 template <class _Visitor, class... _Vs>
496 inline _LIBCPP_INLINE_VISIBILITY
497 static constexpr decltype(auto) __visit_alt(_Visitor&& __visitor,
498 _Vs&&... __vs) {
499 constexpr auto __fmatrix =
500 __make_fmatrix<_Visitor&&,
501 decltype(_VSTD::forward<_Vs>(__vs).__as_base())...>();
502 return __at(__fmatrix, __vs.index()...)(
503 _VSTD::forward<_Visitor>(__visitor),
504 _VSTD::forward<_Vs>(__vs).__as_base()...);
505 }
506
507private:
508 template <class _Tp>
509 inline _LIBCPP_INLINE_VISIBILITY
510 static constexpr const _Tp& __at(const _Tp& __elem) { return __elem; }
511
512 template <class _Tp, size_t _Np, typename... _Indices>
513 inline _LIBCPP_INLINE_VISIBILITY
zoecarver647e31c2021-07-07 15:25:53 -0700514 static constexpr auto&& __at(const __farray<_Tp, _Np>& __elems,
Eric Fiselier87994112020-11-17 17:34:23 -0500515 size_t __index, _Indices... __indices) {
516 return __at(__elems[__index], __indices...);
517 }
518
519 template <class _Fp, class... _Fs>
520 static constexpr void __std_visit_visitor_return_type_check() {
521 static_assert(
522 __all<is_same_v<_Fp, _Fs>...>::value,
523 "`std::visit` requires the visitor to have a single return type.");
524 }
525
526 template <class... _Fs>
527 inline _LIBCPP_INLINE_VISIBILITY
528 static constexpr auto __make_farray(_Fs&&... __fs) {
529 __std_visit_visitor_return_type_check<__uncvref_t<_Fs>...>();
zoecarver647e31c2021-07-07 15:25:53 -0700530 using __result = __farray<common_type_t<__uncvref_t<_Fs>...>, sizeof...(_Fs)>;
Eric Fiselier87994112020-11-17 17:34:23 -0500531 return __result{{_VSTD::forward<_Fs>(__fs)...}};
532 }
533
Arthur O'Dwyer07b22492020-11-27 11:02:06 -0500534 template <size_t... _Is>
Eric Fiselier87994112020-11-17 17:34:23 -0500535 struct __dispatcher {
536 template <class _Fp, class... _Vs>
Michael Park32334da2020-08-30 12:42:35 -0400537 inline _LIBCPP_INLINE_VISIBILITY
Eric Fiselier87994112020-11-17 17:34:23 -0500538 static constexpr decltype(auto) __dispatch(_Fp __f, _Vs... __vs) {
Arthur O'Dwyerf0bff152020-11-24 09:59:26 -0500539 return _VSTD::__invoke_constexpr(
Eric Fiselier87994112020-11-17 17:34:23 -0500540 static_cast<_Fp>(__f),
541 __access::__base::__get_alt<_Is>(static_cast<_Vs>(__vs))...);
Michael Park32334da2020-08-30 12:42:35 -0400542 }
543 };
544
Eric Fiselier87994112020-11-17 17:34:23 -0500545 template <class _Fp, class... _Vs, size_t... _Is>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000546 inline _LIBCPP_INLINE_VISIBILITY
Eric Fiselier87994112020-11-17 17:34:23 -0500547 static constexpr auto __make_dispatch(index_sequence<_Is...>) {
548 return __dispatcher<_Is...>::template __dispatch<_Fp, _Vs...>;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000549 }
550
Eric Fiselier87994112020-11-17 17:34:23 -0500551 template <size_t _Ip, class _Fp, class... _Vs>
552 inline _LIBCPP_INLINE_VISIBILITY
553 static constexpr auto __make_fdiagonal_impl() {
554 return __make_dispatch<_Fp, _Vs...>(
555 index_sequence<(__identity<_Vs>{}, _Ip)...>{});
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000556 }
Eric Fiselier87994112020-11-17 17:34:23 -0500557
558 template <class _Fp, class... _Vs, size_t... _Is>
559 inline _LIBCPP_INLINE_VISIBILITY
560 static constexpr auto __make_fdiagonal_impl(index_sequence<_Is...>) {
561 return __base::__make_farray(__make_fdiagonal_impl<_Is, _Fp, _Vs...>()...);
562 }
563
564 template <class _Fp, class _Vp, class... _Vs>
565 inline _LIBCPP_INLINE_VISIBILITY
566 static constexpr auto __make_fdiagonal() {
567 constexpr size_t _Np = __uncvref_t<_Vp>::__size();
568 static_assert(__all<(_Np == __uncvref_t<_Vs>::__size())...>::value);
569 return __make_fdiagonal_impl<_Fp, _Vp, _Vs...>(make_index_sequence<_Np>{});
570 }
571
572 template <class _Fp, class... _Vs, size_t... _Is>
573 inline _LIBCPP_INLINE_VISIBILITY
574 static constexpr auto __make_fmatrix_impl(index_sequence<_Is...> __is) {
575 return __make_dispatch<_Fp, _Vs...>(__is);
576 }
577
578 template <class _Fp, class... _Vs, size_t... _Is, size_t... _Js, class... _Ls>
579 inline _LIBCPP_INLINE_VISIBILITY
580 static constexpr auto __make_fmatrix_impl(index_sequence<_Is...>,
581 index_sequence<_Js...>,
582 _Ls... __ls) {
583 return __base::__make_farray(__make_fmatrix_impl<_Fp, _Vs...>(
584 index_sequence<_Is..., _Js>{}, __ls...)...);
585 }
586
587 template <class _Fp, class... _Vs>
588 inline _LIBCPP_INLINE_VISIBILITY
589 static constexpr auto __make_fmatrix() {
590 return __make_fmatrix_impl<_Fp, _Vs...>(
591 index_sequence<>{}, make_index_sequence<__uncvref_t<_Vs>::__size()>{}...);
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000592 }
593};
594
595struct __variant {
Eric Fiselier87994112020-11-17 17:34:23 -0500596 template <class _Visitor, class... _Vs>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000597 inline _LIBCPP_INLINE_VISIBILITY
598 static constexpr decltype(auto)
Eric Fiselier87994112020-11-17 17:34:23 -0500599 __visit_alt_at(size_t __index, _Visitor&& __visitor, _Vs&&... __vs) {
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000600 return __base::__visit_alt_at(__index,
Eric Fiselier87994112020-11-17 17:34:23 -0500601 _VSTD::forward<_Visitor>(__visitor),
602 _VSTD::forward<_Vs>(__vs).__impl...);
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000603 }
604
Eric Fiselier87994112020-11-17 17:34:23 -0500605 template <class _Visitor, class... _Vs>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000606 inline _LIBCPP_INLINE_VISIBILITY
Eric Fiselier87994112020-11-17 17:34:23 -0500607 static constexpr decltype(auto) __visit_alt(_Visitor&& __visitor,
608 _Vs&&... __vs) {
Marek Kurdej2f5ec002021-03-25 18:09:11 +0100609 return __base::__visit_alt(
610 _VSTD::forward<_Visitor>(__visitor),
611 _VSTD::__as_variant(_VSTD::forward<_Vs>(__vs)).__impl...);
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000612 }
613
Eric Fiselier87994112020-11-17 17:34:23 -0500614 template <class _Visitor, class... _Vs>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000615 inline _LIBCPP_INLINE_VISIBILITY
616 static constexpr decltype(auto)
Eric Fiselier87994112020-11-17 17:34:23 -0500617 __visit_value_at(size_t __index, _Visitor&& __visitor, _Vs&&... __vs) {
618 return __visit_alt_at(
619 __index,
620 __make_value_visitor(_VSTD::forward<_Visitor>(__visitor)),
621 _VSTD::forward<_Vs>(__vs)...);
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000622 }
623
Eric Fiselier87994112020-11-17 17:34:23 -0500624 template <class _Visitor, class... _Vs>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000625 inline _LIBCPP_INLINE_VISIBILITY
Eric Fiselier87994112020-11-17 17:34:23 -0500626 static constexpr decltype(auto) __visit_value(_Visitor&& __visitor,
627 _Vs&&... __vs) {
628 return __visit_alt(
629 __make_value_visitor(_VSTD::forward<_Visitor>(__visitor)),
630 _VSTD::forward<_Vs>(__vs)...);
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000631 }
Marek Kurdej2f5ec002021-03-25 18:09:11 +0100632
Ruslan Arutyunyan33f34732021-01-25 11:12:25 -0500633#if _LIBCPP_STD_VER > 17
634 template <class _Rp, class _Visitor, class... _Vs>
635 inline _LIBCPP_INLINE_VISIBILITY
636 static constexpr _Rp __visit_value(_Visitor&& __visitor,
637 _Vs&&... __vs) {
638 return __visit_alt(
639 __make_value_visitor<_Rp>(_VSTD::forward<_Visitor>(__visitor)),
640 _VSTD::forward<_Vs>(__vs)...);
641 }
642#endif
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000643
644private:
Eric Fiselier87994112020-11-17 17:34:23 -0500645 template <class _Visitor, class... _Values>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000646 static constexpr void __std_visit_exhaustive_visitor_check() {
Eric Fiselier87994112020-11-17 17:34:23 -0500647 static_assert(is_invocable_v<_Visitor, _Values...>,
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000648 "`std::visit` requires the visitor to be exhaustive.");
649 }
650
Eric Fiselier87994112020-11-17 17:34:23 -0500651 template <class _Visitor>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000652 struct __value_visitor {
653 template <class... _Alts>
654 inline _LIBCPP_INLINE_VISIBILITY
655 constexpr decltype(auto) operator()(_Alts&&... __alts) const {
656 __std_visit_exhaustive_visitor_check<
Eric Fiselier87994112020-11-17 17:34:23 -0500657 _Visitor,
658 decltype((_VSTD::forward<_Alts>(__alts).__value))...>();
Arthur O'Dwyerf0bff152020-11-24 09:59:26 -0500659 return _VSTD::__invoke_constexpr(_VSTD::forward<_Visitor>(__visitor),
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000660 _VSTD::forward<_Alts>(__alts).__value...);
661 }
Eric Fiselier87994112020-11-17 17:34:23 -0500662 _Visitor&& __visitor;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000663 };
664
Ruslan Arutyunyan33f34732021-01-25 11:12:25 -0500665#if _LIBCPP_STD_VER > 17
666 template <class _Rp, class _Visitor>
667 struct __value_visitor_return_type {
668 template <class... _Alts>
669 inline _LIBCPP_INLINE_VISIBILITY
670 constexpr _Rp operator()(_Alts&&... __alts) const {
671 __std_visit_exhaustive_visitor_check<
672 _Visitor,
673 decltype((_VSTD::forward<_Alts>(__alts).__value))...>();
674 if constexpr (is_void_v<_Rp>) {
675 _VSTD::__invoke_constexpr(_VSTD::forward<_Visitor>(__visitor),
676 _VSTD::forward<_Alts>(__alts).__value...);
677 }
678 else {
679 return _VSTD::__invoke_constexpr(_VSTD::forward<_Visitor>(__visitor),
680 _VSTD::forward<_Alts>(__alts).__value...);
681 }
682 }
683
684 _Visitor&& __visitor;
685 };
686#endif
687
Eric Fiselier87994112020-11-17 17:34:23 -0500688 template <class _Visitor>
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000689 inline _LIBCPP_INLINE_VISIBILITY
Eric Fiselier87994112020-11-17 17:34:23 -0500690 static constexpr auto __make_value_visitor(_Visitor&& __visitor) {
691 return __value_visitor<_Visitor>{_VSTD::forward<_Visitor>(__visitor)};
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000692 }
Ruslan Arutyunyan33f34732021-01-25 11:12:25 -0500693
694#if _LIBCPP_STD_VER > 17
695 template <class _Rp, class _Visitor>
696 inline _LIBCPP_INLINE_VISIBILITY
697 static constexpr auto __make_value_visitor(_Visitor&& __visitor) {
698 return __value_visitor_return_type<_Rp, _Visitor>{_VSTD::forward<_Visitor>(__visitor)};
699 }
Ruslan Arutyunyan33f34732021-01-25 11:12:25 -0500700#endif
Nico Weber8aa36612021-01-25 15:10:41 -0500701};
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000702
703} // namespace __visitation
704
705template <size_t _Index, class _Tp>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000706struct _LIBCPP_TEMPLATE_VIS __alt {
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000707 using __value_type = _Tp;
708
709 template <class... _Args>
710 inline _LIBCPP_INLINE_VISIBILITY
711 explicit constexpr __alt(in_place_t, _Args&&... __args)
712 : __value(_VSTD::forward<_Args>(__args)...) {}
713
714 __value_type __value;
715};
716
717template <_Trait _DestructibleTrait, size_t _Index, class... _Types>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000718union _LIBCPP_TEMPLATE_VIS __union;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000719
720template <_Trait _DestructibleTrait, size_t _Index>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000721union _LIBCPP_TEMPLATE_VIS __union<_DestructibleTrait, _Index> {};
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000722
723#define _LIBCPP_VARIANT_UNION(destructible_trait, destructor) \
724 template <size_t _Index, class _Tp, class... _Types> \
Eric Fiselier87994112020-11-17 17:34:23 -0500725 union _LIBCPP_TEMPLATE_VIS __union<destructible_trait, \
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000726 _Index, \
727 _Tp, \
728 _Types...> { \
729 public: \
730 inline _LIBCPP_INLINE_VISIBILITY \
731 explicit constexpr __union(__valueless_t) noexcept : __dummy{} {} \
732 \
733 template <class... _Args> \
734 inline _LIBCPP_INLINE_VISIBILITY \
735 explicit constexpr __union(in_place_index_t<0>, _Args&&... __args) \
736 : __head(in_place, _VSTD::forward<_Args>(__args)...) {} \
737 \
738 template <size_t _Ip, class... _Args> \
739 inline _LIBCPP_INLINE_VISIBILITY \
740 explicit constexpr __union(in_place_index_t<_Ip>, _Args&&... __args) \
741 : __tail(in_place_index<_Ip - 1>, _VSTD::forward<_Args>(__args)...) {} \
742 \
743 __union(const __union&) = default; \
744 __union(__union&&) = default; \
745 \
746 destructor \
747 \
748 __union& operator=(const __union&) = default; \
749 __union& operator=(__union&&) = default; \
750 \
751 private: \
752 char __dummy; \
753 __alt<_Index, _Tp> __head; \
754 __union<destructible_trait, _Index + 1, _Types...> __tail; \
755 \
756 friend struct __access::__union; \
757 }
758
759_LIBCPP_VARIANT_UNION(_Trait::_TriviallyAvailable, ~__union() = default;);
760_LIBCPP_VARIANT_UNION(_Trait::_Available, ~__union() {});
761_LIBCPP_VARIANT_UNION(_Trait::_Unavailable, ~__union() = delete;);
762
763#undef _LIBCPP_VARIANT_UNION
764
765template <_Trait _DestructibleTrait, class... _Types>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000766class _LIBCPP_TEMPLATE_VIS __base {
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000767public:
Eric Fiseliercaccc7b2017-11-19 04:19:44 +0000768 using __index_t = __variant_index_t<sizeof...(_Types)>;
769
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000770 inline _LIBCPP_INLINE_VISIBILITY
771 explicit constexpr __base(__valueless_t tag) noexcept
Eric Fiseliercaccc7b2017-11-19 04:19:44 +0000772 : __data(tag), __index(__variant_npos<__index_t>) {}
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000773
774 template <size_t _Ip, class... _Args>
775 inline _LIBCPP_INLINE_VISIBILITY
776 explicit constexpr __base(in_place_index_t<_Ip>, _Args&&... __args)
Eric Fiselier2adf0872016-12-02 23:17:33 +0000777 :
778 __data(in_place_index<_Ip>, _VSTD::forward<_Args>(__args)...),
779 __index(_Ip) {}
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000780
781 inline _LIBCPP_INLINE_VISIBILITY
782 constexpr bool valueless_by_exception() const noexcept {
783 return index() == variant_npos;
784 }
785
786 inline _LIBCPP_INLINE_VISIBILITY
787 constexpr size_t index() const noexcept {
Eric Fiseliercaccc7b2017-11-19 04:19:44 +0000788 return __index == __variant_npos<__index_t> ? variant_npos : __index;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000789 }
790
791protected:
792 inline _LIBCPP_INLINE_VISIBILITY
793 constexpr auto&& __as_base() & { return *this; }
794
795 inline _LIBCPP_INLINE_VISIBILITY
796 constexpr auto&& __as_base() && { return _VSTD::move(*this); }
797
798 inline _LIBCPP_INLINE_VISIBILITY
799 constexpr auto&& __as_base() const & { return *this; }
800
801 inline _LIBCPP_INLINE_VISIBILITY
802 constexpr auto&& __as_base() const && { return _VSTD::move(*this); }
803
804 inline _LIBCPP_INLINE_VISIBILITY
805 static constexpr size_t __size() { return sizeof...(_Types); }
806
807 __union<_DestructibleTrait, 0, _Types...> __data;
Eric Fiseliercaccc7b2017-11-19 04:19:44 +0000808 __index_t __index;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000809
810 friend struct __access::__base;
811 friend struct __visitation::__base;
812};
813
814template <class _Traits, _Trait = _Traits::__destructible_trait>
Louis Dionneff05add2020-10-05 16:30:23 -0400815class _LIBCPP_TEMPLATE_VIS __dtor;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000816
817#define _LIBCPP_VARIANT_DESTRUCTOR(destructible_trait, destructor, destroy) \
818 template <class... _Types> \
Louis Dionneff05add2020-10-05 16:30:23 -0400819 class _LIBCPP_TEMPLATE_VIS __dtor<__traits<_Types...>, \
820 destructible_trait> \
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000821 : public __base<destructible_trait, _Types...> { \
822 using __base_type = __base<destructible_trait, _Types...>; \
Eric Fiseliercaccc7b2017-11-19 04:19:44 +0000823 using __index_t = typename __base_type::__index_t; \
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000824 \
825 public: \
826 using __base_type::__base_type; \
827 using __base_type::operator=; \
828 \
Louis Dionneff05add2020-10-05 16:30:23 -0400829 __dtor(const __dtor&) = default; \
830 __dtor(__dtor&&) = default; \
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000831 destructor \
Louis Dionneff05add2020-10-05 16:30:23 -0400832 __dtor& operator=(const __dtor&) = default; \
833 __dtor& operator=(__dtor&&) = default; \
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000834 \
835 protected: \
836 inline _LIBCPP_INLINE_VISIBILITY \
837 destroy \
838 }
839
840_LIBCPP_VARIANT_DESTRUCTOR(
841 _Trait::_TriviallyAvailable,
Louis Dionneff05add2020-10-05 16:30:23 -0400842 ~__dtor() = default;,
Eric Fiseliercaccc7b2017-11-19 04:19:44 +0000843 void __destroy() noexcept { this->__index = __variant_npos<__index_t>; });
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000844
845_LIBCPP_VARIANT_DESTRUCTOR(
846 _Trait::_Available,
Louis Dionneff05add2020-10-05 16:30:23 -0400847 ~__dtor() { __destroy(); },
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000848 void __destroy() noexcept {
849 if (!this->valueless_by_exception()) {
850 __visitation::__base::__visit_alt(
851 [](auto& __alt) noexcept {
Marshall Clowe61ba952018-02-12 15:41:25 +0000852 using __alt_type = __uncvref_t<decltype(__alt)>;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000853 __alt.~__alt_type();
854 },
855 *this);
856 }
Eric Fiseliercaccc7b2017-11-19 04:19:44 +0000857 this->__index = __variant_npos<__index_t>;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000858 });
859
860_LIBCPP_VARIANT_DESTRUCTOR(
861 _Trait::_Unavailable,
Louis Dionneff05add2020-10-05 16:30:23 -0400862 ~__dtor() = delete;,
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000863 void __destroy() noexcept = delete;);
864
865#undef _LIBCPP_VARIANT_DESTRUCTOR
866
867template <class _Traits>
Louis Dionneff05add2020-10-05 16:30:23 -0400868class _LIBCPP_TEMPLATE_VIS __ctor : public __dtor<_Traits> {
869 using __base_type = __dtor<_Traits>;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000870
871public:
872 using __base_type::__base_type;
873 using __base_type::operator=;
874
875protected:
876 template <size_t _Ip, class _Tp, class... _Args>
877 inline _LIBCPP_INLINE_VISIBILITY
Eric Fiselier62928442017-04-15 19:32:02 +0000878 static _Tp& __construct_alt(__alt<_Ip, _Tp>& __a, _Args&&... __args) {
Eric Fiselier87994112020-11-17 17:34:23 -0500879 ::new ((void*)_VSTD::addressof(__a))
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000880 __alt<_Ip, _Tp>(in_place, _VSTD::forward<_Args>(__args)...);
Eric Fiselier87994112020-11-17 17:34:23 -0500881 return __a.__value;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000882 }
883
884 template <class _Rhs>
885 inline _LIBCPP_INLINE_VISIBILITY
Louis Dionneff05add2020-10-05 16:30:23 -0400886 static void __generic_construct(__ctor& __lhs, _Rhs&& __rhs) {
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000887 __lhs.__destroy();
888 if (!__rhs.valueless_by_exception()) {
889 __visitation::__base::__visit_alt_at(
890 __rhs.index(),
891 [](auto& __lhs_alt, auto&& __rhs_alt) {
892 __construct_alt(
893 __lhs_alt,
894 _VSTD::forward<decltype(__rhs_alt)>(__rhs_alt).__value);
895 },
896 __lhs, _VSTD::forward<_Rhs>(__rhs));
897 __lhs.__index = __rhs.index();
898 }
899 }
900};
901
902template <class _Traits, _Trait = _Traits::__move_constructible_trait>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000903class _LIBCPP_TEMPLATE_VIS __move_constructor;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000904
905#define _LIBCPP_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, \
906 move_constructor) \
907 template <class... _Types> \
Louis Dionneff05add2020-10-05 16:30:23 -0400908 class _LIBCPP_TEMPLATE_VIS __move_constructor<__traits<_Types...>, \
909 move_constructible_trait> \
910 : public __ctor<__traits<_Types...>> { \
911 using __base_type = __ctor<__traits<_Types...>>; \
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000912 \
913 public: \
914 using __base_type::__base_type; \
915 using __base_type::operator=; \
916 \
917 __move_constructor(const __move_constructor&) = default; \
918 move_constructor \
919 ~__move_constructor() = default; \
920 __move_constructor& operator=(const __move_constructor&) = default; \
921 __move_constructor& operator=(__move_constructor&&) = default; \
922 }
923
924_LIBCPP_VARIANT_MOVE_CONSTRUCTOR(
925 _Trait::_TriviallyAvailable,
926 __move_constructor(__move_constructor&& __that) = default;);
927
928_LIBCPP_VARIANT_MOVE_CONSTRUCTOR(
929 _Trait::_Available,
930 __move_constructor(__move_constructor&& __that) noexcept(
931 __all<is_nothrow_move_constructible_v<_Types>...>::value)
932 : __move_constructor(__valueless_t{}) {
933 this->__generic_construct(*this, _VSTD::move(__that));
934 });
935
936_LIBCPP_VARIANT_MOVE_CONSTRUCTOR(
937 _Trait::_Unavailable,
938 __move_constructor(__move_constructor&&) = delete;);
939
940#undef _LIBCPP_VARIANT_MOVE_CONSTRUCTOR
941
942template <class _Traits, _Trait = _Traits::__copy_constructible_trait>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000943class _LIBCPP_TEMPLATE_VIS __copy_constructor;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000944
945#define _LIBCPP_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, \
946 copy_constructor) \
947 template <class... _Types> \
Eric Fiselier87994112020-11-17 17:34:23 -0500948 class _LIBCPP_TEMPLATE_VIS __copy_constructor<__traits<_Types...>, \
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000949 copy_constructible_trait> \
950 : public __move_constructor<__traits<_Types...>> { \
951 using __base_type = __move_constructor<__traits<_Types...>>; \
952 \
953 public: \
954 using __base_type::__base_type; \
955 using __base_type::operator=; \
956 \
957 copy_constructor \
958 __copy_constructor(__copy_constructor&&) = default; \
959 ~__copy_constructor() = default; \
960 __copy_constructor& operator=(const __copy_constructor&) = default; \
961 __copy_constructor& operator=(__copy_constructor&&) = default; \
962 }
963
964_LIBCPP_VARIANT_COPY_CONSTRUCTOR(
965 _Trait::_TriviallyAvailable,
966 __copy_constructor(const __copy_constructor& __that) = default;);
967
968_LIBCPP_VARIANT_COPY_CONSTRUCTOR(
969 _Trait::_Available,
970 __copy_constructor(const __copy_constructor& __that)
971 : __copy_constructor(__valueless_t{}) {
972 this->__generic_construct(*this, __that);
973 });
974
975_LIBCPP_VARIANT_COPY_CONSTRUCTOR(
976 _Trait::_Unavailable,
977 __copy_constructor(const __copy_constructor&) = delete;);
978
979#undef _LIBCPP_VARIANT_COPY_CONSTRUCTOR
980
981template <class _Traits>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000982class _LIBCPP_TEMPLATE_VIS __assignment : public __copy_constructor<_Traits> {
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000983 using __base_type = __copy_constructor<_Traits>;
984
985public:
986 using __base_type::__base_type;
987 using __base_type::operator=;
988
989 template <size_t _Ip, class... _Args>
990 inline _LIBCPP_INLINE_VISIBILITY
Eric Fiselier62928442017-04-15 19:32:02 +0000991 auto& __emplace(_Args&&... __args) {
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000992 this->__destroy();
Eric Fiselier62928442017-04-15 19:32:02 +0000993 auto& __res = this->__construct_alt(__access::__base::__get_alt<_Ip>(*this),
Eric Fiselier87994112020-11-17 17:34:23 -0500994 _VSTD::forward<_Args>(__args)...);
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000995 this->__index = _Ip;
Eric Fiselier62928442017-04-15 19:32:02 +0000996 return __res;
Eric Fiselier94cdacc2016-12-02 23:00:05 +0000997 }
998
999protected:
Michael Park62118352017-06-07 10:22:43 +00001000 template <size_t _Ip, class _Tp, class _Arg>
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001001 inline _LIBCPP_INLINE_VISIBILITY
Michael Park62118352017-06-07 10:22:43 +00001002 void __assign_alt(__alt<_Ip, _Tp>& __a, _Arg&& __arg) {
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001003 if (this->index() == _Ip) {
1004 __a.__value = _VSTD::forward<_Arg>(__arg);
1005 } else {
1006 struct {
1007 void operator()(true_type) const {
Michael Park62118352017-06-07 10:22:43 +00001008 __this->__emplace<_Ip>(_VSTD::forward<_Arg>(__arg));
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001009 }
1010 void operator()(false_type) const {
Michael Park62118352017-06-07 10:22:43 +00001011 __this->__emplace<_Ip>(_Tp(_VSTD::forward<_Arg>(__arg)));
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001012 }
1013 __assignment* __this;
1014 _Arg&& __arg;
1015 } __impl{this, _VSTD::forward<_Arg>(__arg)};
Michael Park62118352017-06-07 10:22:43 +00001016 __impl(bool_constant<is_nothrow_constructible_v<_Tp, _Arg> ||
1017 !is_nothrow_move_constructible_v<_Tp>>{});
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001018 }
1019 }
1020
1021 template <class _That>
1022 inline _LIBCPP_INLINE_VISIBILITY
1023 void __generic_assign(_That&& __that) {
1024 if (this->valueless_by_exception() && __that.valueless_by_exception()) {
1025 // do nothing.
1026 } else if (__that.valueless_by_exception()) {
1027 this->__destroy();
1028 } else {
1029 __visitation::__base::__visit_alt_at(
1030 __that.index(),
1031 [this](auto& __this_alt, auto&& __that_alt) {
1032 this->__assign_alt(
1033 __this_alt,
Michael Park62118352017-06-07 10:22:43 +00001034 _VSTD::forward<decltype(__that_alt)>(__that_alt).__value);
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001035 },
1036 *this, _VSTD::forward<_That>(__that));
1037 }
1038 }
1039};
1040
1041template <class _Traits, _Trait = _Traits::__move_assignable_trait>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00001042class _LIBCPP_TEMPLATE_VIS __move_assignment;
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001043
1044#define _LIBCPP_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, \
1045 move_assignment) \
1046 template <class... _Types> \
Eric Fiselier87994112020-11-17 17:34:23 -05001047 class _LIBCPP_TEMPLATE_VIS __move_assignment<__traits<_Types...>, \
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001048 move_assignable_trait> \
1049 : public __assignment<__traits<_Types...>> { \
1050 using __base_type = __assignment<__traits<_Types...>>; \
1051 \
1052 public: \
1053 using __base_type::__base_type; \
1054 using __base_type::operator=; \
1055 \
1056 __move_assignment(const __move_assignment&) = default; \
1057 __move_assignment(__move_assignment&&) = default; \
1058 ~__move_assignment() = default; \
1059 __move_assignment& operator=(const __move_assignment&) = default; \
1060 move_assignment \
1061 }
1062
1063_LIBCPP_VARIANT_MOVE_ASSIGNMENT(
1064 _Trait::_TriviallyAvailable,
1065 __move_assignment& operator=(__move_assignment&& __that) = default;);
1066
1067_LIBCPP_VARIANT_MOVE_ASSIGNMENT(
1068 _Trait::_Available,
1069 __move_assignment& operator=(__move_assignment&& __that) noexcept(
1070 __all<(is_nothrow_move_constructible_v<_Types> &&
1071 is_nothrow_move_assignable_v<_Types>)...>::value) {
1072 this->__generic_assign(_VSTD::move(__that));
1073 return *this;
1074 });
1075
1076_LIBCPP_VARIANT_MOVE_ASSIGNMENT(
1077 _Trait::_Unavailable,
1078 __move_assignment& operator=(__move_assignment&&) = delete;);
1079
1080#undef _LIBCPP_VARIANT_MOVE_ASSIGNMENT
1081
1082template <class _Traits, _Trait = _Traits::__copy_assignable_trait>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00001083class _LIBCPP_TEMPLATE_VIS __copy_assignment;
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001084
1085#define _LIBCPP_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, \
1086 copy_assignment) \
1087 template <class... _Types> \
Eric Fiselier87994112020-11-17 17:34:23 -05001088 class _LIBCPP_TEMPLATE_VIS __copy_assignment<__traits<_Types...>, \
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001089 copy_assignable_trait> \
1090 : public __move_assignment<__traits<_Types...>> { \
1091 using __base_type = __move_assignment<__traits<_Types...>>; \
1092 \
1093 public: \
1094 using __base_type::__base_type; \
1095 using __base_type::operator=; \
1096 \
1097 __copy_assignment(const __copy_assignment&) = default; \
1098 __copy_assignment(__copy_assignment&&) = default; \
1099 ~__copy_assignment() = default; \
1100 copy_assignment \
1101 __copy_assignment& operator=(__copy_assignment&&) = default; \
1102 }
1103
1104_LIBCPP_VARIANT_COPY_ASSIGNMENT(
1105 _Trait::_TriviallyAvailable,
1106 __copy_assignment& operator=(const __copy_assignment& __that) = default;);
1107
1108_LIBCPP_VARIANT_COPY_ASSIGNMENT(
1109 _Trait::_Available,
1110 __copy_assignment& operator=(const __copy_assignment& __that) {
1111 this->__generic_assign(__that);
1112 return *this;
1113 });
1114
1115_LIBCPP_VARIANT_COPY_ASSIGNMENT(
1116 _Trait::_Unavailable,
1117 __copy_assignment& operator=(const __copy_assignment&) = delete;);
1118
1119#undef _LIBCPP_VARIANT_COPY_ASSIGNMENT
1120
1121template <class... _Types>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00001122class _LIBCPP_TEMPLATE_VIS __impl
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001123 : public __copy_assignment<__traits<_Types...>> {
1124 using __base_type = __copy_assignment<__traits<_Types...>>;
1125
1126public:
1127 using __base_type::__base_type;
1128 using __base_type::operator=;
1129
1130 template <size_t _Ip, class _Arg>
1131 inline _LIBCPP_INLINE_VISIBILITY
1132 void __assign(_Arg&& __arg) {
1133 this->__assign_alt(__access::__base::__get_alt<_Ip>(*this),
Michael Park62118352017-06-07 10:22:43 +00001134 _VSTD::forward<_Arg>(__arg));
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001135 }
1136
1137 inline _LIBCPP_INLINE_VISIBILITY
1138 void __swap(__impl& __that) {
1139 if (this->valueless_by_exception() && __that.valueless_by_exception()) {
1140 // do nothing.
1141 } else if (this->index() == __that.index()) {
1142 __visitation::__base::__visit_alt_at(
1143 this->index(),
1144 [](auto& __this_alt, auto& __that_alt) {
1145 using _VSTD::swap;
1146 swap(__this_alt.__value, __that_alt.__value);
1147 },
1148 *this,
1149 __that);
1150 } else {
1151 __impl* __lhs = this;
1152 __impl* __rhs = _VSTD::addressof(__that);
1153 if (__lhs->__move_nothrow() && !__rhs->__move_nothrow()) {
1154 _VSTD::swap(__lhs, __rhs);
1155 }
1156 __impl __tmp(_VSTD::move(*__rhs));
Michael Park5dee7342020-06-16 15:15:10 -07001157#ifndef _LIBCPP_NO_EXCEPTIONS
Michael Park6a9ef642020-07-08 10:46:02 -07001158 if constexpr (__all<is_nothrow_move_constructible_v<_Types>...>::value) {
Michael Park31967aa2020-06-16 13:29:23 -07001159 this->__generic_construct(*__rhs, _VSTD::move(*__lhs));
1160 } else {
1161 // EXTENSION: When the move construction of `__lhs` into `__rhs` throws
1162 // and `__tmp` is nothrow move constructible then we move `__tmp` back
1163 // into `__rhs` and provide the strong exception safety guarantee.
1164 try {
1165 this->__generic_construct(*__rhs, _VSTD::move(*__lhs));
1166 } catch (...) {
1167 if (__tmp.__move_nothrow()) {
1168 this->__generic_construct(*__rhs, _VSTD::move(__tmp));
1169 }
1170 throw;
1171 }
1172 }
Michael Park5dee7342020-06-16 15:15:10 -07001173#else
1174 // this isn't consolidated with the `if constexpr` branch above due to
1175 // `throw` being ill-formed with exceptions disabled even when discarded.
1176 this->__generic_construct(*__rhs, _VSTD::move(*__lhs));
1177#endif
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001178 this->__generic_construct(*__lhs, _VSTD::move(__tmp));
1179 }
1180 }
1181
1182private:
1183 inline _LIBCPP_INLINE_VISIBILITY
1184 bool __move_nothrow() const {
1185 constexpr bool __results[] = {is_nothrow_move_constructible_v<_Types>...};
1186 return this->valueless_by_exception() || __results[this->index()];
1187 }
1188};
1189
Eric Fiselier3aaf8a32019-07-14 18:21:15 +00001190struct __no_narrowing_check {
1191 template <class _Dest, class _Source>
1192 using _Apply = __identity<_Dest>;
1193};
1194
1195struct __narrowing_check {
1196 template <class _Dest>
1197 static auto __test_impl(_Dest (&&)[1]) -> __identity<_Dest>;
1198 template <class _Dest, class _Source>
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001199 using _Apply _LIBCPP_NODEBUG_TYPE = decltype(__test_impl<_Dest>({declval<_Source>()}));
Eric Fiselier3aaf8a32019-07-14 18:21:15 +00001200};
1201
1202template <class _Dest, class _Source>
Eric Fiselieraa7cdca2019-07-14 21:29:39 +00001203using __check_for_narrowing _LIBCPP_NODEBUG_TYPE =
1204 typename _If<
Eric Fiselier3aaf8a32019-07-14 18:21:15 +00001205#ifdef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT
1206 false &&
1207#endif
1208 is_arithmetic<_Dest>::value,
1209 __narrowing_check,
1210 __no_narrowing_check
Eric Fiselieraa7cdca2019-07-14 21:29:39 +00001211 >::template _Apply<_Dest, _Source>;
Eric Fiselier3aaf8a32019-07-14 18:21:15 +00001212
Eric Fiselieraa7cdca2019-07-14 21:29:39 +00001213template <class _Tp, size_t _Idx>
1214struct __overload {
Zhihao Yuan821efb82019-06-20 22:09:40 +00001215 template <class _Up>
Eric Fiselier80f5dfb2019-07-14 18:31:55 +00001216 auto operator()(_Tp, _Up&&) const -> __check_for_narrowing<_Tp, _Up>;
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001217};
1218
Eric Fiselieraa7cdca2019-07-14 21:29:39 +00001219template <class _Tp, size_t>
1220struct __overload_bool {
Zhihao Yuan821efb82019-06-20 22:09:40 +00001221 template <class _Up, class _Ap = __uncvref_t<_Up>>
1222 auto operator()(bool, _Up&&) const
1223 -> enable_if_t<is_same_v<_Ap, bool>, __identity<_Tp>>;
1224};
1225
Eric Fiselieraa7cdca2019-07-14 21:29:39 +00001226template <size_t _Idx>
1227struct __overload<bool, _Idx> : __overload_bool<bool, _Idx> {};
1228template <size_t _Idx>
1229struct __overload<bool const, _Idx> : __overload_bool<bool const, _Idx> {};
1230template <size_t _Idx>
1231struct __overload<bool volatile, _Idx> : __overload_bool<bool volatile, _Idx> {};
1232template <size_t _Idx>
1233struct __overload<bool const volatile, _Idx> : __overload_bool<bool const volatile, _Idx> {};
1234
1235template <class ..._Bases>
1236struct __all_overloads : _Bases... {
1237 void operator()() const;
1238 using _Bases::operator()...;
1239};
1240
1241template <class IdxSeq>
1242struct __make_overloads_imp;
1243
1244template <size_t ..._Idx>
1245struct __make_overloads_imp<__tuple_indices<_Idx...> > {
1246 template <class ..._Types>
1247 using _Apply _LIBCPP_NODEBUG_TYPE = __all_overloads<__overload<_Types, _Idx>...>;
1248};
1249
1250template <class ..._Types>
1251using _MakeOverloads _LIBCPP_NODEBUG_TYPE = typename __make_overloads_imp<
1252 __make_indices_imp<sizeof...(_Types), 0> >::template _Apply<_Types...>;
Zhihao Yuan821efb82019-06-20 22:09:40 +00001253
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001254template <class _Tp, class... _Types>
Zhihao Yuan821efb82019-06-20 22:09:40 +00001255using __best_match_t =
Eric Fiselieraa7cdca2019-07-14 21:29:39 +00001256 typename invoke_result_t<_MakeOverloads<_Types...>, _Tp, _Tp>::type;
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001257
1258} // __variant_detail
1259
1260template <class... _Types>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00001261class _LIBCPP_TEMPLATE_VIS variant
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001262 : private __sfinae_ctor_base<
1263 __all<is_copy_constructible_v<_Types>...>::value,
1264 __all<is_move_constructible_v<_Types>...>::value>,
1265 private __sfinae_assign_base<
1266 __all<(is_copy_constructible_v<_Types> &&
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001267 is_copy_assignable_v<_Types>)...>::value,
1268 __all<(is_move_constructible_v<_Types> &&
1269 is_move_assignable_v<_Types>)...>::value> {
1270 static_assert(0 < sizeof...(_Types),
1271 "variant must consist of at least one alternative.");
1272
1273 static_assert(__all<!is_array_v<_Types>...>::value,
1274 "variant can not have an array type as an alternative.");
1275
1276 static_assert(__all<!is_reference_v<_Types>...>::value,
1277 "variant can not have a reference type as an alternative.");
1278
1279 static_assert(__all<!is_void_v<_Types>...>::value,
1280 "variant can not have a void type as an alternative.");
1281
1282 using __first_type = variant_alternative_t<0, variant>;
1283
1284public:
1285 template <bool _Dummy = true,
1286 enable_if_t<__dependent_type<is_default_constructible<__first_type>,
1287 _Dummy>::value,
1288 int> = 0>
1289 inline _LIBCPP_INLINE_VISIBILITY
1290 constexpr variant() noexcept(is_nothrow_default_constructible_v<__first_type>)
1291 : __impl(in_place_index<0>) {}
1292
1293 variant(const variant&) = default;
1294 variant(variant&&) = default;
1295
1296 template <
1297 class _Arg,
Marshall Clowd5bbc242018-02-06 20:56:55 +00001298 enable_if_t<!is_same_v<__uncvref_t<_Arg>, variant>, int> = 0,
1299 enable_if_t<!__is_inplace_type<__uncvref_t<_Arg>>::value, int> = 0,
1300 enable_if_t<!__is_inplace_index<__uncvref_t<_Arg>>::value, int> = 0,
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001301 class _Tp = __variant_detail::__best_match_t<_Arg, _Types...>,
1302 size_t _Ip =
1303 __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value,
1304 enable_if_t<is_constructible_v<_Tp, _Arg>, int> = 0>
1305 inline _LIBCPP_INLINE_VISIBILITY
1306 constexpr variant(_Arg&& __arg) noexcept(
1307 is_nothrow_constructible_v<_Tp, _Arg>)
1308 : __impl(in_place_index<_Ip>, _VSTD::forward<_Arg>(__arg)) {}
1309
1310 template <size_t _Ip, class... _Args,
Eric Fiselier5d2df752018-03-23 23:42:30 +00001311 class = enable_if_t<(_Ip < sizeof...(_Types)), int>,
1312 class _Tp = variant_alternative_t<_Ip, variant<_Types...>>,
1313 enable_if_t<is_constructible_v<_Tp, _Args...>, int> = 0>
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001314 inline _LIBCPP_INLINE_VISIBILITY
Eric Fiselier5d2df752018-03-23 23:42:30 +00001315 explicit constexpr variant(
1316 in_place_index_t<_Ip>,
1317 _Args&&... __args) noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001318 : __impl(in_place_index<_Ip>, _VSTD::forward<_Args>(__args)...) {}
1319
Eric Fiselier5d2df752018-03-23 23:42:30 +00001320 template <
1321 size_t _Ip,
1322 class _Up,
1323 class... _Args,
1324 enable_if_t<(_Ip < sizeof...(_Types)), int> = 0,
1325 class _Tp = variant_alternative_t<_Ip, variant<_Types...>>,
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001326 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
1327 int> = 0>
1328 inline _LIBCPP_INLINE_VISIBILITY
Eric Fiselier5d2df752018-03-23 23:42:30 +00001329 explicit constexpr variant(
1330 in_place_index_t<_Ip>,
1331 initializer_list<_Up> __il,
1332 _Args&&... __args) noexcept(
1333 is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>)
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001334 : __impl(in_place_index<_Ip>, __il, _VSTD::forward<_Args>(__args)...) {}
1335
1336 template <
1337 class _Tp,
1338 class... _Args,
1339 size_t _Ip =
1340 __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value,
1341 enable_if_t<is_constructible_v<_Tp, _Args...>, int> = 0>
1342 inline _LIBCPP_INLINE_VISIBILITY
1343 explicit constexpr variant(in_place_type_t<_Tp>, _Args&&... __args) noexcept(
1344 is_nothrow_constructible_v<_Tp, _Args...>)
1345 : __impl(in_place_index<_Ip>, _VSTD::forward<_Args>(__args)...) {}
1346
1347 template <
1348 class _Tp,
1349 class _Up,
1350 class... _Args,
1351 size_t _Ip =
1352 __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value,
1353 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
1354 int> = 0>
1355 inline _LIBCPP_INLINE_VISIBILITY
1356 explicit constexpr variant(
1357 in_place_type_t<_Tp>,
1358 initializer_list<_Up> __il,
1359 _Args&&... __args) noexcept(
1360 is_nothrow_constructible_v<_Tp, initializer_list< _Up>&, _Args...>)
1361 : __impl(in_place_index<_Ip>, __il, _VSTD::forward<_Args>(__args)...) {}
1362
1363 ~variant() = default;
1364
1365 variant& operator=(const variant&) = default;
1366 variant& operator=(variant&&) = default;
1367
1368 template <
1369 class _Arg,
Marshall Clowd5bbc242018-02-06 20:56:55 +00001370 enable_if_t<!is_same_v<__uncvref_t<_Arg>, variant>, int> = 0,
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001371 class _Tp = __variant_detail::__best_match_t<_Arg, _Types...>,
1372 size_t _Ip =
1373 __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value,
1374 enable_if_t<is_assignable_v<_Tp&, _Arg> && is_constructible_v<_Tp, _Arg>,
1375 int> = 0>
1376 inline _LIBCPP_INLINE_VISIBILITY
1377 variant& operator=(_Arg&& __arg) noexcept(
1378 is_nothrow_assignable_v<_Tp&, _Arg> &&
1379 is_nothrow_constructible_v<_Tp, _Arg>) {
1380 __impl.template __assign<_Ip>(_VSTD::forward<_Arg>(__arg));
1381 return *this;
1382 }
1383
1384 template <
1385 size_t _Ip,
1386 class... _Args,
1387 enable_if_t<(_Ip < sizeof...(_Types)), int> = 0,
1388 class _Tp = variant_alternative_t<_Ip, variant<_Types...>>,
1389 enable_if_t<is_constructible_v<_Tp, _Args...>, int> = 0>
1390 inline _LIBCPP_INLINE_VISIBILITY
Eric Fiselier62928442017-04-15 19:32:02 +00001391 _Tp& emplace(_Args&&... __args) {
1392 return __impl.template __emplace<_Ip>(_VSTD::forward<_Args>(__args)...);
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001393 }
1394
1395 template <
1396 size_t _Ip,
1397 class _Up,
1398 class... _Args,
1399 enable_if_t<(_Ip < sizeof...(_Types)), int> = 0,
1400 class _Tp = variant_alternative_t<_Ip, variant<_Types...>>,
1401 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
1402 int> = 0>
1403 inline _LIBCPP_INLINE_VISIBILITY
Eric Fiselier62928442017-04-15 19:32:02 +00001404 _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) {
1405 return __impl.template __emplace<_Ip>(__il, _VSTD::forward<_Args>(__args)...);
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001406 }
1407
1408 template <
1409 class _Tp,
1410 class... _Args,
1411 size_t _Ip =
1412 __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value,
1413 enable_if_t<is_constructible_v<_Tp, _Args...>, int> = 0>
1414 inline _LIBCPP_INLINE_VISIBILITY
Eric Fiselier62928442017-04-15 19:32:02 +00001415 _Tp& emplace(_Args&&... __args) {
1416 return __impl.template __emplace<_Ip>(_VSTD::forward<_Args>(__args)...);
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001417 }
1418
1419 template <
1420 class _Tp,
1421 class _Up,
1422 class... _Args,
1423 size_t _Ip =
1424 __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value,
1425 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>,
1426 int> = 0>
1427 inline _LIBCPP_INLINE_VISIBILITY
Eric Fiselier62928442017-04-15 19:32:02 +00001428 _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) {
1429 return __impl.template __emplace<_Ip>(__il, _VSTD::forward<_Args>(__args)...);
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001430 }
1431
1432 inline _LIBCPP_INLINE_VISIBILITY
1433 constexpr bool valueless_by_exception() const noexcept {
1434 return __impl.valueless_by_exception();
1435 }
1436
1437 inline _LIBCPP_INLINE_VISIBILITY
1438 constexpr size_t index() const noexcept { return __impl.index(); }
1439
1440 template <
1441 bool _Dummy = true,
1442 enable_if_t<
1443 __all<(
1444 __dependent_type<is_move_constructible<_Types>, _Dummy>::value &&
1445 __dependent_type<is_swappable<_Types>, _Dummy>::value)...>::value,
1446 int> = 0>
1447 inline _LIBCPP_INLINE_VISIBILITY
1448 void swap(variant& __that) noexcept(
1449 __all<(is_nothrow_move_constructible_v<_Types> &&
1450 is_nothrow_swappable_v<_Types>)...>::value) {
1451 __impl.__swap(__that.__impl);
1452 }
1453
1454private:
1455 __variant_detail::__impl<_Types...> __impl;
1456
1457 friend struct __variant_detail::__access::__variant;
1458 friend struct __variant_detail::__visitation::__variant;
1459};
1460
1461template <size_t _Ip, class... _Types>
1462inline _LIBCPP_INLINE_VISIBILITY
1463constexpr bool __holds_alternative(const variant<_Types...>& __v) noexcept {
1464 return __v.index() == _Ip;
1465}
1466
1467template <class _Tp, class... _Types>
1468inline _LIBCPP_INLINE_VISIBILITY
1469constexpr bool holds_alternative(const variant<_Types...>& __v) noexcept {
1470 return __holds_alternative<__find_exactly_one_t<_Tp, _Types...>::value>(__v);
1471}
1472
1473template <size_t _Ip, class _Vp>
1474inline _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +00001475_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
Richard Smith66d1c552018-08-27 21:41:50 +00001476constexpr auto&& __generic_get(_Vp&& __v) {
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001477 using __variant_detail::__access::__variant;
1478 if (!__holds_alternative<_Ip>(__v)) {
Eric Fiselier10642ea2016-12-03 01:58:07 +00001479 __throw_bad_variant_access();
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001480 }
1481 return __variant::__get_alt<_Ip>(_VSTD::forward<_Vp>(__v)).__value;
1482}
1483
1484template <size_t _Ip, class... _Types>
1485inline _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +00001486_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001487constexpr variant_alternative_t<_Ip, variant<_Types...>>& get(
1488 variant<_Types...>& __v) {
1489 static_assert(_Ip < sizeof...(_Types));
1490 static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>);
1491 return __generic_get<_Ip>(__v);
1492}
1493
1494template <size_t _Ip, class... _Types>
1495inline _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +00001496_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001497constexpr variant_alternative_t<_Ip, variant<_Types...>>&& get(
1498 variant<_Types...>&& __v) {
1499 static_assert(_Ip < sizeof...(_Types));
1500 static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>);
1501 return __generic_get<_Ip>(_VSTD::move(__v));
1502}
1503
1504template <size_t _Ip, class... _Types>
1505inline _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +00001506_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001507constexpr const variant_alternative_t<_Ip, variant<_Types...>>& get(
1508 const variant<_Types...>& __v) {
1509 static_assert(_Ip < sizeof...(_Types));
1510 static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>);
1511 return __generic_get<_Ip>(__v);
1512}
1513
1514template <size_t _Ip, class... _Types>
1515inline _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +00001516_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001517constexpr const variant_alternative_t<_Ip, variant<_Types...>>&& get(
1518 const variant<_Types...>&& __v) {
1519 static_assert(_Ip < sizeof...(_Types));
1520 static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>);
1521 return __generic_get<_Ip>(_VSTD::move(__v));
1522}
1523
1524template <class _Tp, class... _Types>
1525inline _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +00001526_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001527constexpr _Tp& get(variant<_Types...>& __v) {
1528 static_assert(!is_void_v<_Tp>);
1529 return _VSTD::get<__find_exactly_one_t<_Tp, _Types...>::value>(__v);
1530}
1531
1532template <class _Tp, class... _Types>
1533inline _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +00001534_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001535constexpr _Tp&& get(variant<_Types...>&& __v) {
1536 static_assert(!is_void_v<_Tp>);
1537 return _VSTD::get<__find_exactly_one_t<_Tp, _Types...>::value>(
1538 _VSTD::move(__v));
1539}
1540
1541template <class _Tp, class... _Types>
1542inline _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +00001543_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001544constexpr const _Tp& get(const variant<_Types...>& __v) {
1545 static_assert(!is_void_v<_Tp>);
1546 return _VSTD::get<__find_exactly_one_t<_Tp, _Types...>::value>(__v);
1547}
1548
1549template <class _Tp, class... _Types>
1550inline _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +00001551_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001552constexpr const _Tp&& get(const variant<_Types...>&& __v) {
1553 static_assert(!is_void_v<_Tp>);
1554 return _VSTD::get<__find_exactly_one_t<_Tp, _Types...>::value>(
1555 _VSTD::move(__v));
1556}
1557
1558template <size_t _Ip, class _Vp>
1559inline _LIBCPP_INLINE_VISIBILITY
1560constexpr auto* __generic_get_if(_Vp* __v) noexcept {
1561 using __variant_detail::__access::__variant;
1562 return __v && __holds_alternative<_Ip>(*__v)
1563 ? _VSTD::addressof(__variant::__get_alt<_Ip>(*__v).__value)
1564 : nullptr;
1565}
1566
1567template <size_t _Ip, class... _Types>
1568inline _LIBCPP_INLINE_VISIBILITY
1569constexpr add_pointer_t<variant_alternative_t<_Ip, variant<_Types...>>>
1570get_if(variant<_Types...>* __v) noexcept {
1571 static_assert(_Ip < sizeof...(_Types));
1572 static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>);
1573 return __generic_get_if<_Ip>(__v);
1574}
1575
1576template <size_t _Ip, class... _Types>
1577inline _LIBCPP_INLINE_VISIBILITY
1578constexpr add_pointer_t<const variant_alternative_t<_Ip, variant<_Types...>>>
1579get_if(const variant<_Types...>* __v) noexcept {
1580 static_assert(_Ip < sizeof...(_Types));
1581 static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>);
1582 return __generic_get_if<_Ip>(__v);
1583}
1584
1585template <class _Tp, class... _Types>
1586inline _LIBCPP_INLINE_VISIBILITY
1587constexpr add_pointer_t<_Tp>
1588get_if(variant<_Types...>* __v) noexcept {
1589 static_assert(!is_void_v<_Tp>);
1590 return _VSTD::get_if<__find_exactly_one_t<_Tp, _Types...>::value>(__v);
1591}
1592
1593template <class _Tp, class... _Types>
1594inline _LIBCPP_INLINE_VISIBILITY
1595constexpr add_pointer_t<const _Tp>
1596get_if(const variant<_Types...>* __v) noexcept {
1597 static_assert(!is_void_v<_Tp>);
1598 return _VSTD::get_if<__find_exactly_one_t<_Tp, _Types...>::value>(__v);
1599}
1600
Eric Fiselierfb6a2bc2018-09-19 17:53:21 +00001601template <class _Operator>
1602struct __convert_to_bool {
1603 template <class _T1, class _T2>
1604 _LIBCPP_INLINE_VISIBILITY constexpr bool operator()(_T1 && __t1, _T2&& __t2) const {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001605 static_assert(is_convertible<decltype(_Operator{}(_VSTD::forward<_T1>(__t1), _VSTD::forward<_T2>(__t2))), bool>::value,
Eric Fiselierfb6a2bc2018-09-19 17:53:21 +00001606 "the relational operator does not return a type which is implicitly convertible to bool");
1607 return _Operator{}(_VSTD::forward<_T1>(__t1), _VSTD::forward<_T2>(__t2));
1608 }
1609};
1610
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001611template <class... _Types>
1612inline _LIBCPP_INLINE_VISIBILITY
1613constexpr bool operator==(const variant<_Types...>& __lhs,
1614 const variant<_Types...>& __rhs) {
1615 using __variant_detail::__visitation::__variant;
1616 if (__lhs.index() != __rhs.index()) return false;
1617 if (__lhs.valueless_by_exception()) return true;
Eric Fiselierfb6a2bc2018-09-19 17:53:21 +00001618 return __variant::__visit_value_at(__lhs.index(), __convert_to_bool<equal_to<>>{}, __lhs, __rhs);
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001619}
1620
1621template <class... _Types>
1622inline _LIBCPP_INLINE_VISIBILITY
1623constexpr bool operator!=(const variant<_Types...>& __lhs,
1624 const variant<_Types...>& __rhs) {
1625 using __variant_detail::__visitation::__variant;
1626 if (__lhs.index() != __rhs.index()) return true;
1627 if (__lhs.valueless_by_exception()) return false;
1628 return __variant::__visit_value_at(
Eric Fiselierfb6a2bc2018-09-19 17:53:21 +00001629 __lhs.index(), __convert_to_bool<not_equal_to<>>{}, __lhs, __rhs);
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001630}
1631
1632template <class... _Types>
1633inline _LIBCPP_INLINE_VISIBILITY
1634constexpr bool operator<(const variant<_Types...>& __lhs,
1635 const variant<_Types...>& __rhs) {
1636 using __variant_detail::__visitation::__variant;
1637 if (__rhs.valueless_by_exception()) return false;
1638 if (__lhs.valueless_by_exception()) return true;
1639 if (__lhs.index() < __rhs.index()) return true;
1640 if (__lhs.index() > __rhs.index()) return false;
Eric Fiselierfb6a2bc2018-09-19 17:53:21 +00001641 return __variant::__visit_value_at(__lhs.index(), __convert_to_bool<less<>>{}, __lhs, __rhs);
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001642}
1643
1644template <class... _Types>
1645inline _LIBCPP_INLINE_VISIBILITY
1646constexpr bool operator>(const variant<_Types...>& __lhs,
1647 const variant<_Types...>& __rhs) {
1648 using __variant_detail::__visitation::__variant;
1649 if (__lhs.valueless_by_exception()) return false;
1650 if (__rhs.valueless_by_exception()) return true;
1651 if (__lhs.index() > __rhs.index()) return true;
1652 if (__lhs.index() < __rhs.index()) return false;
Eric Fiselierfb6a2bc2018-09-19 17:53:21 +00001653 return __variant::__visit_value_at(__lhs.index(), __convert_to_bool<greater<>>{}, __lhs, __rhs);
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001654}
1655
1656template <class... _Types>
1657inline _LIBCPP_INLINE_VISIBILITY
1658constexpr bool operator<=(const variant<_Types...>& __lhs,
1659 const variant<_Types...>& __rhs) {
1660 using __variant_detail::__visitation::__variant;
1661 if (__lhs.valueless_by_exception()) return true;
1662 if (__rhs.valueless_by_exception()) return false;
1663 if (__lhs.index() < __rhs.index()) return true;
1664 if (__lhs.index() > __rhs.index()) return false;
1665 return __variant::__visit_value_at(
Eric Fiselierfb6a2bc2018-09-19 17:53:21 +00001666 __lhs.index(), __convert_to_bool<less_equal<>>{}, __lhs, __rhs);
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001667}
1668
1669template <class... _Types>
1670inline _LIBCPP_INLINE_VISIBILITY
1671constexpr bool operator>=(const variant<_Types...>& __lhs,
1672 const variant<_Types...>& __rhs) {
1673 using __variant_detail::__visitation::__variant;
1674 if (__rhs.valueless_by_exception()) return true;
1675 if (__lhs.valueless_by_exception()) return false;
1676 if (__lhs.index() > __rhs.index()) return true;
1677 if (__lhs.index() < __rhs.index()) return false;
1678 return __variant::__visit_value_at(
Eric Fiselierfb6a2bc2018-09-19 17:53:21 +00001679 __lhs.index(), __convert_to_bool<greater_equal<>>{}, __lhs, __rhs);
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001680}
1681
Ruslan Arutyunyan24d0eea2021-01-25 13:34:03 -05001682template <class... _Vs>
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001683inline _LIBCPP_INLINE_VISIBILITY
Marek Kurdej2f5ec002021-03-25 18:09:11 +01001684 _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr void
1685 __throw_if_valueless(_Vs&&... __vs) {
1686 const bool __valueless =
1687 (... || _VSTD::__as_variant(__vs).valueless_by_exception());
Ruslan Arutyunyan33f34732021-01-25 11:12:25 -05001688 if (__valueless) {
Marek Kurdej2f5ec002021-03-25 18:09:11 +01001689 __throw_bad_variant_access();
Ruslan Arutyunyan33f34732021-01-25 11:12:25 -05001690 }
1691}
1692
Marek Kurdej2f5ec002021-03-25 18:09:11 +01001693template <
1694 class _Visitor, class... _Vs,
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001695 typename = void_t<decltype(_VSTD::__as_variant(declval<_Vs>()))...> >
Ruslan Arutyunyan33f34732021-01-25 11:12:25 -05001696inline _LIBCPP_INLINE_VISIBILITY
Marek Kurdej2f5ec002021-03-25 18:09:11 +01001697 _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr
1698 decltype(auto) visit(_Visitor&& __visitor, _Vs&&... __vs) {
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001699 using __variant_detail::__visitation::__variant;
Ruslan Arutyunyan24d0eea2021-01-25 13:34:03 -05001700 _VSTD::__throw_if_valueless(_VSTD::forward<_Vs>(__vs)...);
Eric Fiselier87994112020-11-17 17:34:23 -05001701 return __variant::__visit_value(_VSTD::forward<_Visitor>(__visitor),
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001702 _VSTD::forward<_Vs>(__vs)...);
1703}
1704
Ruslan Arutyunyan33f34732021-01-25 11:12:25 -05001705#if _LIBCPP_STD_VER > 17
Marek Kurdej2f5ec002021-03-25 18:09:11 +01001706template <
1707 class _Rp, class _Visitor, class... _Vs,
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001708 typename = void_t<decltype(_VSTD::__as_variant(declval<_Vs>()))...> >
Ruslan Arutyunyan33f34732021-01-25 11:12:25 -05001709inline _LIBCPP_INLINE_VISIBILITY
Marek Kurdej2f5ec002021-03-25 18:09:11 +01001710 _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr _Rp
1711 visit(_Visitor&& __visitor, _Vs&&... __vs) {
Ruslan Arutyunyan33f34732021-01-25 11:12:25 -05001712 using __variant_detail::__visitation::__variant;
Ruslan Arutyunyan24d0eea2021-01-25 13:34:03 -05001713 _VSTD::__throw_if_valueless(_VSTD::forward<_Vs>(__vs)...);
Ruslan Arutyunyan33f34732021-01-25 11:12:25 -05001714 return __variant::__visit_value<_Rp>(_VSTD::forward<_Visitor>(__visitor),
1715 _VSTD::forward<_Vs>(__vs)...);
1716}
1717#endif
1718
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001719template <class... _Types>
1720inline _LIBCPP_INLINE_VISIBILITY
Louis Dionnef1a01932021-08-16 12:41:58 -04001721auto swap(variant<_Types...>& __lhs, variant<_Types...>& __rhs)
1722 noexcept(noexcept(__lhs.swap(__rhs)))
1723 -> decltype( __lhs.swap(__rhs))
1724 { return __lhs.swap(__rhs); }
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001725
1726template <class... _Types>
Eric Fiselier698a97b2017-01-21 00:02:12 +00001727struct _LIBCPP_TEMPLATE_VIS hash<
1728 __enable_hash_helper<variant<_Types...>, remove_const_t<_Types>...>> {
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001729 using argument_type = variant<_Types...>;
1730 using result_type = size_t;
1731
1732 inline _LIBCPP_INLINE_VISIBILITY
1733 result_type operator()(const argument_type& __v) const {
1734 using __variant_detail::__visitation::__variant;
Eric Fiselier9a4e3502016-12-02 23:38:31 +00001735 size_t __res =
1736 __v.valueless_by_exception()
Eric Fiselier6b1683c2016-12-04 21:37:37 +00001737 ? 299792458 // Random value chosen by the universe upon creation
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001738 : __variant::__visit_alt(
1739 [](const auto& __alt) {
Marshall Clowe61ba952018-02-12 15:41:25 +00001740 using __alt_type = __uncvref_t<decltype(__alt)>;
Eric Fiselier698a97b2017-01-21 00:02:12 +00001741 using __value_type = remove_const_t<
1742 typename __alt_type::__value_type>;
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001743 return hash<__value_type>{}(__alt.__value);
1744 },
1745 __v);
Eric Fiselier9a4e3502016-12-02 23:38:31 +00001746 return __hash_combine(__res, hash<size_t>{}(__v.index()));
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001747 }
1748};
1749
zoecarver6eb71a92021-05-27 09:23:19 -07001750// __unchecked_get is the same as std::get, except, it is UB to use it with the wrong
1751// type whereas std::get will throw or returning nullptr. This makes it faster than
1752// std::get.
1753template <size_t _Ip, class _Vp>
1754inline _LIBCPP_INLINE_VISIBILITY
1755constexpr auto&& __unchecked_get(_Vp&& __v) noexcept {
1756 using __variant_detail::__access::__variant;
1757 return __variant::__get_alt<_Ip>(_VSTD::forward<_Vp>(__v)).__value;
1758}
1759
1760template <class _Tp, class... _Types>
1761inline _LIBCPP_INLINE_VISIBILITY
1762constexpr auto&& __unchecked_get(const variant<_Types...>& __v) noexcept {
1763 return __unchecked_get<__find_exactly_one_t<_Tp, _Types...>::value>(__v);
1764}
1765
1766template <class _Tp, class... _Types>
1767inline _LIBCPP_INLINE_VISIBILITY
1768constexpr auto&& __unchecked_get(variant<_Types...>& __v) noexcept {
1769 return __unchecked_get<__find_exactly_one_t<_Tp, _Types...>::value>(__v);
1770}
1771
Louis Dionne2b1ceaa2021-04-20 12:03:32 -04001772#endif // _LIBCPP_STD_VER > 14
Eric Fiselier94cdacc2016-12-02 23:00:05 +00001773
1774_LIBCPP_END_NAMESPACE_STD
1775
Eric Fiselier8625d332017-11-19 04:57:22 +00001776_LIBCPP_POP_MACROS
1777
Louis Dionne2b1ceaa2021-04-20 12:03:32 -04001778#endif // _LIBCPP_VARIANT