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