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>
44#include <bits/enable_special_members.h>
45#include <bits/exception_defines.h>
46#include <bits/functional_hash.h>
47#include <bits/invoke.h>
48#include <bits/monostate.h>
49#include <bits/parse_numbers.h> // _Select_int
50#include <bits/stl_iterator_base_funcs.h>
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)
590 std::_Construct(std::__addressof(this->_M_u),
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)
627 std::_Construct(std::__addressof(this->_M_u),
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,
979 std::index_sequence<__var_indices...>)
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)>,
1007 std::index_sequence<__indices..., __index>>::_S_apply();
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 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1391 // 2766. Swapping non-swappable types
1392 template<typename... _Types>
1393 enable_if_t<!((is_move_constructible_v<_Types> && ...)
1394 && (is_swappable_v<_Types> && ...))>
1395 swap(variant<_Types...>&, variant<_Types...>&) = delete;
1396
1397 [[noreturn]] void __throw_bad_variant_access(unsigned);
1398
1399 class bad_variant_access : public exception
1400 {
1401 public:
1402 bad_variant_access() noexcept { }
1403
1404 const char* what() const noexcept override
1405 { return _M_reason; }
1406
1407 private:
1408 // Must only be called with a string literal
1409 bad_variant_access(const char* __reason) noexcept : _M_reason(__reason) { }
1410
1411 // Must point to a string with static storage duration:
1412 const char* _M_reason = "bad variant access";
1413
1414 friend void __throw_bad_variant_access([[maybe_unused]] unsigned __n)
1415 {
1416 [[maybe_unused]] static constexpr const char* __reasons[] = {
1417 "std::get: wrong index for variant",
1418 "std::get: variant is valueless",
1419 "std::visit: variant is valueless",
1420 "std::visit<R>: variant is valueless",
1421 };
1422 _GLIBCXX_THROW_OR_ABORT(bad_variant_access(__reasons[__n % 4u]));
1423 }
1424 };
1425
1426 template<typename... _Types>
1427 class variant
1428 : private __detail::__variant::_Variant_base<_Types...>,
1429 private _Enable_copy_move<
1430 __detail::__variant::_Traits<_Types...>::_S_copy_ctor,
1431 __detail::__variant::_Traits<_Types...>::_S_copy_assign,
1432 __detail::__variant::_Traits<_Types...>::_S_move_ctor,
1433 __detail::__variant::_Traits<_Types...>::_S_move_assign,
1434 variant<_Types...>>
1435 {
1436 private:
1437 template <typename... _UTypes, typename _Tp>
1438 friend _GLIBCXX20_CONSTEXPR decltype(auto)
1439 __variant_cast(_Tp&&);
1440
1441 static_assert(sizeof...(_Types) > 0,
1442 "variant must have at least one alternative");
1443 static_assert(((std::is_object_v<_Types> && !is_array_v<_Types>) && ...),
1444 "variant alternatives must be non-array object types");
1445
1446 using _Base = __detail::__variant::_Variant_base<_Types...>;
1447
1448 template<typename _Tp>
1449 static constexpr bool __not_self
1450 = !is_same_v<__remove_cvref_t<_Tp>, variant>;
1451
1452 template<typename _Tp>
1453 static constexpr bool
1454 __exactly_once = __detail::__variant::__exactly_once<_Tp, _Types...>;
1455
1456 template<typename _Tp>
1457 static constexpr size_t __accepted_index
1458 = __detail::__variant::__accepted_index<_Tp, variant>;
1459
1460 template<size_t _Np, typename = enable_if_t<(_Np < sizeof...(_Types))>>
1461 using __to_type = typename _Nth_type<_Np, _Types...>::type;
1462
1463 template<typename _Tp, typename = enable_if_t<__not_self<_Tp>>>
1464 using __accepted_type = __to_type<__accepted_index<_Tp>>;
1465
1466 template<typename _Tp>
1467 static constexpr size_t __index_of
1468 = std::__find_uniq_type_in_pack<_Tp, _Types...>();
1469
1470 using _Traits = __detail::__variant::_Traits<_Types...>;
1471
1472 template<typename _Tp>
1473 static constexpr bool __not_in_place_tag
1474 = !__is_in_place_type_v<__remove_cvref_t<_Tp>>
1475 && !__is_in_place_index_v<__remove_cvref_t<_Tp>>;
1476
1477 public:
1478#if __cpp_concepts
1479 variant() requires is_default_constructible_v<__to_type<0>> = default;
1480#else
1481 template<typename _Tp0 = __to_type<0>,
1482 typename = enable_if_t<is_default_constructible_v<_Tp0>>>
1483 constexpr
1484 variant() noexcept(is_nothrow_default_constructible_v<__to_type<0>>)
1485 { }
1486#endif
1487
1488 variant(const variant& __rhs) = default;
1489 variant(variant&&) = default;
1490 variant& operator=(const variant&) = default;
1491 variant& operator=(variant&&) = default;
1492 _GLIBCXX20_CONSTEXPR ~variant() = default;
1493
1494 template<typename _Tp,
1495 typename = enable_if_t<sizeof...(_Types) != 0>,
1496 typename = enable_if_t<__not_in_place_tag<_Tp>>,
1497 typename _Tj = __accepted_type<_Tp&&>,
1498 typename = enable_if_t<__exactly_once<_Tj>
1499 && is_constructible_v<_Tj, _Tp>>>
1500 constexpr
1501 variant(_Tp&& __t)
1502 noexcept(is_nothrow_constructible_v<_Tj, _Tp>)
1503 : variant(in_place_index<__accepted_index<_Tp>>,
1504 std::forward<_Tp>(__t))
1505 { }
1506
1507 template<typename _Tp, typename... _Args,
1508 typename = enable_if_t<__exactly_once<_Tp>
1509 && is_constructible_v<_Tp, _Args...>>>
1510 constexpr explicit
1511 variant(in_place_type_t<_Tp>, _Args&&... __args)
1512 : variant(in_place_index<__index_of<_Tp>>,
1513 std::forward<_Args>(__args)...)
1514 { }
1515
1516 template<typename _Tp, typename _Up, typename... _Args,
1517 typename = enable_if_t<__exactly_once<_Tp>
1518 && is_constructible_v<_Tp,
1519 initializer_list<_Up>&, _Args...>>>
1520 constexpr explicit
1521 variant(in_place_type_t<_Tp>, initializer_list<_Up> __il,
1522 _Args&&... __args)
1523 : variant(in_place_index<__index_of<_Tp>>, __il,
1524 std::forward<_Args>(__args)...)
1525 { }
1526
1527 template<size_t _Np, typename... _Args,
1528 typename _Tp = __to_type<_Np>,
1529 typename = enable_if_t<is_constructible_v<_Tp, _Args...>>>
1530 constexpr explicit
1531 variant(in_place_index_t<_Np>, _Args&&... __args)
1532 : _Base(in_place_index<_Np>, std::forward<_Args>(__args)...)
1533 { }
1534
1535 template<size_t _Np, typename _Up, typename... _Args,
1536 typename _Tp = __to_type<_Np>,
1537 typename = enable_if_t<is_constructible_v<_Tp,
1538 initializer_list<_Up>&,
1539 _Args...>>>
1540 constexpr explicit
1541 variant(in_place_index_t<_Np>, initializer_list<_Up> __il,
1542 _Args&&... __args)
1543 : _Base(in_place_index<_Np>, __il, std::forward<_Args>(__args)...)
1544 { }
1545
1546 template<typename _Tp>
1547 _GLIBCXX20_CONSTEXPR
1548 enable_if_t<__exactly_once<__accepted_type<_Tp&&>>
1549 && is_constructible_v<__accepted_type<_Tp&&>, _Tp>
1550 && is_assignable_v<__accepted_type<_Tp&&>&, _Tp>,
1551 variant&>
1552 operator=(_Tp&& __rhs)
1553 noexcept(is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp>
1554 && is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp>)
1555 {
1556 constexpr auto __index = __accepted_index<_Tp>;
1557 if (index() == __index)
1558 std::get<__index>(*this) = std::forward<_Tp>(__rhs);
1559 else
1560 {
1561 using _Tj = __accepted_type<_Tp&&>;
1562 if constexpr (is_nothrow_constructible_v<_Tj, _Tp>
1563 || !is_nothrow_move_constructible_v<_Tj>)
1564 this->emplace<__index>(std::forward<_Tp>(__rhs));
1565 else
1566 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1567 // 3585. converting assignment with immovable alternative
1568 this->emplace<__index>(_Tj(std::forward<_Tp>(__rhs)));
1569 }
1570 return *this;
1571 }
1572
1573 template<typename _Tp, typename... _Args>
1574 _GLIBCXX20_CONSTEXPR
1575 enable_if_t<is_constructible_v<_Tp, _Args...> && __exactly_once<_Tp>,
1576 _Tp&>
1577 emplace(_Args&&... __args)
1578 {
1579 constexpr size_t __index = __index_of<_Tp>;
1580 return this->emplace<__index>(std::forward<_Args>(__args)...);
1581 }
1582
1583 template<typename _Tp, typename _Up, typename... _Args>
1584 _GLIBCXX20_CONSTEXPR
1585 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
1586 && __exactly_once<_Tp>,
1587 _Tp&>
1588 emplace(initializer_list<_Up> __il, _Args&&... __args)
1589 {
1590 constexpr size_t __index = __index_of<_Tp>;
1591 return this->emplace<__index>(__il, std::forward<_Args>(__args)...);
1592 }
1593
1594 template<size_t _Np, typename... _Args>
1595 _GLIBCXX20_CONSTEXPR
1596 enable_if_t<is_constructible_v<__to_type<_Np>, _Args...>,
1597 __to_type<_Np>&>
1598 emplace(_Args&&... __args)
1599 {
1600 namespace __variant = std::__detail::__variant;
1601 using type = typename _Nth_type<_Np, _Types...>::type;
1602 // Provide the strong exception-safety guarantee when possible,
1603 // to avoid becoming valueless.
1604 if constexpr (is_nothrow_constructible_v<type, _Args...>)
1605 {
1606 __variant::__emplace<_Np>(*this, std::forward<_Args>(__args)...);
1607 }
1608 else if constexpr (is_scalar_v<type>)
1609 {
1610 // This might invoke a potentially-throwing conversion operator:
1611 const type __tmp(std::forward<_Args>(__args)...);
1612 // But this won't throw:
1613 __variant::__emplace<_Np>(*this, __tmp);
1614 }
1615 else if constexpr (__variant::_Never_valueless_alt<type>()
1616 && _Traits::_S_move_assign)
1617 {
1618 // This construction might throw:
1619 variant __tmp(in_place_index<_Np>,
1620 std::forward<_Args>(__args)...);
1621 // But _Never_valueless_alt<type> means this won't:
1622 *this = std::move(__tmp);
1623 }
1624 else
1625 {
1626 // This case only provides the basic exception-safety guarantee,
1627 // i.e. the variant can become valueless.
1628 __variant::__emplace<_Np>(*this, std::forward<_Args>(__args)...);
1629 }
1630 return std::get<_Np>(*this);
1631 }
1632
1633 template<size_t _Np, typename _Up, typename... _Args>
1634 _GLIBCXX20_CONSTEXPR
1635 enable_if_t<is_constructible_v<__to_type<_Np>,
1636 initializer_list<_Up>&, _Args...>,
1637 __to_type<_Np>&>
1638 emplace(initializer_list<_Up> __il, _Args&&... __args)
1639 {
1640 namespace __variant = std::__detail::__variant;
1641 using type = typename _Nth_type<_Np, _Types...>::type;
1642 // Provide the strong exception-safety guarantee when possible,
1643 // to avoid becoming valueless.
1644 if constexpr (is_nothrow_constructible_v<type,
1645 initializer_list<_Up>&,
1646 _Args...>)
1647 {
1648 __variant::__emplace<_Np>(*this, __il,
1649 std::forward<_Args>(__args)...);
1650 }
1651 else if constexpr (__variant::_Never_valueless_alt<type>()
1652 && _Traits::_S_move_assign)
1653 {
1654 // This construction might throw:
1655 variant __tmp(in_place_index<_Np>, __il,
1656 std::forward<_Args>(__args)...);
1657 // But _Never_valueless_alt<type> means this won't:
1658 *this = std::move(__tmp);
1659 }
1660 else
1661 {
1662 // This case only provides the basic exception-safety guarantee,
1663 // i.e. the variant can become valueless.
1664 __variant::__emplace<_Np>(*this, __il,
1665 std::forward<_Args>(__args)...);
1666 }
1667 return std::get<_Np>(*this);
1668 }
1669
1670 template<size_t _Np, typename... _Args>
1671 enable_if_t<!(_Np < sizeof...(_Types))> emplace(_Args&&...) = delete;
1672
1673 template<typename _Tp, typename... _Args>
1674 enable_if_t<!__exactly_once<_Tp>> emplace(_Args&&...) = delete;
1675
1676 constexpr bool valueless_by_exception() const noexcept
1677 { return !this->_M_valid(); }
1678
1679 constexpr size_t index() const noexcept
1680 {
1681 using __index_type = typename _Base::__index_type;
1682 if constexpr (__detail::__variant::__never_valueless<_Types...>())
1683 return this->_M_index;
1684 else if constexpr (sizeof...(_Types) <= __index_type(-1) / 2)
1685 return make_signed_t<__index_type>(this->_M_index);
1686 else
1687 return size_t(__index_type(this->_M_index + 1)) - 1;
1688 }
1689
1690 _GLIBCXX20_CONSTEXPR
1691 void
1692 swap(variant& __rhs)
1693 noexcept((__is_nothrow_swappable<_Types>::value && ...)
1694 && is_nothrow_move_constructible_v<variant>)
1695 {
1696 static_assert((is_move_constructible_v<_Types> && ...));
1697
1698 // Handle this here to simplify the visitation.
1699 if (__rhs.valueless_by_exception()) [[__unlikely__]]
1700 {
1701 if (!this->valueless_by_exception()) [[__likely__]]
1702 __rhs.swap(*this);
1703 return;
1704 }
1705
1706 namespace __variant = __detail::__variant;
1707
1708 __variant::__raw_idx_visit(
1709 [this, &__rhs](auto&& __rhs_mem, auto __rhs_index) mutable
1710 {
1711 constexpr size_t __j = __rhs_index;
1712 if constexpr (__j != variant_npos)
1713 {
1714 if (this->index() == __j)
1715 {
1716 using std::swap;
1717 swap(std::get<__j>(*this), __rhs_mem);
1718 }
1719 else
1720 {
1721 auto __tmp(std::move(__rhs_mem));
1722
1723 if constexpr (_Traits::_S_trivial_move_assign)
1724 __rhs = std::move(*this);
1725 else
1726 __variant::__raw_idx_visit(
1727 [&__rhs](auto&& __this_mem, auto __this_index) mutable
1728 {
1729 constexpr size_t __k = __this_index;
1730 if constexpr (__k != variant_npos)
1731 __variant::__emplace<__k>(__rhs,
1732 std::move(__this_mem));
1733 }, *this);
1734
1735 __variant::__emplace<__j>(*this, std::move(__tmp));
1736 }
1737 }
1738 }, __rhs);
1739 }
1740
1741#if __cpp_lib_variant >= 202306L // >= C++26
1742 // [variant.visit], visitation
1743
1744 /** Simple visitation for a single variant
1745 *
1746 * To visit a single variant you can use `var.visit(visitor)`
1747 * instead of `std::visit(visitor, var)`.
1748 *
1749 * @since C++26
1750 */
1751 template<int = 0, typename _Self, typename _Visitor>
1752 constexpr decltype(auto)
1753 visit(this _Self&& __self, _Visitor&& __vis)
1754 {
1755 using _CVar = __conditional_t<is_const_v<remove_reference_t<_Self>>,
1756 const variant, variant>;
1757 using _Var = __conditional_t<is_rvalue_reference_v<_Self&&>,
1758 _CVar&&, _CVar&>;
1759 return std::visit(std::forward<_Visitor>(__vis), (_Var)__self);
1760 }
1761
1762 /** Simple visitation for a single variant, with explicit return type
1763 *
1764 * To visit a single variant you can use `var.visit<R>(visitor)`
1765 * instead of `std::visit<R>(visitor, var)`.
1766 *
1767 * @since C++26
1768 */
1769 template<typename _Res, typename _Self, typename _Visitor>
1770 constexpr _Res
1771 visit(this _Self&& __self, _Visitor&& __vis)
1772 {
1773 using _CVar = __conditional_t<is_const_v<remove_reference_t<_Self>>,
1774 const variant, variant>;
1775 using _Var = __conditional_t<is_rvalue_reference_v<_Self&&>,
1776 _CVar&&, _CVar&>;
1777 return std::visit<_Res>(std::forward<_Visitor>(__vis), (_Var)__self);
1778 }
1779#endif
1780
1781 private:
1782 template<size_t _Np, typename _Vp>
1783 friend constexpr decltype(auto)
1784 __detail::__variant::__get(_Vp&& __v) noexcept;
1785 };
1786
1787 template<size_t _Np, typename... _Types>
1788 constexpr variant_alternative_t<_Np, variant<_Types...>>&
1789 get(variant<_Types...>& __v)
1790 {
1791 static_assert(_Np < sizeof...(_Types),
1792 "The index must be in [0, number of alternatives)");
1793 if (__v.index() != _Np)
1794 __throw_bad_variant_access(__v.valueless_by_exception());
1795 return __detail::__variant::__get<_Np>(__v);
1796 }
1797
1798 template<size_t _Np, typename... _Types>
1799 constexpr variant_alternative_t<_Np, variant<_Types...>>&&
1800 get(variant<_Types...>&& __v)
1801 {
1802 static_assert(_Np < sizeof...(_Types),
1803 "The index must be in [0, number of alternatives)");
1804 if (__v.index() != _Np)
1805 __throw_bad_variant_access(__v.valueless_by_exception());
1806 return __detail::__variant::__get<_Np>(std::move(__v));
1807 }
1808
1809 template<size_t _Np, typename... _Types>
1810 constexpr const variant_alternative_t<_Np, variant<_Types...>>&
1811 get(const variant<_Types...>& __v)
1812 {
1813 static_assert(_Np < sizeof...(_Types),
1814 "The index must be in [0, number of alternatives)");
1815 if (__v.index() != _Np)
1816 __throw_bad_variant_access(__v.valueless_by_exception());
1817 return __detail::__variant::__get<_Np>(__v);
1818 }
1819
1820 template<size_t _Np, typename... _Types>
1821 constexpr const variant_alternative_t<_Np, variant<_Types...>>&&
1822 get(const variant<_Types...>&& __v)
1823 {
1824 static_assert(_Np < sizeof...(_Types),
1825 "The index must be in [0, number of alternatives)");
1826 if (__v.index() != _Np)
1827 __throw_bad_variant_access(__v.valueless_by_exception());
1828 return __detail::__variant::__get<_Np>(std::move(__v));
1829 }
1830
1831 /// @cond undocumented
1832 template<typename _Result_type, typename _Visitor, typename... _Variants>
1833 constexpr decltype(auto)
1834 __do_visit(_Visitor&& __visitor, _Variants&&... __variants)
1835 {
1836 // Get the silly case of visiting no variants out of the way first.
1837 if constexpr (sizeof...(_Variants) == 0)
1838 {
1839 if constexpr (is_void_v<_Result_type>)
1840 return (void) std::forward<_Visitor>(__visitor)();
1841 else
1842 return std::forward<_Visitor>(__visitor)();
1843 }
1844 else
1845 {
1846 constexpr size_t __max = 11; // "These go to eleven."
1847
1848 // The type of the first variant in the pack.
1849 using _V0 = typename _Nth_type<0, _Variants...>::type;
1850 // The number of alternatives in that first variant.
1851 constexpr auto __n = variant_size_v<remove_reference_t<_V0>>;
1852
1853 if constexpr (sizeof...(_Variants) > 1 || __n > __max)
1854 {
1855 // Use a jump table for the general case.
1856 constexpr auto& __vtable = __detail::__variant::__gen_vtable<
1857 _Result_type, _Visitor&&, _Variants&&...>::_S_vtable;
1858
1859 auto __func_ptr = __vtable._M_access(__variants.index()...);
1860 return (*__func_ptr)(std::forward<_Visitor>(__visitor),
1861 std::forward<_Variants>(__variants)...);
1862 }
1863 else // We have a single variant with a small number of alternatives.
1864 {
1865 // A name for the first variant in the pack.
1866 _V0& __v0
1867 = [](_V0& __v, ...) -> _V0& { return __v; }(__variants...);
1868
1869 using __detail::__variant::_Multi_array;
1870 using __detail::__variant::__gen_vtable_impl;
1871 using _Ma = _Multi_array<_Result_type (*)(_Visitor&&, _V0&&)>;
1872
1873#ifdef _GLIBCXX_DEBUG
1874# define _GLIBCXX_VISIT_UNREACHABLE __builtin_trap
1875#else
1876# define _GLIBCXX_VISIT_UNREACHABLE __builtin_unreachable
1877#endif
1878
1879#define _GLIBCXX_VISIT_CASE(N) \
1880 case N: \
1881 { \
1882 if constexpr (N < __n) \
1883 { \
1884 return __gen_vtable_impl<_Ma, index_sequence<N>>:: \
1885 __visit_invoke(std::forward<_Visitor>(__visitor), \
1886 std::forward<_V0>(__v0)); \
1887 } \
1888 else _GLIBCXX_VISIT_UNREACHABLE(); \
1889 }
1890
1891 switch (__v0.index())
1892 {
1893 _GLIBCXX_VISIT_CASE(0)
1894 _GLIBCXX_VISIT_CASE(1)
1895 _GLIBCXX_VISIT_CASE(2)
1896 _GLIBCXX_VISIT_CASE(3)
1897 _GLIBCXX_VISIT_CASE(4)
1898 _GLIBCXX_VISIT_CASE(5)
1899 _GLIBCXX_VISIT_CASE(6)
1900 _GLIBCXX_VISIT_CASE(7)
1901 _GLIBCXX_VISIT_CASE(8)
1902 _GLIBCXX_VISIT_CASE(9)
1903 _GLIBCXX_VISIT_CASE(10)
1904 case variant_npos:
1905 using __detail::__variant::__variant_idx_cookie;
1906 using __detail::__variant::__variant_cookie;
1907 if constexpr (is_same_v<_Result_type, __variant_idx_cookie>
1908 || is_same_v<_Result_type, __variant_cookie>)
1909 {
1910 using _Npos = index_sequence<variant_npos>;
1911 return __gen_vtable_impl<_Ma, _Npos>::
1912 __visit_invoke(std::forward<_Visitor>(__visitor),
1913 std::forward<_V0>(__v0));
1914 }
1915 else
1916 _GLIBCXX_VISIT_UNREACHABLE();
1917 default:
1918 _GLIBCXX_VISIT_UNREACHABLE();
1919 }
1920#undef _GLIBCXX_VISIT_CASE
1921#undef _GLIBCXX_VISIT_UNREACHABLE
1922 }
1923 }
1924 }
1925 /// @endcond
1926
1927 template<typename _Visitor, typename... _Variants>
1928 constexpr __detail::__variant::__visit_result_t<_Visitor, _Variants...>
1929 visit(_Visitor&& __visitor, _Variants&&... __variants)
1930 {
1931 namespace __variant = std::__detail::__variant;
1932
1933 if ((__variant::__as(__variants).valueless_by_exception() || ...))
1934 __throw_bad_variant_access(2);
1935
1936 using _Result_type
1937 = __detail::__variant::__visit_result_t<_Visitor, _Variants...>;
1938
1939 using _Tag = __detail::__variant::__deduce_visit_result<_Result_type>;
1940
1941 if constexpr (sizeof...(_Variants) == 1)
1942 {
1943 using _Vp = decltype(__variant::__as(std::declval<_Variants>()...));
1944
1945 constexpr bool __visit_rettypes_match = __detail::__variant::
1946 __check_visitor_results<_Visitor, _Vp>(
1947 make_index_sequence<variant_size_v<remove_reference_t<_Vp>>>());
1948 if constexpr (!__visit_rettypes_match)
1949 {
1950 static_assert(__visit_rettypes_match,
1951 "std::visit requires the visitor to have the same "
1952 "return type for all alternatives of a variant");
1953 return;
1954 }
1955 else
1956 return std::__do_visit<_Tag>(
1957 std::forward<_Visitor>(__visitor),
1958 static_cast<_Vp>(__variants)...);
1959 }
1960 else
1961 return std::__do_visit<_Tag>(
1962 std::forward<_Visitor>(__visitor),
1963 __variant::__as(std::forward<_Variants>(__variants))...);
1964 }
1965
1966#if __cplusplus > 201703L
1967 template<typename _Res, typename _Visitor, typename... _Variants>
1968 constexpr _Res
1969 visit(_Visitor&& __visitor, _Variants&&... __variants)
1970 {
1971 namespace __variant = std::__detail::__variant;
1972
1973 if ((__variant::__as(__variants).valueless_by_exception() || ...))
1974 __throw_bad_variant_access(3);
1975
1976 return std::__do_visit<_Res>(std::forward<_Visitor>(__visitor),
1977 __variant::__as(std::forward<_Variants>(__variants))...);
1978 }
1979#endif
1980
1981 /// @cond undocumented
1982 template<typename... _Types>
1983 struct __variant_hash
1984 {
1985#if __cplusplus < 202002L
1986 using result_type [[__deprecated__]] = size_t;
1987 using argument_type [[__deprecated__]] = variant<_Types...>;
1988#endif
1989
1990 size_t
1991 operator()(const variant<_Types...>& __t) const
1992 noexcept((is_nothrow_invocable_v<hash<decay_t<_Types>>, _Types> && ...))
1993 {
1994 size_t __ret;
1995 __detail::__variant::__raw_visit(
1996 [&__t, &__ret](auto&& __t_mem) mutable
1997 {
1998 using _Type = __remove_cvref_t<decltype(__t_mem)>;
1999 if constexpr (!is_same_v<_Type,
2000 __detail::__variant::__variant_cookie>)
2001 __ret = std::hash<size_t>{}(__t.index())
2002 + std::hash<_Type>{}(__t_mem);
2003 else
2004 __ret = std::hash<size_t>{}(__t.index());
2005 }, __t);
2006 return __ret;
2007 }
2008 };
2009 /// @endcond
2010
2011 template<typename... _Types>
2012 struct hash<variant<_Types...>>
2013 : __conditional_t<(__is_hash_enabled_for<remove_const_t<_Types>> && ...),
2014 __variant_hash<_Types...>,
2015 __hash_not_enabled<variant<_Types...>>>
2016#if ! _GLIBCXX_INLINE_VERSION
2017 , __detail::__variant::_Variant_hash_base<variant<_Types...>,
2018 index_sequence_for<_Types...>>
2019#endif
2020 { };
2021
2022 template<typename... _Types>
2023 struct __is_fast_hash<hash<variant<_Types...>>>
2024 : bool_constant<(__is_fast_hash<_Types>::value && ...)>
2025 { };
2026
2027_GLIBCXX_END_NAMESPACE_VERSION
2028} // namespace std
2029
2030#endif // __cpp_lib_variant
2031#endif // _GLIBCXX_VARIANT