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