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