IPPL (Independent Parallel Particle Layer)
IPPL
Loading...
Searching...
No Matches
Variant.h
Go to the documentation of this file.
1#ifdef IPPL_USE_ALTERNATIVE_VARIANT
2// <variant> -*- C++ -*-
3
4// Copyright (C) 2016-2023 Free Software Foundation, Inc.
5//
6// This file is part of the GNU ISO C++ Library. This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 3, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16
17// Under Section 7 of GPL version 3, you are granted additional
18// permissions described in the GCC Runtime Library Exception, version
19// 3.1, as published by the Free Software Foundation.
20
21// You should have received a copy of the GNU General Public License and
22// a copy of the GCC Runtime Library Exception along with this program;
23// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24// <http://www.gnu.org/licenses/>.
25
29
30#ifndef _GLIBCXX_VARIANT
31#define _GLIBCXX_VARIANT 1
32
33#pragma GCC system_header
34
35#if __cplusplus >= 201703L
36
37#include <bits/enable_special_members.h>
38#include <bits/exception_defines.h>
39#include <bits/functional_hash.h>
40#include <bits/invoke.h>
41#include <bits/parse_numbers.h>
42#include <bits/stl_construct.h>
43#include <bits/stl_iterator_base_funcs.h>
44#include <bits/utility.h> // in_place_index_t
45#include <initializer_list>
46#include <type_traits>
47#if __cplusplus >= 202002L
48#include <compare>
49#endif
50
51#if __cpp_concepts >= 202002L && __cpp_constexpr >= 201811L
52// P2231R1 constexpr needs constexpr unions and constrained destructors.
53#define __cpp_lib_variant 202106L
54#else
55#include <ext/aligned_buffer.h> // Use __aligned_membuf instead of union.
56#define __cpp_lib_variant 202102L
57#endif
58
59namespace std _GLIBCXX_VISIBILITY(default) {
60 _GLIBCXX_BEGIN_NAMESPACE_VERSION
61
62 template <typename... _Types>
63 class tuple;
64 template <typename... _Types>
65 class variant;
66 template <typename>
67 struct hash;
68
69 template <typename _Variant>
70 struct variant_size;
71
72 template <typename _Variant>
73 struct variant_size<const _Variant> : variant_size<_Variant> {};
74
75 template <typename _Variant>
76 struct variant_size<volatile _Variant> : variant_size<_Variant> {};
77
78 template <typename _Variant>
79 struct variant_size<const volatile _Variant> : variant_size<_Variant> {};
80
81 template <typename... _Types>
82 struct variant_size<variant<_Types...>> : std::integral_constant<size_t, sizeof...(_Types)> {};
83
84 template <typename _Variant>
85 inline constexpr size_t variant_size_v = variant_size<_Variant>::value;
86
87 template <typename... _Types>
88 inline constexpr size_t variant_size_v<variant<_Types...>> = sizeof...(_Types);
89
90 template <typename... _Types>
91 inline constexpr size_t variant_size_v<const variant<_Types...>> = sizeof...(_Types);
92
93 template <size_t _Np, typename _Variant>
94 struct variant_alternative;
95
96 template <size_t _Np, typename... _Types>
97 struct variant_alternative<_Np, variant<_Types...>> {
98 static_assert(_Np < sizeof...(_Types));
99
100 using type = typename _Nth_type<_Np, _Types...>::type;
101 };
102
103 template <size_t _Np, typename _Variant>
104 using variant_alternative_t = typename variant_alternative<_Np, _Variant>::type;
105
106 template <size_t _Np, typename _Variant>
107 struct variant_alternative<_Np, const _Variant> {
108 using type = const variant_alternative_t<_Np, _Variant>;
109 };
110
111 template <size_t _Np, typename _Variant>
112 struct variant_alternative<_Np, volatile _Variant> {
113 using type = volatile variant_alternative_t<_Np, _Variant>;
114 };
115
116 template <size_t _Np, typename _Variant>
117 struct variant_alternative<_Np, const volatile _Variant> {
118 using type = const volatile variant_alternative_t<_Np, _Variant>;
119 };
120
121 inline constexpr size_t variant_npos = -1;
122
123 template <size_t _Np, typename... _Types>
124 constexpr variant_alternative_t<_Np, variant<_Types...>>& get(variant<_Types...>&);
125
126 template <size_t _Np, typename... _Types>
127 constexpr variant_alternative_t<_Np, variant<_Types...>>&& get(variant<_Types...>&&);
128
129 template <size_t _Np, typename... _Types>
130 constexpr variant_alternative_t<_Np, variant<_Types...>> const& get(const variant<_Types...>&);
131
132 template <size_t _Np, typename... _Types>
133 constexpr variant_alternative_t<_Np, variant<_Types...>> const&& get(
134 const variant<_Types...>&&);
135
136 template <typename _Result_type, typename _Visitor, typename... _Variants>
137 constexpr decltype(auto) __do_visit(_Visitor&& __visitor, _Variants&&... __variants);
138
139 template <typename... _Types, typename _Tp>
140 _GLIBCXX20_CONSTEXPR decltype(auto) __variant_cast(_Tp&& __rhs) {
141 if constexpr (is_lvalue_reference_v<_Tp>) {
142 if constexpr (is_const_v<remove_reference_t<_Tp>>)
143 return static_cast<const variant<_Types...>&>(__rhs);
144 else
145 return static_cast<variant<_Types...>&>(__rhs);
146 } else
147 return static_cast<variant<_Types...>&&>(__rhs);
148 }
149
150 namespace __detail {
151 namespace __variant {
152 // used for raw visitation
153 struct __variant_cookie {};
154 // used for raw visitation with indices passed in
155 struct __variant_idx_cookie {
156 using type = __variant_idx_cookie;
157 };
158 // Used to enable deduction (and same-type checking) for std::visit:
159 template <typename _Tp>
160 struct __deduce_visit_result {
161 using type = _Tp;
162 };
163
164 // Visit variants that might be valueless.
165 template <typename _Visitor, typename... _Variants>
166 constexpr void __raw_visit(_Visitor&& __visitor, _Variants&&... __variants) {
167 std::__do_visit<__variant_cookie>(std::forward<_Visitor>(__visitor),
168 std::forward<_Variants>(__variants)...);
169 }
170
171 // Visit variants that might be valueless, passing indices to the visitor.
172 template <typename _Visitor, typename... _Variants>
173 constexpr void __raw_idx_visit(_Visitor&& __visitor, _Variants&&... __variants) {
174 std::__do_visit<__variant_idx_cookie>(std::forward<_Visitor>(__visitor),
175 std::forward<_Variants>(__variants)...);
176 }
177
178 // The __as function templates implement the exposition-only "as-variant"
179
180 template <typename... _Types>
181 constexpr std::variant<_Types...>& __as(std::variant<_Types...>& __v) noexcept {
182 return __v;
183 }
184
185 template <typename... _Types>
186 constexpr const std::variant<_Types...>& __as(
187 const std::variant<_Types...>& __v) noexcept {
188 return __v;
189 }
190
191 template <typename... _Types>
192 constexpr std::variant<_Types...>&& __as(std::variant<_Types...>&& __v) noexcept {
193 return std::move(__v);
194 }
195
196 template <typename... _Types>
197 constexpr const std::variant<_Types...>&& __as(
198 const std::variant<_Types...>&& __v) noexcept {
199 return std::move(__v);
200 }
201
202 // For C++17:
203 // _Uninitialized<T> is guaranteed to be a trivially destructible type,
204 // even if T is not.
205 // For C++20:
206 // _Uninitialized<T> is trivially destructible iff T is, so _Variant_union
207 // needs a constrained non-trivial destructor.
208 template <typename _Type, bool = std::is_trivially_destructible_v<_Type>>
209 struct _Uninitialized;
210
211 template <typename _Type>
212 struct _Uninitialized<_Type, true> {
213 template <typename... _Args>
214 constexpr _Uninitialized(in_place_index_t<0>, _Args&&... __args)
215 : _M_storage(std::forward<_Args>(__args)...) {}
216
217 constexpr const _Type& _M_get() const& noexcept { return _M_storage; }
218
219 constexpr _Type& _M_get() & noexcept { return _M_storage; }
220
221 constexpr const _Type&& _M_get() const&& noexcept { return std::move(_M_storage); }
222
223 constexpr _Type&& _M_get() && noexcept { return std::move(_M_storage); }
224
225 _Type _M_storage;
226 };
227
228 template <typename _Type>
229 struct _Uninitialized<_Type, false> {
230#if __cpp_lib_variant >= 202106L
231 template <typename... _Args>
232 constexpr _Uninitialized(in_place_index_t<0>, _Args&&... __args)
233 : _M_storage(std::forward<_Args>(__args)...) {}
234
235 constexpr ~_Uninitialized() {}
236
237 _Uninitialized(const _Uninitialized&) = default;
238 _Uninitialized(_Uninitialized&&) = default;
239 _Uninitialized& operator=(const _Uninitialized&) = default;
240 _Uninitialized& operator=(_Uninitialized&&) = default;
241
242 constexpr const _Type& _M_get() const& noexcept { return _M_storage; }
243
244 constexpr _Type& _M_get() & noexcept { return _M_storage; }
245
246 constexpr const _Type&& _M_get() const&& noexcept { return std::move(_M_storage); }
247
248 constexpr _Type&& _M_get() && noexcept { return std::move(_M_storage); }
249
250 struct _Empty_byte {};
251
252 union {
253 _Empty_byte _M_empty;
254 _Type _M_storage;
255 };
256#else
257 template <typename... _Args>
258 constexpr _Uninitialized(in_place_index_t<0>, _Args&&... __args) {
259 ::new ((void*)std::addressof(_M_storage)) _Type(std::forward<_Args>(__args)...);
260 }
261
262 const _Type& _M_get() const& noexcept { return *_M_storage._M_ptr(); }
263
264 _Type& _M_get() & noexcept { return *_M_storage._M_ptr(); }
265
266 const _Type&& _M_get() const&& noexcept { return std::move(*_M_storage._M_ptr()); }
267
268 _Type&& _M_get() && noexcept { return std::move(*_M_storage._M_ptr()); }
269
270 __gnu_cxx::__aligned_membuf<_Type> _M_storage;
271#endif
272 };
273
274 template <size_t _Np, typename _Union>
275 constexpr decltype(auto) __get_n(_Union&& __u) noexcept {
276 if constexpr (_Np == 0)
277 return std::forward<_Union>(__u)._M_first._M_get();
278 else if constexpr (_Np == 1)
279 return std::forward<_Union>(__u)._M_rest._M_first._M_get();
280 else if constexpr (_Np == 2)
281 return std::forward<_Union>(__u)._M_rest._M_rest._M_first._M_get();
282 else
283 return __variant::__get_n<_Np - 3>(
284 std::forward<_Union>(__u)._M_rest._M_rest._M_rest);
285 }
286
287 // Returns the typed storage for __v.
288 template <size_t _Np, typename _Variant>
289 constexpr decltype(auto) __get(_Variant&& __v) noexcept {
290 return __variant::__get_n<_Np>(std::forward<_Variant>(__v)._M_u);
291 }
292
293 template <typename... _Types>
294 struct _Traits {
295 static constexpr bool _S_default_ctor =
296 is_default_constructible_v<typename _Nth_type<0, _Types...>::type>;
297 static constexpr bool _S_copy_ctor = (is_copy_constructible_v<_Types> && ...);
298 static constexpr bool _S_move_ctor = (is_move_constructible_v<_Types> && ...);
299 static constexpr bool _S_copy_assign =
300 _S_copy_ctor && (is_copy_assignable_v<_Types> && ...);
301 static constexpr bool _S_move_assign =
302 _S_move_ctor && (is_move_assignable_v<_Types> && ...);
303
304 static constexpr bool _S_trivial_dtor =
305 (is_trivially_destructible_v<_Types> && ...);
306 static constexpr bool _S_trivial_copy_ctor =
307 (is_trivially_copy_constructible_v<_Types> && ...);
308 static constexpr bool _S_trivial_move_ctor =
309 (is_trivially_move_constructible_v<_Types> && ...);
310 static constexpr bool _S_trivial_copy_assign =
311 _S_trivial_dtor && _S_trivial_copy_ctor
312 && (is_trivially_copy_assignable_v<_Types> && ...);
313 static constexpr bool _S_trivial_move_assign =
314 _S_trivial_dtor && _S_trivial_move_ctor
315 && (is_trivially_move_assignable_v<_Types> && ...);
316
317 // The following nothrow traits are for non-trivial SMFs. Trivial SMFs
318 // are always nothrow.
319 static constexpr bool _S_nothrow_default_ctor =
320 is_nothrow_default_constructible_v<typename _Nth_type<0, _Types...>::type>;
321 static constexpr bool _S_nothrow_copy_ctor = false;
322 static constexpr bool _S_nothrow_move_ctor =
323 (is_nothrow_move_constructible_v<_Types> && ...);
324 static constexpr bool _S_nothrow_copy_assign = false;
325 static constexpr bool _S_nothrow_move_assign =
326 _S_nothrow_move_ctor && (is_nothrow_move_assignable_v<_Types> && ...);
327 };
328
329 // Defines members and ctors.
330 template <typename... _Types>
331 union _Variadic_union {
332 _Variadic_union() = default;
333
334 template <size_t _Np, typename... _Args>
335 _Variadic_union(in_place_index_t<_Np>, _Args&&...) = delete;
336 };
337
338 template <typename _First, typename... _Rest>
339 union _Variadic_union<_First, _Rest...> {
340 constexpr _Variadic_union()
341 : _M_rest() {}
342
343 template <typename... _Args>
344 constexpr _Variadic_union(in_place_index_t<0>, _Args&&... __args)
345 : _M_first(in_place_index<0>, std::forward<_Args>(__args)...) {}
346
347 template <size_t _Np, typename... _Args>
348 constexpr _Variadic_union(in_place_index_t<_Np>, _Args&&... __args)
349 : _M_rest(in_place_index<_Np - 1>, std::forward<_Args>(__args)...) {}
350
351#if __cpp_lib_variant >= 202106L
352 _Variadic_union(const _Variadic_union&) = default;
353 _Variadic_union(_Variadic_union&&) = default;
354 _Variadic_union& operator=(const _Variadic_union&) = default;
355 _Variadic_union& operator=(_Variadic_union&&) = default;
356
357 ~_Variadic_union(){};
358
359 constexpr ~_Variadic_union()
360 requires(!__has_trivial_destructor(_First))
361 || (!__has_trivial_destructor(_Variadic_union<_Rest...>))
362 {}
363#endif
364
365 _Uninitialized<_First> _M_first;
366 _Variadic_union<_Rest...> _M_rest;
367 };
368
369 // _Never_valueless_alt is true for variant alternatives that can
370 // always be placed in a variant without it becoming valueless.
371
372 // For suitably-small, trivially copyable types we can create temporaries
373 // on the stack and then memcpy them into place.
374 template <typename _Tp>
375 struct _Never_valueless_alt
376 : __and_<bool_constant<sizeof(_Tp) <= 256>, is_trivially_copyable<_Tp>> {};
377
378 // Specialize _Never_valueless_alt for other types which have a
379 // non-throwing and cheap move construction and move assignment operator,
380 // so that emplacing the type will provide the strong exception-safety
381 // guarantee, by creating and moving a temporary.
382 // Whether _Never_valueless_alt<T> is true or not affects the ABI of a
383 // variant using that alternative, so we can't change the value later!
384
385 // True if every alternative in _Types... can be emplaced in a variant
386 // without it becoming valueless. If this is true, variant<_Types...>
387 // can never be valueless, which enables some minor optimizations.
388 template <typename... _Types>
389 constexpr bool __never_valueless() {
390 return _Traits<_Types...>::_S_move_assign
391 && (_Never_valueless_alt<_Types>::value && ...);
392 }
393
394 // Defines index and the dtor, possibly trivial.
395 template <bool __trivially_destructible, typename... _Types>
396 struct _Variant_storage;
397
398 template <typename... _Types>
399 using __select_index =
400 typename __select_int::_Select_int_base<sizeof...(_Types), unsigned char,
401 unsigned short>::type::value_type;
402
403 template <typename... _Types>
404 struct _Variant_storage<false, _Types...> {
405 constexpr _Variant_storage()
406 : _M_index(static_cast<__index_type>(variant_npos)) {}
407
408 template <size_t _Np, typename... _Args>
409 constexpr _Variant_storage(in_place_index_t<_Np>, _Args&&... __args)
410 : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...)
411 , _M_index{_Np} {}
412
413 constexpr void _M_reset() {
414 if (!_M_valid()) [[unlikely]]
415 return;
416
417 std::__do_visit<void>(
418 [](auto&& __this_mem) mutable {
419 std::_Destroy(std::__addressof(__this_mem));
420 },
421 __variant_cast<_Types...>(*this));
422
423 _M_index = static_cast<__index_type>(variant_npos);
424 }
425
426 _GLIBCXX20_CONSTEXPR
427 ~_Variant_storage() { _M_reset(); }
428
429 constexpr bool _M_valid() const noexcept {
430 if constexpr (__variant::__never_valueless<_Types...>())
431 return true;
432 return this->_M_index != __index_type(variant_npos);
433 }
434
435 _Variadic_union<_Types...> _M_u;
436 using __index_type = __select_index<_Types...>;
437 __index_type _M_index;
438 };
439
440 template <typename... _Types>
441 struct _Variant_storage<true, _Types...> {
442 constexpr _Variant_storage()
443 : _M_index(static_cast<__index_type>(variant_npos)) {}
444
445 template <size_t _Np, typename... _Args>
446 constexpr _Variant_storage(in_place_index_t<_Np>, _Args&&... __args)
447 : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...)
448 , _M_index{_Np} {}
449
450 constexpr void _M_reset() noexcept {
451 _M_index = static_cast<__index_type>(variant_npos);
452 }
453
454 constexpr bool _M_valid() const noexcept {
455 if constexpr (__variant::__never_valueless<_Types...>())
456 return true;
457 // It would be nice if we could just return true for -fno-exceptions.
458 // It's possible (but inadvisable) that a std::variant could become
459 // valueless in a translation unit compiled with -fexceptions and then
460 // be passed to functions compiled with -fno-exceptions. We would need
461 // some #ifdef _GLIBCXX_NO_EXCEPTIONS_GLOBALLY property to elide all
462 // checks for valueless_by_exception().
463 return this->_M_index != static_cast<__index_type>(variant_npos);
464 }
465
466 _Variadic_union<_Types...> _M_u;
467 using __index_type = __select_index<_Types...>;
468 __index_type _M_index;
469 };
470
471 // Implementation of v.emplace<N>(args...).
472 template <size_t _Np, bool _Triv, typename... _Types, typename... _Args>
473 _GLIBCXX20_CONSTEXPR inline void __emplace(_Variant_storage<_Triv, _Types...>& __v,
474 _Args&&... __args) {
475 __v._M_reset();
476 auto* __addr = std::__addressof(__variant::__get_n<_Np>(__v._M_u));
477 std::_Construct(__addr, std::forward<_Args>(__args)...);
478 // Construction didn't throw, so can set the new index now:
479 __v._M_index = _Np;
480 }
481
482 template <typename... _Types>
483 using _Variant_storage_alias =
484 _Variant_storage<_Traits<_Types...>::_S_trivial_dtor, _Types...>;
485
486 // The following are (Copy|Move) (ctor|assign) layers for forwarding
487 // triviality and handling non-trivial SMF behaviors.
488
489 template <bool, typename... _Types>
490 struct _Copy_ctor_base : _Variant_storage_alias<_Types...> {
491 using _Base = _Variant_storage_alias<_Types...>;
492 using _Base::_Base;
493
494 _GLIBCXX20_CONSTEXPR
495 _Copy_ctor_base(const _Copy_ctor_base& __rhs) noexcept(
496 _Traits<_Types...>::_S_nothrow_copy_ctor) {
497 __variant::__raw_idx_visit(
498 [this](auto&& __rhs_mem, auto __rhs_index) mutable {
499 constexpr size_t __j = __rhs_index;
500 if constexpr (__j != variant_npos)
501 std::_Construct(std::__addressof(this->_M_u), in_place_index<__j>,
502 __rhs_mem);
503 },
504 __variant_cast<_Types...>(__rhs));
505 this->_M_index = __rhs._M_index;
506 }
507
508 _Copy_ctor_base(_Copy_ctor_base&&) = default;
509 _Copy_ctor_base& operator=(const _Copy_ctor_base&) = default;
510 _Copy_ctor_base& operator=(_Copy_ctor_base&&) = default;
511 };
512
513 template <typename... _Types>
514 struct _Copy_ctor_base<true, _Types...> : _Variant_storage_alias<_Types...> {
515 using _Base = _Variant_storage_alias<_Types...>;
516 using _Base::_Base;
517 };
518
519 template <typename... _Types>
520 using _Copy_ctor_alias =
521 _Copy_ctor_base<_Traits<_Types...>::_S_trivial_copy_ctor, _Types...>;
522
523 template <bool, typename... _Types>
524 struct _Move_ctor_base : _Copy_ctor_alias<_Types...> {
525 using _Base = _Copy_ctor_alias<_Types...>;
526 using _Base::_Base;
527
528 _GLIBCXX20_CONSTEXPR
529 _Move_ctor_base(_Move_ctor_base&& __rhs) noexcept(
530 _Traits<_Types...>::_S_nothrow_move_ctor) {
531 __variant::__raw_idx_visit(
532 [this](auto&& __rhs_mem, auto __rhs_index) mutable {
533 constexpr size_t __j = __rhs_index;
534 if constexpr (__j != variant_npos)
535 std::_Construct(std::__addressof(this->_M_u), in_place_index<__j>,
536 std::forward<decltype(__rhs_mem)>(__rhs_mem));
537 },
538 __variant_cast<_Types...>(std::move(__rhs)));
539 this->_M_index = __rhs._M_index;
540 }
541
542 _Move_ctor_base(const _Move_ctor_base&) = default;
543 _Move_ctor_base& operator=(const _Move_ctor_base&) = default;
544 _Move_ctor_base& operator=(_Move_ctor_base&&) = default;
545 };
546
547 template <typename... _Types>
548 struct _Move_ctor_base<true, _Types...> : _Copy_ctor_alias<_Types...> {
549 using _Base = _Copy_ctor_alias<_Types...>;
550 using _Base::_Base;
551 };
552
553 template <typename... _Types>
554 using _Move_ctor_alias =
555 _Move_ctor_base<_Traits<_Types...>::_S_trivial_move_ctor, _Types...>;
556
557 template <bool, typename... _Types>
558 struct _Copy_assign_base : _Move_ctor_alias<_Types...> {
559 using _Base = _Move_ctor_alias<_Types...>;
560 using _Base::_Base;
561
562 _GLIBCXX20_CONSTEXPR
563 _Copy_assign_base& operator=(const _Copy_assign_base& __rhs) noexcept(
564 _Traits<_Types...>::_S_nothrow_copy_assign) {
565 __variant::__raw_idx_visit(
566 [this](auto&& __rhs_mem, auto __rhs_index) mutable {
567 constexpr size_t __j = __rhs_index;
568 if constexpr (__j == variant_npos)
569 this->_M_reset(); // Make *this valueless.
570 else if (this->_M_index == __j)
571 __variant::__get<__j>(*this) = __rhs_mem;
572 else {
573 using _Tj = typename _Nth_type<__j, _Types...>::type;
574 if constexpr (is_nothrow_copy_constructible_v<_Tj>
575 || !is_nothrow_move_constructible_v<_Tj>)
576 __variant::__emplace<__j>(*this, __rhs_mem);
577 else {
578 using _Variant = variant<_Types...>;
579 _Variant& __self = __variant_cast<_Types...>(*this);
580 __self = _Variant(in_place_index<__j>, __rhs_mem);
581 }
582 }
583 },
584 __variant_cast<_Types...>(__rhs));
585 return *this;
586 }
587
588 _Copy_assign_base(const _Copy_assign_base&) = default;
589 _Copy_assign_base(_Copy_assign_base&&) = default;
590 _Copy_assign_base& operator=(_Copy_assign_base&&) = default;
591 };
592
593 template <typename... _Types>
594 struct _Copy_assign_base<true, _Types...> : _Move_ctor_alias<_Types...> {
595 using _Base = _Move_ctor_alias<_Types...>;
596 using _Base::_Base;
597 };
598
599 template <typename... _Types>
600 using _Copy_assign_alias =
601 _Copy_assign_base<_Traits<_Types...>::_S_trivial_copy_assign, _Types...>;
602
603 template <bool, typename... _Types>
604 struct _Move_assign_base : _Copy_assign_alias<_Types...> {
605 using _Base = _Copy_assign_alias<_Types...>;
606 using _Base::_Base;
607
608 _GLIBCXX20_CONSTEXPR
609 _Move_assign_base& operator=(_Move_assign_base&& __rhs) noexcept(
610 _Traits<_Types...>::_S_nothrow_move_assign) {
611 __variant::__raw_idx_visit(
612 [this](auto&& __rhs_mem, auto __rhs_index) mutable {
613 constexpr size_t __j = __rhs_index;
614 if constexpr (__j != variant_npos) {
615 if (this->_M_index == __j)
616 __variant::__get<__j>(*this) = std::move(__rhs_mem);
617 else {
618 using _Tj = typename _Nth_type<__j, _Types...>::type;
619 if constexpr (is_nothrow_move_constructible_v<_Tj>)
620 __variant::__emplace<__j>(*this, std::move(__rhs_mem));
621 else {
622 using _Variant = variant<_Types...>;
623 _Variant& __self = __variant_cast<_Types...>(*this);
624 __self.template emplace<__j>(std::move(__rhs_mem));
625 }
626 }
627 } else
628 this->_M_reset();
629 },
630 __variant_cast<_Types...>(__rhs));
631 return *this;
632 }
633
634 _Move_assign_base(const _Move_assign_base&) = default;
635 _Move_assign_base(_Move_assign_base&&) = default;
636 _Move_assign_base& operator=(const _Move_assign_base&) = default;
637 };
638
639 template <typename... _Types>
640 struct _Move_assign_base<true, _Types...> : _Copy_assign_alias<_Types...> {
641 using _Base = _Copy_assign_alias<_Types...>;
642 using _Base::_Base;
643 };
644
645 template <typename... _Types>
646 using _Move_assign_alias =
647 _Move_assign_base<_Traits<_Types...>::_S_trivial_move_assign, _Types...>;
648
649 template <typename... _Types>
650 struct _Variant_base : _Move_assign_alias<_Types...> {
651 using _Base = _Move_assign_alias<_Types...>;
652
653 constexpr _Variant_base() noexcept(_Traits<_Types...>::_S_nothrow_default_ctor)
654 : _Variant_base(in_place_index<0>) {}
655
656 template <size_t _Np, typename... _Args>
657 constexpr explicit _Variant_base(in_place_index_t<_Np> __i, _Args&&... __args)
658 : _Base(__i, std::forward<_Args>(__args)...) {}
659
660 _Variant_base(const _Variant_base&) = default;
661 _Variant_base(_Variant_base&&) = default;
662 _Variant_base& operator=(const _Variant_base&) = default;
663 _Variant_base& operator=(_Variant_base&&) = default;
664 };
665
666 template <typename _Tp, typename... _Types>
667 inline constexpr bool __exactly_once =
668 std::__find_uniq_type_in_pack<_Tp, _Types...>() < sizeof...(_Types);
669
670 // Helper used to check for valid conversions that don't involve narrowing.
671 template <typename _Ti>
672 struct _Arr {
673 _Ti _M_x[1];
674 };
675
676 // "Build an imaginary function FUN(Ti) for each alternative type Ti"
677 template <size_t _Ind, typename _Tp, typename _Ti, typename = void>
678 struct _Build_FUN {
679 // This function means 'using _Build_FUN<I, T, Ti>::_S_fun;' is valid,
680 // but only static functions will be considered in the call below.
681 void _S_fun() = delete;
682 };
683
684 // "... for which Ti x[] = {std::forward<T>(t)}; is well-formed."
685 template <size_t _Ind, typename _Tp, typename _Ti>
686 struct _Build_FUN<_Ind, _Tp, _Ti, void_t<decltype(_Arr<_Ti>{{std::declval<_Tp>()}})>> {
687 // This is the FUN function for type _Ti, with index _Ind
688 static integral_constant<size_t, _Ind> _S_fun(_Ti);
689 };
690
691 template <typename _Tp, typename _Variant,
692 typename = make_index_sequence<variant_size_v<_Variant>>>
693 struct _Build_FUNs;
694
695 template <typename _Tp, typename... _Ti, size_t... _Ind>
696 struct _Build_FUNs<_Tp, variant<_Ti...>, index_sequence<_Ind...>>
697 : _Build_FUN<_Ind, _Tp, _Ti>... {
698 using _Build_FUN<_Ind, _Tp, _Ti>::_S_fun...;
699 };
700
701 // The index j of the overload FUN(Tj) selected by overload resolution
702 // for FUN(std::forward<_Tp>(t))
703 template <typename _Tp, typename _Variant>
704 using _FUN_type = decltype(_Build_FUNs<_Tp, _Variant>::_S_fun(std::declval<_Tp>()));
705
706 // The index selected for FUN(std::forward<T>(t)), or variant_npos if none.
707 template <typename _Tp, typename _Variant, typename = void>
708 inline constexpr size_t __accepted_index = variant_npos;
709
710 template <typename _Tp, typename _Variant>
711 inline constexpr size_t
712 __accepted_index<_Tp, _Variant, void_t<_FUN_type<_Tp, _Variant>>> =
713 _FUN_type<_Tp, _Variant>::value;
714
715 template <typename _Maybe_variant_cookie, typename _Variant,
716 typename = __remove_cvref_t<_Variant>>
717 inline constexpr bool __extra_visit_slot_needed = false;
718
719 template <typename _Var, typename... _Types>
720 inline constexpr bool
721 __extra_visit_slot_needed<__variant_cookie, _Var, variant<_Types...>> =
722 !__variant::__never_valueless<_Types...>();
723
724 template <typename _Var, typename... _Types>
725 inline constexpr bool
726 __extra_visit_slot_needed<__variant_idx_cookie, _Var, variant<_Types...>> =
727 !__variant::__never_valueless<_Types...>();
728
729 // Used for storing a multi-dimensional vtable.
730 template <typename _Tp, size_t... _Dimensions>
731 struct _Multi_array;
732
733 // Partial specialization with rank zero, stores a single _Tp element.
734 template <typename _Tp>
735 struct _Multi_array<_Tp> {
736 template <typename>
737 struct __untag_result : false_type {
738 using element_type = _Tp;
739 };
740
741#pragma GCC diagnostic push
742#pragma GCC diagnostic ignored "-Wignored-qualifiers"
743 template <typename... _Args>
744 struct __untag_result<const void (*)(_Args...)> : false_type {
745 using element_type = void (*)(_Args...);
746 };
747#pragma GCC diagnostic pop
748
749 template <typename... _Args>
750 struct __untag_result<__variant_cookie (*)(_Args...)> : false_type {
751 using element_type = void (*)(_Args...);
752 };
753
754 template <typename... _Args>
755 struct __untag_result<__variant_idx_cookie (*)(_Args...)> : false_type {
756 using element_type = void (*)(_Args...);
757 };
758
759 template <typename _Res, typename... _Args>
760 struct __untag_result<__deduce_visit_result<_Res> (*)(_Args...)> : true_type {
761 using element_type = _Res (*)(_Args...);
762 };
763
764 using __result_is_deduced = __untag_result<_Tp>;
765
766 constexpr const typename __untag_result<_Tp>::element_type& _M_access() const {
767 return _M_data;
768 }
769
770 typename __untag_result<_Tp>::element_type _M_data;
771 };
772
773 // Partial specialization with rank >= 1.
774 template <typename _Ret, typename _Visitor, typename... _Variants, size_t __first,
775 size_t... __rest>
776 struct _Multi_array<_Ret (*)(_Visitor, _Variants...), __first, __rest...> {
777 static constexpr size_t __index = sizeof...(_Variants) - sizeof...(__rest) - 1;
778
779 using _Variant = typename _Nth_type<__index, _Variants...>::type;
780
781 static constexpr int __do_cookie =
782 __extra_visit_slot_needed<_Ret, _Variant> ? 1 : 0;
783
784 using _Tp = _Ret (*)(_Visitor, _Variants...);
785
786 template <typename... _Args>
787 constexpr decltype(auto) _M_access(size_t __first_index,
788 _Args... __rest_indices) const {
789 return _M_arr[__first_index + __do_cookie]._M_access(__rest_indices...);
790 }
791
792 _Multi_array<_Tp, __rest...> _M_arr[__first + __do_cookie];
793 };
794
795 // Creates a multi-dimensional vtable recursively.
796 //
797 // For example,
798 // visit([](auto, auto){},
799 // variant<int, char>(), // typedef'ed as V1
800 // variant<float, double, long double>()) // typedef'ed as V2
801 // will trigger instantiations of:
802 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 2, 3>,
803 // tuple<V1&&, V2&&>, std::index_sequence<>>
804 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 3>,
805 // tuple<V1&&, V2&&>, std::index_sequence<0>>
806 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
807 // tuple<V1&&, V2&&>, std::index_sequence<0, 0>>
808 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
809 // tuple<V1&&, V2&&>, std::index_sequence<0, 1>>
810 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
811 // tuple<V1&&, V2&&>, std::index_sequence<0, 2>>
812 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 3>,
813 // tuple<V1&&, V2&&>, std::index_sequence<1>>
814 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
815 // tuple<V1&&, V2&&>, std::index_sequence<1, 0>>
816 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
817 // tuple<V1&&, V2&&>, std::index_sequence<1, 1>>
818 // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
819 // tuple<V1&&, V2&&>, std::index_sequence<1, 2>>
820 // The returned multi-dimensional vtable can be fast accessed by the visitor
821 // using index calculation.
822 template <typename _Array_type, typename _Index_seq>
823 struct __gen_vtable_impl;
824
825 // Defines the _S_apply() member that returns a _Multi_array populated
826 // with function pointers that perform the visitation expressions e(m)
827 // for each valid pack of indexes into the variant types _Variants.
828 //
829 // This partial specialization builds up the index sequences by recursively
830 // calling _S_apply() on the next specialization of __gen_vtable_impl.
831 // The base case of the recursion defines the actual function pointers.
832 template <typename _Result_type, typename _Visitor, size_t... __dimensions,
833 typename... _Variants, size_t... __indices>
834 struct __gen_vtable_impl<
835 _Multi_array<_Result_type (*)(_Visitor, _Variants...), __dimensions...>,
836 std::index_sequence<__indices...>> {
837 using _Next = remove_reference_t<
838 typename _Nth_type<sizeof...(__indices), _Variants...>::type>;
839 using _Array_type =
840 _Multi_array<_Result_type (*)(_Visitor, _Variants...), __dimensions...>;
841
842 static constexpr _Array_type _S_apply() {
843 _Array_type __vtable{};
844 _S_apply_all_alts(__vtable, make_index_sequence<variant_size_v<_Next>>());
845 return __vtable;
846 }
847
848 template <size_t... __var_indices>
849 static constexpr void _S_apply_all_alts(_Array_type& __vtable,
850 std::index_sequence<__var_indices...>) {
851 if constexpr (__extra_visit_slot_needed<_Result_type, _Next>)
852 (_S_apply_single_alt<true, __var_indices>(
853 __vtable._M_arr[__var_indices + 1], &(__vtable._M_arr[0])),
854 ...);
855 else
856 (_S_apply_single_alt<false, __var_indices>(__vtable._M_arr[__var_indices]),
857 ...);
858 }
859
860 template <bool __do_cookie, size_t __index, typename _Tp>
861 static constexpr void _S_apply_single_alt(_Tp& __element,
862 _Tp* __cookie_element = nullptr) {
863 if constexpr (__do_cookie) {
864 __element = __gen_vtable_impl<
865 _Tp, std::index_sequence<__indices..., __index>>::_S_apply();
866 *__cookie_element = __gen_vtable_impl<
867 _Tp, std::index_sequence<__indices..., variant_npos>>::_S_apply();
868 } else {
869 auto __tmp_element = __gen_vtable_impl<
870 remove_reference_t<decltype(__element)>,
871 std::index_sequence<__indices..., __index>>::_S_apply();
872 static_assert(is_same_v<_Tp, decltype(__tmp_element)>,
873 "std::visit requires the visitor to have the same "
874 "return type for all alternatives of a variant");
875 __element = __tmp_element;
876 }
877 }
878 };
879
880 // This partial specialization is the base case for the recursion.
881 // It populates a _Multi_array element with the address of a function
882 // that invokes the visitor with the alternatives specified by __indices.
883 template <typename _Result_type, typename _Visitor, typename... _Variants,
884 size_t... __indices>
885 struct __gen_vtable_impl<_Multi_array<_Result_type (*)(_Visitor, _Variants...)>,
886 std::index_sequence<__indices...>> {
887 using _Array_type = _Multi_array<_Result_type (*)(_Visitor, _Variants...)>;
888
889 template <size_t __index, typename _Variant>
890 static constexpr decltype(auto) __element_by_index_or_cookie(
891 _Variant&& __var) noexcept {
892 if constexpr (__index != variant_npos)
893 return __variant::__get<__index>(std::forward<_Variant>(__var));
894 else
895 return __variant_cookie{};
896 }
897
898 static constexpr decltype(auto) __visit_invoke(_Visitor&& __visitor,
899 _Variants... __vars) {
900 if constexpr (is_same_v<_Result_type, __variant_idx_cookie>)
901 // For raw visitation using indices, pass the indices to the visitor
902 // and discard the return value:
903 std::__invoke(std::forward<_Visitor>(__visitor),
904 __element_by_index_or_cookie<__indices>(
905 std::forward<_Variants>(__vars))...,
906 integral_constant<size_t, __indices>()...);
907 else if constexpr (is_same_v<_Result_type, __variant_cookie>)
908 // For raw visitation without indices, and discard the return value:
909 std::__invoke(std::forward<_Visitor>(__visitor),
910 __element_by_index_or_cookie<__indices>(
911 std::forward<_Variants>(__vars))...);
912 else if constexpr (_Array_type::__result_is_deduced::value)
913 // For the usual std::visit case deduce the return value:
914 return std::__invoke(std::forward<_Visitor>(__visitor),
915 __element_by_index_or_cookie<__indices>(
916 std::forward<_Variants>(__vars))...);
917 else // for std::visit<R> use INVOKE<R>
918 return std::__invoke_r<_Result_type>(
919 std::forward<_Visitor>(__visitor),
920 __variant::__get<__indices>(std::forward<_Variants>(__vars))...);
921 }
922
923 static constexpr auto _S_apply() {
924 if constexpr (_Array_type::__result_is_deduced::value) {
925 constexpr bool __visit_ret_type_mismatch =
926 !is_same_v<typename _Result_type::type,
927 decltype(__visit_invoke(std::declval<_Visitor>(),
928 std::declval<_Variants>()...))>;
929 if constexpr (__visit_ret_type_mismatch) {
930 struct __cannot_match {};
931 return __cannot_match{};
932 } else
933 return _Array_type{&__visit_invoke};
934 } else
935 return _Array_type{&__visit_invoke};
936 }
937 };
938
939 template <typename _Result_type, typename _Visitor, typename... _Variants>
940 struct __gen_vtable {
941 using _Array_type = _Multi_array<_Result_type (*)(_Visitor, _Variants...),
942 variant_size_v<remove_reference_t<_Variants>>...>;
943
944 static constexpr _Array_type _S_vtable =
945 __gen_vtable_impl<_Array_type, std::index_sequence<>>::_S_apply();
946 };
947
948 template <size_t _Np, typename _Tp>
949 struct _Base_dedup : public _Tp {};
950
951 template <typename _Variant, typename __indices>
952 struct _Variant_hash_base;
953
954 template <typename... _Types, size_t... __indices>
955 struct _Variant_hash_base<variant<_Types...>, std::index_sequence<__indices...>>
956 : _Base_dedup<__indices, __poison_hash<remove_const_t<_Types>>>... {};
957
958 // Equivalent to decltype(get<_Np>(as-variant(declval<_Variant>())))
959 template <size_t _Np, typename _Variant,
960 typename _AsV = decltype(__variant::__as(std::declval<_Variant>())),
961 typename _Tp = variant_alternative_t<_Np, remove_reference_t<_AsV>>>
962 using __get_t = __conditional_t<is_lvalue_reference_v<_Variant>, _Tp&, _Tp&&>;
963
964 // Return type of std::visit.
965 template <typename _Visitor, typename... _Variants>
966 using __visit_result_t = invoke_result_t<_Visitor, __get_t<0, _Variants>...>;
967
968 template <typename _Tp, typename... _Types>
969 constexpr inline bool __same_types = (is_same_v<_Tp, _Types> && ...);
970
971 template <typename _Visitor, typename _Variant, size_t... _Idxs>
972 constexpr bool __check_visitor_results(std::index_sequence<_Idxs...>) {
973 return __same_types<invoke_result_t<_Visitor, __get_t<_Idxs, _Variant>>...>;
974 }
975
976 } // namespace __variant
977 } // namespace __detail
978
979 template <typename _Tp, typename... _Types>
980 constexpr bool holds_alternative(const variant<_Types...>& __v) noexcept {
981 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
982 "T must occur exactly once in alternatives");
983 return __v.index() == std::__find_uniq_type_in_pack<_Tp, _Types...>();
984 }
985
986 template <typename _Tp, typename... _Types>
987 constexpr _Tp& get(variant<_Types...>& __v) {
988 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
989 "T must occur exactly once in alternatives");
990 static_assert(!is_void_v<_Tp>, "_Tp must not be void");
991 constexpr size_t __n = std::__find_uniq_type_in_pack<_Tp, _Types...>();
992 return std::get<__n>(__v);
993 }
994
995 template <typename _Tp, typename... _Types>
996 constexpr _Tp&& get(variant<_Types...>&& __v) {
997 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
998 "T must occur exactly once in alternatives");
999 static_assert(!is_void_v<_Tp>, "_Tp must not be void");
1000 constexpr size_t __n = std::__find_uniq_type_in_pack<_Tp, _Types...>();
1001 return std::get<__n>(std::move(__v));
1002 }
1003
1004 template <typename _Tp, typename... _Types>
1005 constexpr const _Tp& get(const variant<_Types...>& __v) {
1006 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
1007 "T must occur exactly once in alternatives");
1008 static_assert(!is_void_v<_Tp>, "_Tp must not be void");
1009 constexpr size_t __n = std::__find_uniq_type_in_pack<_Tp, _Types...>();
1010 return std::get<__n>(__v);
1011 }
1012
1013 template <typename _Tp, typename... _Types>
1014 constexpr const _Tp&& get(const variant<_Types...>&& __v) {
1015 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
1016 "T must occur exactly once in alternatives");
1017 static_assert(!is_void_v<_Tp>, "_Tp must not be void");
1018 constexpr size_t __n = std::__find_uniq_type_in_pack<_Tp, _Types...>();
1019 return std::get<__n>(std::move(__v));
1020 }
1021
1022 template <size_t _Np, typename... _Types>
1023 constexpr add_pointer_t<variant_alternative_t<_Np, variant<_Types...>>> get_if(
1024 variant<_Types...>* __ptr) noexcept {
1025 using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>;
1026 static_assert(_Np < sizeof...(_Types), "The index must be in [0, number of alternatives)");
1027 static_assert(!is_void_v<_Alternative_type>, "_Tp must not be void");
1028 if (__ptr && __ptr->index() == _Np)
1029 return std::addressof(__detail::__variant::__get<_Np>(*__ptr));
1030 return nullptr;
1031 }
1032
1033 template <size_t _Np, typename... _Types>
1034 constexpr add_pointer_t<const variant_alternative_t<_Np, variant<_Types...>>> get_if(
1035 const variant<_Types...>* __ptr) noexcept {
1036 using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>;
1037 static_assert(_Np < sizeof...(_Types), "The index must be in [0, number of alternatives)");
1038 static_assert(!is_void_v<_Alternative_type>, "_Tp must not be void");
1039 if (__ptr && __ptr->index() == _Np)
1040 return std::addressof(__detail::__variant::__get<_Np>(*__ptr));
1041 return nullptr;
1042 }
1043
1044 template <typename _Tp, typename... _Types>
1045 constexpr add_pointer_t<_Tp> get_if(variant<_Types...>* __ptr) noexcept {
1046 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
1047 "T must occur exactly once in alternatives");
1048 static_assert(!is_void_v<_Tp>, "_Tp must not be void");
1049 constexpr size_t __n = std::__find_uniq_type_in_pack<_Tp, _Types...>();
1050 return std::get_if<__n>(__ptr);
1051 }
1052
1053 template <typename _Tp, typename... _Types>
1054 constexpr add_pointer_t<const _Tp> get_if(const variant<_Types...>* __ptr) noexcept {
1055 static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
1056 "T must occur exactly once in alternatives");
1057 static_assert(!is_void_v<_Tp>, "_Tp must not be void");
1058 constexpr size_t __n = std::__find_uniq_type_in_pack<_Tp, _Types...>();
1059 return std::get_if<__n>(__ptr);
1060 }
1061
1062 struct monostate {};
1063
1064#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \
1065 template <typename... _Types> \
1066 constexpr bool operator __OP(const variant<_Types...>& __lhs, \
1067 const variant<_Types...>& __rhs) { \
1068 bool __ret = true; \
1069 __detail::__variant::__raw_idx_visit( \
1070 [&__ret, &__lhs](auto&& __rhs_mem, auto __rhs_index) mutable { \
1071 if constexpr (__rhs_index != variant_npos) { \
1072 if (__lhs.index() == __rhs_index) { \
1073 auto& __this_mem = std::get<__rhs_index>(__lhs); \
1074 __ret = __this_mem __OP __rhs_mem; \
1075 } else \
1076 __ret = (__lhs.index() + 1) __OP(__rhs_index + 1); \
1077 } else \
1078 __ret = (__lhs.index() + 1) __OP(__rhs_index + 1); \
1079 }, \
1080 __rhs); \
1081 return __ret; \
1082 }
1083
1084 _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less)
1085 _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal)
1086 _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
1087 _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal)
1088 _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal)
1089 _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater)
1090
1091#undef _VARIANT_RELATION_FUNCTION_TEMPLATE
1092
1093 constexpr bool operator==(monostate, monostate) noexcept {
1094 return true;
1095 }
1096
1097#ifdef __cpp_lib_three_way_comparison
1098 template <typename... _Types>
1099 requires(three_way_comparable<_Types> && ...)
1100 constexpr common_comparison_category_t<compare_three_way_result_t<_Types>...> operator<=>(
1101 const variant<_Types...>& __v, const variant<_Types...>& __w) {
1102 common_comparison_category_t<compare_three_way_result_t<_Types>...> __ret =
1103 strong_ordering::equal;
1104
1105 __detail::__variant::__raw_idx_visit(
1106 [&__ret, &__v](auto&& __w_mem, auto __w_index) mutable {
1107 if constexpr (__w_index != variant_npos) {
1108 if (__v.index() == __w_index) {
1109 auto& __this_mem = std::get<__w_index>(__v);
1110 __ret = __this_mem <=> __w_mem;
1111 return;
1112 }
1113 }
1114 __ret = (__v.index() + 1) <=> (__w_index + 1);
1115 },
1116 __w);
1117 return __ret;
1118 }
1119
1120 constexpr strong_ordering operator<=>(monostate, monostate) noexcept {
1121 return strong_ordering::equal;
1122 }
1123#else
1124 constexpr bool operator!=(monostate, monostate) noexcept {
1125 return false;
1126 }
1127 constexpr bool operator<(monostate, monostate) noexcept {
1128 return false;
1129 }
1130 constexpr bool operator>(monostate, monostate) noexcept {
1131 return false;
1132 }
1133 constexpr bool operator<=(monostate, monostate) noexcept {
1134 return true;
1135 }
1136 constexpr bool operator>=(monostate, monostate) noexcept {
1137 return true;
1138 }
1139#endif
1140
1141 template <typename _Visitor, typename... _Variants>
1142 constexpr __detail::__variant::__visit_result_t<_Visitor, _Variants...> visit(_Visitor&&,
1143 _Variants&&...);
1144
1145 template <typename... _Types>
1146 _GLIBCXX20_CONSTEXPR inline enable_if_t<(is_move_constructible_v<_Types> && ...)
1147 && (is_swappable_v<_Types> && ...)>
1148 swap(variant<_Types...>& __lhs,
1149 variant<_Types...>& __rhs) noexcept(noexcept(__lhs.swap(__rhs))) {
1150 __lhs.swap(__rhs);
1151 }
1152
1153 template <typename... _Types>
1154 enable_if_t<!((is_move_constructible_v<_Types> && ...) && (is_swappable_v<_Types> && ...))>
1155 swap(variant<_Types...>&, variant<_Types...>&) = delete;
1156
1157 class bad_variant_access : public exception {
1158 public:
1159 bad_variant_access() noexcept {}
1160
1161 const char* what() const noexcept override { return _M_reason; }
1162
1163 private:
1164 bad_variant_access(const char* __reason) noexcept
1165 : _M_reason(__reason) {}
1166
1167 // Must point to a string with static storage duration:
1168 const char* _M_reason = "bad variant access";
1169
1170 friend void __throw_bad_variant_access(const char* __what);
1171 };
1172
1173 // Must only be called with a string literal
1174 inline void __throw_bad_variant_access(const char* __what) {
1175 _GLIBCXX_THROW_OR_ABORT(bad_variant_access(__what));
1176 }
1177
1178 inline void __throw_bad_variant_access(bool __valueless) {
1179 if (__valueless) [[__unlikely__]]
1180 __throw_bad_variant_access("std::get: variant is valueless");
1181 else
1182 __throw_bad_variant_access("std::get: wrong index for variant");
1183 }
1184
1185 template <typename... _Types>
1186 class variant
1187 : private __detail::__variant::_Variant_base<_Types...>,
1188 private _Enable_default_constructor<
1189 __detail::__variant::_Traits<_Types...>::_S_default_ctor, variant<_Types...>>,
1190 private _Enable_copy_move<__detail::__variant::_Traits<_Types...>::_S_copy_ctor,
1191 __detail::__variant::_Traits<_Types...>::_S_copy_assign,
1192 __detail::__variant::_Traits<_Types...>::_S_move_ctor,
1193 __detail::__variant::_Traits<_Types...>::_S_move_assign,
1194 variant<_Types...>> {
1195 private:
1196 template <typename... _UTypes, typename _Tp>
1197 friend _GLIBCXX20_CONSTEXPR decltype(auto) __variant_cast(_Tp&&);
1198
1199 static_assert(sizeof...(_Types) > 0, "variant must have at least one alternative");
1200 static_assert(!(std::is_reference_v<_Types> || ...),
1201 "variant must have no reference alternative");
1202 static_assert(!(std::is_void_v<_Types> || ...), "variant must have no void alternative");
1203
1204 using _Base = __detail::__variant::_Variant_base<_Types...>;
1205 using _Default_ctor_enabler =
1206 _Enable_default_constructor<__detail::__variant::_Traits<_Types...>::_S_default_ctor,
1207 variant<_Types...>>;
1208
1209 template <typename _Tp>
1210 static constexpr bool __not_self = !is_same_v<__remove_cvref_t<_Tp>, variant>;
1211
1212 template <typename _Tp>
1213 static constexpr bool __exactly_once = __detail::__variant::__exactly_once<_Tp, _Types...>;
1214
1215 template <typename _Tp>
1216 static constexpr size_t __accepted_index =
1217 __detail::__variant::__accepted_index<_Tp, variant>;
1218
1219 template <size_t _Np, typename = enable_if_t<(_Np < sizeof...(_Types))>>
1220 using __to_type = typename _Nth_type<_Np, _Types...>::type;
1221
1222 template <typename _Tp, typename = enable_if_t<__not_self<_Tp>>>
1223 using __accepted_type = __to_type<__accepted_index<_Tp>>;
1224
1225 template <typename _Tp>
1226 static constexpr size_t __index_of = std::__find_uniq_type_in_pack<_Tp, _Types...>();
1227
1228 using _Traits = __detail::__variant::_Traits<_Types...>;
1229
1230 template <typename _Tp>
1231 struct __is_in_place_tag : false_type {};
1232 template <typename _Tp>
1233 struct __is_in_place_tag<in_place_type_t<_Tp>> : true_type {};
1234 template <size_t _Np>
1235 struct __is_in_place_tag<in_place_index_t<_Np>> : true_type {};
1236
1237 template <typename _Tp>
1238 static constexpr bool __not_in_place_tag = !__is_in_place_tag<__remove_cvref_t<_Tp>>::value;
1239
1240 public:
1241 variant() = default;
1242 variant(const variant& __rhs) = default;
1243 variant(variant&&) = default;
1244 variant& operator=(const variant&) = default;
1245 variant& operator=(variant&&) = default;
1246 _GLIBCXX20_CONSTEXPR ~variant() = default;
1247
1248 template <typename _Tp, typename = enable_if_t<sizeof...(_Types) != 0>,
1249 typename = enable_if_t<__not_in_place_tag<_Tp>>,
1250 typename _Tj = __accepted_type<_Tp&&>,
1251 typename = enable_if_t<__exactly_once<_Tj> && is_constructible_v<_Tj, _Tp>>>
1252 constexpr variant(_Tp&& __t) noexcept(is_nothrow_constructible_v<_Tj, _Tp>)
1253 : variant(in_place_index<__accepted_index<_Tp>>, std::forward<_Tp>(__t)) {}
1254
1255 template <typename _Tp, typename... _Args,
1256 typename = enable_if_t<__exactly_once<_Tp> && is_constructible_v<_Tp, _Args...>>>
1257 constexpr explicit variant(in_place_type_t<_Tp>, _Args&&... __args)
1258 : variant(in_place_index<__index_of<_Tp>>, std::forward<_Args>(__args)...) {}
1259
1260 template <
1261 typename _Tp, typename _Up, typename... _Args,
1262 typename = enable_if_t<__exactly_once<_Tp>
1263 && is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>>>
1264 constexpr explicit variant(in_place_type_t<_Tp>, initializer_list<_Up> __il,
1265 _Args&&... __args)
1266 : variant(in_place_index<__index_of<_Tp>>, __il, std::forward<_Args>(__args)...) {}
1267
1268 template <size_t _Np, typename... _Args, typename _Tp = __to_type<_Np>,
1269 typename = enable_if_t<is_constructible_v<_Tp, _Args...>>>
1270 constexpr explicit variant(in_place_index_t<_Np>, _Args&&... __args)
1271 : _Base(in_place_index<_Np>, std::forward<_Args>(__args)...)
1272 , _Default_ctor_enabler(_Enable_default_constructor_tag{}) {}
1273
1274 template <size_t _Np, typename _Up, typename... _Args, typename _Tp = __to_type<_Np>,
1275 typename = enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>>>
1276 constexpr explicit variant(in_place_index_t<_Np>, initializer_list<_Up> __il,
1277 _Args&&... __args)
1278 : _Base(in_place_index<_Np>, __il, std::forward<_Args>(__args)...)
1279 , _Default_ctor_enabler(_Enable_default_constructor_tag{}) {}
1280
1281 template <typename _Tp>
1282 _GLIBCXX20_CONSTEXPR enable_if_t<__exactly_once<__accepted_type<_Tp&&>>
1283 && is_constructible_v<__accepted_type<_Tp&&>, _Tp>
1284 && is_assignable_v<__accepted_type<_Tp&&>&, _Tp>,
1285 variant&>
1286 operator=(_Tp&& __rhs) noexcept(
1287 is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp>&&
1288 is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp>) {
1289 constexpr auto __index = __accepted_index<_Tp>;
1290 if (index() == __index)
1291 std::get<__index>(*this) = std::forward<_Tp>(__rhs);
1292 else {
1293 using _Tj = __accepted_type<_Tp&&>;
1294 if constexpr (is_nothrow_constructible_v<_Tj, _Tp>
1295 || !is_nothrow_move_constructible_v<_Tj>)
1296 this->emplace<__index>(std::forward<_Tp>(__rhs));
1297 else
1298 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1299 // 3585. converting assignment with immovable alternative
1300 this->emplace<__index>(_Tj(std::forward<_Tp>(__rhs)));
1301 }
1302 return *this;
1303 }
1304
1305 template <typename _Tp, typename... _Args>
1306 _GLIBCXX20_CONSTEXPR
1307 enable_if_t<is_constructible_v<_Tp, _Args...> && __exactly_once<_Tp>, _Tp&>
1308 emplace(_Args&&... __args) {
1309 constexpr size_t __index = __index_of<_Tp>;
1310 return this->emplace<__index>(std::forward<_Args>(__args)...);
1311 }
1312
1313 template <typename _Tp, typename _Up, typename... _Args>
1314 _GLIBCXX20_CONSTEXPR enable_if_t<
1315 is_constructible_v<_Tp, initializer_list<_Up>&, _Args...> && __exactly_once<_Tp>, _Tp&>
1316 emplace(initializer_list<_Up> __il, _Args&&... __args) {
1317 constexpr size_t __index = __index_of<_Tp>;
1318 return this->emplace<__index>(__il, std::forward<_Args>(__args)...);
1319 }
1320
1321 template <size_t _Np, typename... _Args>
1322 _GLIBCXX20_CONSTEXPR
1323 enable_if_t<is_constructible_v<__to_type<_Np>, _Args...>, __to_type<_Np>&>
1324 emplace(_Args&&... __args) {
1325 namespace __variant = std::__detail::__variant;
1326 using type = typename _Nth_type<_Np, _Types...>::type;
1327 // Provide the strong exception-safety guarantee when possible,
1328 // to avoid becoming valueless.
1329 if constexpr (is_nothrow_constructible_v<type, _Args...>) {
1330 __variant::__emplace<_Np>(*this, std::forward<_Args>(__args)...);
1331 } else if constexpr (is_scalar_v<type>) {
1332 // This might invoke a potentially-throwing conversion operator:
1333 const type __tmp(std::forward<_Args>(__args)...);
1334 // But this won't throw:
1335 __variant::__emplace<_Np>(*this, __tmp);
1336 } else if constexpr (__variant::_Never_valueless_alt<type>()
1337 && _Traits::_S_move_assign) {
1338 // This construction might throw:
1339 variant __tmp(in_place_index<_Np>, std::forward<_Args>(__args)...);
1340 // But _Never_valueless_alt<type> means this won't:
1341 *this = std::move(__tmp);
1342 } else {
1343 // This case only provides the basic exception-safety guarantee,
1344 // i.e. the variant can become valueless.
1345 __variant::__emplace<_Np>(*this, std::forward<_Args>(__args)...);
1346 }
1347 return std::get<_Np>(*this);
1348 }
1349
1350 template <size_t _Np, typename _Up, typename... _Args>
1351 _GLIBCXX20_CONSTEXPR enable_if_t<
1352 is_constructible_v<__to_type<_Np>, initializer_list<_Up>&, _Args...>, __to_type<_Np>&>
1353 emplace(initializer_list<_Up> __il, _Args&&... __args) {
1354 namespace __variant = std::__detail::__variant;
1355 using type = typename _Nth_type<_Np, _Types...>::type;
1356 // Provide the strong exception-safety guarantee when possible,
1357 // to avoid becoming valueless.
1358 if constexpr (is_nothrow_constructible_v<type, initializer_list<_Up>&, _Args...>) {
1359 __variant::__emplace<_Np>(*this, __il, std::forward<_Args>(__args)...);
1360 } else if constexpr (__variant::_Never_valueless_alt<type>()
1361 && _Traits::_S_move_assign) {
1362 // This construction might throw:
1363 variant __tmp(in_place_index<_Np>, __il, std::forward<_Args>(__args)...);
1364 // But _Never_valueless_alt<type> means this won't:
1365 *this = std::move(__tmp);
1366 } else {
1367 // This case only provides the basic exception-safety guarantee,
1368 // i.e. the variant can become valueless.
1369 __variant::__emplace<_Np>(*this, __il, std::forward<_Args>(__args)...);
1370 }
1371 return std::get<_Np>(*this);
1372 }
1373
1374 template <size_t _Np, typename... _Args>
1375 enable_if_t<!(_Np < sizeof...(_Types))> emplace(_Args&&...) = delete;
1376
1377 template <typename _Tp, typename... _Args>
1378 enable_if_t<!__exactly_once<_Tp>> emplace(_Args&&...) = delete;
1379
1380 constexpr bool valueless_by_exception() const noexcept { return !this->_M_valid(); }
1381
1382 constexpr size_t index() const noexcept {
1383 using __index_type = typename _Base::__index_type;
1384 if constexpr (__detail::__variant::__never_valueless<_Types...>())
1385 return this->_M_index;
1386 else if constexpr (sizeof...(_Types) <= __index_type(-1) / 2)
1387 return make_signed_t<__index_type>(this->_M_index);
1388 else
1389 return size_t(__index_type(this->_M_index + 1)) - 1;
1390 }
1391
1392 _GLIBCXX20_CONSTEXPR
1393 void swap(variant& __rhs) noexcept((__is_nothrow_swappable<_Types>::value && ...)
1394 && is_nothrow_move_constructible_v<variant>) {
1395 static_assert((is_move_constructible_v<_Types> && ...));
1396
1397 // Handle this here to simplify the visitation.
1398 if (__rhs.valueless_by_exception()) [[__unlikely__]] {
1399 if (!this->valueless_by_exception()) [[__likely__]]
1400 __rhs.swap(*this);
1401 return;
1402 }
1403
1404 namespace __variant = __detail::__variant;
1405
1406 __variant::__raw_idx_visit(
1407 [this, &__rhs](auto&& __rhs_mem, auto __rhs_index) mutable {
1408 constexpr size_t __j = __rhs_index;
1409 if constexpr (__j != variant_npos) {
1410 if (this->index() == __j) {
1411 using std::swap;
1412 swap(std::get<__j>(*this), __rhs_mem);
1413 } else {
1414 auto __tmp(std::move(__rhs_mem));
1415
1416 if constexpr (_Traits::_S_trivial_move_assign)
1417 __rhs = std::move(*this);
1418 else
1419 __variant::__raw_idx_visit(
1420 [&__rhs](auto&& __this_mem, auto __this_index) mutable {
1421 constexpr size_t __k = __this_index;
1422 if constexpr (__k != variant_npos)
1423 __variant::__emplace<__k>(__rhs, std::move(__this_mem));
1424 },
1425 *this);
1426
1427 __variant::__emplace<__j>(*this, std::move(__tmp));
1428 }
1429 }
1430 },
1431 __rhs);
1432 }
1433
1434#if defined(__clang__) && __clang_major__ <= 7
1435 public:
1436 using _Base::_M_u; // See https://bugs.llvm.org/show_bug.cgi?id=31852
1437#endif
1438
1439 private:
1440 template <size_t _Np, typename _Vp>
1441 friend constexpr decltype(auto) __detail::__variant::__get(_Vp&& __v) noexcept;
1442
1443#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP) \
1444 template <typename... _Tp> \
1445 friend constexpr bool operator __OP(const variant<_Tp...>& __lhs, \
1446 const variant<_Tp...>& __rhs);
1447
1448 _VARIANT_RELATION_FUNCTION_TEMPLATE(<)
1449 _VARIANT_RELATION_FUNCTION_TEMPLATE(<=)
1450 _VARIANT_RELATION_FUNCTION_TEMPLATE(==)
1451 _VARIANT_RELATION_FUNCTION_TEMPLATE(!=)
1452 _VARIANT_RELATION_FUNCTION_TEMPLATE(>=)
1453 _VARIANT_RELATION_FUNCTION_TEMPLATE(>)
1454
1455#undef _VARIANT_RELATION_FUNCTION_TEMPLATE
1456 };
1457
1458 template <size_t _Np, typename... _Types>
1459 constexpr variant_alternative_t<_Np, variant<_Types...>>& get(variant<_Types...>& __v) {
1460 static_assert(_Np < sizeof...(_Types), "The index must be in [0, number of alternatives)");
1461 if (__v.index() != _Np)
1462 __throw_bad_variant_access(__v.valueless_by_exception());
1463 return __detail::__variant::__get<_Np>(__v);
1464 }
1465
1466 template <size_t _Np, typename... _Types>
1467 constexpr variant_alternative_t<_Np, variant<_Types...>>&& get(variant<_Types...>&& __v) {
1468 static_assert(_Np < sizeof...(_Types), "The index must be in [0, number of alternatives)");
1469 if (__v.index() != _Np)
1470 __throw_bad_variant_access(__v.valueless_by_exception());
1471 return __detail::__variant::__get<_Np>(std::move(__v));
1472 }
1473
1474 template <size_t _Np, typename... _Types>
1475 constexpr const variant_alternative_t<_Np, variant<_Types...>>& get(
1476 const variant<_Types...>& __v) {
1477 static_assert(_Np < sizeof...(_Types), "The index must be in [0, number of alternatives)");
1478 if (__v.index() != _Np)
1479 __throw_bad_variant_access(__v.valueless_by_exception());
1480 return __detail::__variant::__get<_Np>(__v);
1481 }
1482
1483 template <size_t _Np, typename... _Types>
1484 constexpr const variant_alternative_t<_Np, variant<_Types...>>&& get(
1485 const variant<_Types...>&& __v) {
1486 static_assert(_Np < sizeof...(_Types), "The index must be in [0, number of alternatives)");
1487 if (__v.index() != _Np)
1488 __throw_bad_variant_access(__v.valueless_by_exception());
1489 return __detail::__variant::__get<_Np>(std::move(__v));
1490 }
1491
1493 template <typename _Result_type, typename _Visitor, typename... _Variants>
1494 constexpr decltype(auto) __do_visit(_Visitor&& __visitor, _Variants&&... __variants) {
1495 // Get the silly case of visiting no variants out of the way first.
1496 if constexpr (sizeof...(_Variants) == 0) {
1497 if constexpr (is_void_v<_Result_type>)
1498 return (void)std::forward<_Visitor>(__visitor)();
1499 else
1500 return std::forward<_Visitor>(__visitor)();
1501 } else {
1502 constexpr size_t __max = 11; // "These go to eleven."
1503
1504 // The type of the first variant in the pack.
1505 using _V0 = typename _Nth_type<0, _Variants...>::type;
1506 // The number of alternatives in that first variant.
1507 constexpr auto __n = variant_size_v<remove_reference_t<_V0>>;
1508
1509 if constexpr (sizeof...(_Variants) > 1 || __n > __max) {
1510 // Use a jump table for the general case.
1511 constexpr auto& __vtable =
1512 __detail::__variant::__gen_vtable<_Result_type, _Visitor&&,
1513 _Variants&&...>::_S_vtable;
1514
1515 auto __func_ptr = __vtable._M_access(__variants.index()...);
1516 return (*__func_ptr)(std::forward<_Visitor>(__visitor),
1517 std::forward<_Variants>(__variants)...);
1518 } else // We have a single variant with a small number of alternatives.
1519 {
1520 // A name for the first variant in the pack.
1521 _V0& __v0 = [](_V0& __v, ...) -> _V0& {
1522 return __v;
1523 }(__variants...);
1524
1525 using __detail::__variant::__gen_vtable_impl;
1526 using __detail::__variant::_Multi_array;
1527 using _Ma = _Multi_array<_Result_type (*)(_Visitor&&, _V0 &&)>;
1528
1529#ifdef _GLIBCXX_DEBUG
1530#define _GLIBCXX_VISIT_UNREACHABLE __builtin_trap
1531#else
1532#define _GLIBCXX_VISIT_UNREACHABLE __builtin_unreachable
1533#endif
1534
1535#define _GLIBCXX_VISIT_CASE(N) \
1536 case N: { \
1537 if constexpr (N < __n) { \
1538 return __gen_vtable_impl<_Ma, index_sequence<N>>::__visit_invoke( \
1539 std::forward<_Visitor>(__visitor), std::forward<_V0>(__v0)); \
1540 } else \
1541 _GLIBCXX_VISIT_UNREACHABLE(); \
1542 }
1543
1544 switch (__v0.index()) {
1545 _GLIBCXX_VISIT_CASE(0)
1546 _GLIBCXX_VISIT_CASE(1)
1547 _GLIBCXX_VISIT_CASE(2)
1548 _GLIBCXX_VISIT_CASE(3)
1549 _GLIBCXX_VISIT_CASE(4)
1550 _GLIBCXX_VISIT_CASE(5)
1551 _GLIBCXX_VISIT_CASE(6)
1552 _GLIBCXX_VISIT_CASE(7)
1553 _GLIBCXX_VISIT_CASE(8)
1554 _GLIBCXX_VISIT_CASE(9)
1555 _GLIBCXX_VISIT_CASE(10)
1556 case variant_npos:
1557 using __detail::__variant::__variant_cookie;
1558 using __detail::__variant::__variant_idx_cookie;
1559 if constexpr (is_same_v<_Result_type, __variant_idx_cookie>
1560 || is_same_v<_Result_type, __variant_cookie>) {
1561 using _Npos = index_sequence<variant_npos>;
1562 return __gen_vtable_impl<_Ma, _Npos>::__visit_invoke(
1563 std::forward<_Visitor>(__visitor), std::forward<_V0>(__v0));
1564 } else
1565 _GLIBCXX_VISIT_UNREACHABLE();
1566 default:
1567 _GLIBCXX_VISIT_UNREACHABLE();
1568 }
1569#undef _GLIBCXX_VISIT_CASE
1570#undef _GLIBCXX_VISIT_UNREACHABLE
1571 }
1572 }
1573 }
1575
1576 template <typename _Visitor, typename... _Variants>
1577 constexpr __detail::__variant::__visit_result_t<_Visitor, _Variants...> visit(
1578 _Visitor&& __visitor, _Variants&&... __variants) {
1579 namespace __variant = std::__detail::__variant;
1580
1581 if ((__variant::__as(__variants).valueless_by_exception() || ...))
1582 __throw_bad_variant_access("std::visit: variant is valueless");
1583
1584 using _Result_type = __detail::__variant::__visit_result_t<_Visitor, _Variants...>;
1585
1586 using _Tag = __detail::__variant::__deduce_visit_result<_Result_type>;
1587
1588 if constexpr (sizeof...(_Variants) == 1) {
1589 using _Vp = decltype(__variant::__as(std::declval<_Variants>()...));
1590
1591 constexpr bool __visit_rettypes_match =
1592 __detail::__variant::__check_visitor_results<_Visitor, _Vp>(
1593 make_index_sequence<variant_size_v<remove_reference_t<_Vp>>>());
1594 if constexpr (!__visit_rettypes_match) {
1595 static_assert(__visit_rettypes_match,
1596 "std::visit requires the visitor to have the same "
1597 "return type for all alternatives of a variant");
1598 return;
1599 } else
1600 return std::__do_visit<_Tag>(std::forward<_Visitor>(__visitor),
1601 static_cast<_Vp>(__variants)...);
1602 } else
1603 return std::__do_visit<_Tag>(std::forward<_Visitor>(__visitor),
1604 __variant::__as(std::forward<_Variants>(__variants))...);
1605 }
1606
1607#if __cplusplus > 201703L
1608 template <typename _Res, typename _Visitor, typename... _Variants>
1609 constexpr _Res visit(_Visitor&& __visitor, _Variants&&... __variants) {
1610 namespace __variant = std::__detail::__variant;
1611
1612 if ((__variant::__as(__variants).valueless_by_exception() || ...))
1613 __throw_bad_variant_access("std::visit<R>: variant is valueless");
1614
1615 return std::__do_visit<_Res>(std::forward<_Visitor>(__visitor),
1616 __variant::__as(std::forward<_Variants>(__variants))...);
1617 }
1618#endif
1619
1621 template <bool, typename... _Types>
1622 struct __variant_hash_call_base_impl {
1623 size_t operator()(const variant<_Types...>& __t) const
1624 noexcept((is_nothrow_invocable_v<hash<decay_t<_Types>>, _Types> && ...)) {
1625 size_t __ret;
1626 __detail::__variant::__raw_visit(
1627 [&__t, &__ret](auto&& __t_mem) mutable {
1628 using _Type = __remove_cvref_t<decltype(__t_mem)>;
1629 if constexpr (!is_same_v<_Type, __detail::__variant::__variant_cookie>)
1630 __ret = std::hash<size_t>{}(__t.index()) + std::hash<_Type>{}(__t_mem);
1631 else
1632 __ret = std::hash<size_t>{}(__t.index());
1633 },
1634 __t);
1635 return __ret;
1636 }
1637 };
1638
1639 template <typename... _Types>
1640 struct __variant_hash_call_base_impl<false, _Types...> {};
1641
1642 template <typename... _Types>
1643 using __variant_hash_call_base = __variant_hash_call_base_impl<
1644 (__poison_hash<remove_const_t<_Types>>::__enable_hash_call && ...), _Types...>;
1646
1647 template <typename... _Types>
1648 struct hash<variant<_Types...>>
1649 : private __detail::__variant::_Variant_hash_base<variant<_Types...>,
1650 std::index_sequence_for<_Types...>>,
1651 public __variant_hash_call_base<_Types...> {
1652 using result_type [[__deprecated__]] = size_t;
1653 using argument_type [[__deprecated__]] = variant<_Types...>;
1654 };
1655
1656 template <>
1657 struct hash<monostate> {
1658 using result_type [[__deprecated__]] = size_t;
1659 using argument_type [[__deprecated__]] = monostate;
1660
1661 size_t operator()(const monostate&) const noexcept {
1662 constexpr size_t __magic_monostate_hash = -7777;
1663 return __magic_monostate_hash;
1664 }
1665 };
1666
1667 template <typename... _Types>
1668 struct __is_fast_hash<hash<variant<_Types...>>>
1669 : bool_constant<(__is_fast_hash<_Types>::value && ...)> {};
1670
1671 _GLIBCXX_END_NAMESPACE_VERSION
1672} // namespace std _GLIBCXX_VISIBILITY(default)
1673
1674#endif // C++17
1675
1676#endif // _GLIBCXX_VARIANT
1677#else
1678#include <variant>
1679#endif
STL namespace.
KOKKOS_INLINE_FUNCTION auto & get(::ippl::Tuple< Ts... > &t)
Definition Tuple.h:362
bool operator!=(const NDIndex< Dim > &nd1, const NDIndex< Dim > &nd2)
Definition NDIndex.hpp:218
bool operator==(const NDIndex< Dim > &nd1, const NDIndex< Dim > &nd2)
Definition NDIndex.hpp:208