* tree-ssa-loop-ivopts.c (struct cost_pair): Remove field inv_expr
[official-gcc.git] / libstdc++-v3 / include / std / variant
blob272b2a6f6d29c5d74c30c1c1cdcab2cae26d3518
1 // <variant> -*- C++ -*-
3 // Copyright (C) 2016-2017 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.
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.
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.
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/>.
25 /** @file variant
26  *  This is the <variant> C++ Library header.
27  */
29 #ifndef _GLIBCXX_VARIANT
30 #define _GLIBCXX_VARIANT 1
32 #pragma GCC system_header
34 #if __cplusplus <= 201402L
35 # include <bits/c++17_warning.h>
36 #else
38 #include <type_traits>
39 #include <utility>
40 #include <bits/enable_special_members.h>
41 #include <bits/functexcept.h>
42 #include <bits/move.h>
43 #include <bits/functional_hash.h>
44 #include <bits/invoke.h>
45 #include <ext/aligned_buffer.h>
46 #include <bits/parse_numbers.h>
48 namespace std _GLIBCXX_VISIBILITY(default)
50 namespace __detail
52 namespace __variant
54 _GLIBCXX_BEGIN_NAMESPACE_VERSION
56   template<size_t _Np, typename... _Types>
57     struct _Nth_type;
59   template<size_t _Np, typename _First, typename... _Rest>
60     struct _Nth_type<_Np, _First, _Rest...>
61     : _Nth_type<_Np-1, _Rest...> { };
63   template<typename _First, typename... _Rest>
64     struct _Nth_type<0, _First, _Rest...>
65     { using type = _First; };
67 _GLIBCXX_END_NAMESPACE_VERSION
68 } // namespace __variant
69 } // namespace __detail
71 _GLIBCXX_BEGIN_NAMESPACE_VERSION
73   template<typename... _Types> class tuple;
74   template<typename... _Types> class variant;
75   template <typename> struct hash;
77   template<typename _Variant>
78     struct variant_size;
80   template<typename _Variant>
81     struct variant_size<const _Variant> : variant_size<_Variant> {};
83   template<typename _Variant>
84     struct variant_size<volatile _Variant> : variant_size<_Variant> {};
86   template<typename _Variant>
87     struct variant_size<const volatile _Variant> : variant_size<_Variant> {};
89   template<typename... _Types>
90     struct variant_size<variant<_Types...>>
91     : std::integral_constant<size_t, sizeof...(_Types)> {};
93   template<typename _Variant>
94     inline constexpr size_t variant_size_v = variant_size<_Variant>::value;
96   template<size_t _Np, typename _Variant>
97     struct variant_alternative;
99   template<size_t _Np, typename _First, typename... _Rest>
100     struct variant_alternative<_Np, variant<_First, _Rest...>>
101     : variant_alternative<_Np-1, variant<_Rest...>> {};
103   template<typename _First, typename... _Rest>
104     struct variant_alternative<0, variant<_First, _Rest...>>
105     { using type = _First; };
107   template<size_t _Np, typename _Variant>
108     using variant_alternative_t =
109       typename variant_alternative<_Np, _Variant>::type;
111   template<size_t _Np, typename _Variant>
112     struct variant_alternative<_Np, const _Variant>
113     { using type = add_const_t<variant_alternative_t<_Np, _Variant>>; };
115   template<size_t _Np, typename _Variant>
116     struct variant_alternative<_Np, volatile _Variant>
117     { using type = add_volatile_t<variant_alternative_t<_Np, _Variant>>; };
119   template<size_t _Np, typename _Variant>
120     struct variant_alternative<_Np, const volatile _Variant>
121     { using type = add_cv_t<variant_alternative_t<_Np, _Variant>>; };
123   inline constexpr size_t variant_npos = -1;
125   template<size_t _Np, typename... _Types>
126     constexpr variant_alternative_t<_Np, variant<_Types...>>&
127     get(variant<_Types...>&);
129   template<size_t _Np, typename... _Types>
130     constexpr variant_alternative_t<_Np, variant<_Types...>>&&
131     get(variant<_Types...>&&);
133   template<size_t _Np, typename... _Types>
134     constexpr variant_alternative_t<_Np, variant<_Types...>> const&
135     get(const variant<_Types...>&);
137   template<size_t _Np, typename... _Types>
138     constexpr variant_alternative_t<_Np, variant<_Types...>> const&&
139     get(const variant<_Types...>&&);
141 _GLIBCXX_END_NAMESPACE_VERSION
143 namespace __detail
145 namespace __variant
147 _GLIBCXX_BEGIN_NAMESPACE_VERSION
148   // Returns the first apparence of _Tp in _Types.
149   // Returns sizeof...(_Types) if _Tp is not in _Types.
150   template<typename _Tp, typename... _Types>
151     struct __index_of : std::integral_constant<size_t, 0> {};
153   template<typename _Tp, typename... _Types>
154     inline constexpr size_t __index_of_v = __index_of<_Tp, _Types...>::value;
156   template<typename _Tp, typename _First, typename... _Rest>
157     struct __index_of<_Tp, _First, _Rest...> :
158       std::integral_constant<size_t, is_same_v<_Tp, _First>
159         ? 0 : __index_of_v<_Tp, _Rest...> + 1> {};
161   // _Uninitialized<T> is guaranteed to be a literal type, even if T is not.
162   // We have to do this, because [basic.types]p10.5.3 (n4606) is not implemented
163   // yet. When it's implemented, _Uninitialized<T> can be changed to the alias
164   // to T, therefore equivalent to being removed entirely.
165   //
166   // Another reason we may not want to remove _Uninitialzied<T> may be that, we
167   // want _Uninitialized<T> to be trivially destructible, no matter whether T
168   // is; but we will see.
169   template<typename _Type, bool = std::is_literal_type_v<_Type>>
170     struct _Uninitialized;
172   template<typename _Type>
173     struct _Uninitialized<_Type, true>
174     {
175       template<typename... _Args>
176       constexpr _Uninitialized(in_place_index_t<0>, _Args&&... __args)
177       : _M_storage(std::forward<_Args>(__args)...)
178       { }
180       constexpr const _Type& _M_get() const &
181       { return _M_storage; }
183       constexpr _Type& _M_get() &
184       { return _M_storage; }
186       constexpr const _Type&& _M_get() const &&
187       { return std::move(_M_storage); }
189       constexpr _Type&& _M_get() &&
190       { return std::move(_M_storage); }
192       _Type _M_storage;
193     };
195   template<typename _Type>
196     struct _Uninitialized<_Type, false>
197     {
198       template<typename... _Args>
199       constexpr _Uninitialized(in_place_index_t<0>, _Args&&... __args)
200       { ::new (&_M_storage) _Type(std::forward<_Args>(__args)...); }
202       const _Type& _M_get() const &
203       { return *_M_storage._M_ptr(); }
205       _Type& _M_get() &
206       { return *_M_storage._M_ptr(); }
208       const _Type&& _M_get() const &&
209       { return std::move(*_M_storage._M_ptr()); }
211       _Type&& _M_get() &&
212       { return std::move(*_M_storage._M_ptr()); }
214       __gnu_cxx::__aligned_membuf<_Type> _M_storage;
215     };
217   template<typename _Ref>
218     _Ref __ref_cast(void* __ptr)
219     {
220       return static_cast<_Ref>(*static_cast<remove_reference_t<_Ref>*>(__ptr));
221     }
223   template<typename _Union>
224     constexpr decltype(auto) __get(in_place_index_t<0>, _Union&& __u)
225     { return std::forward<_Union>(__u)._M_first._M_get(); }
227   template<size_t _Np, typename _Union>
228     constexpr decltype(auto) __get(in_place_index_t<_Np>, _Union&& __u)
229     { return __get(in_place_index<_Np-1>, std::forward<_Union>(__u)._M_rest); }
231   // Returns the typed storage for __v.
232   template<size_t _Np, typename _Variant>
233     constexpr decltype(auto) __get(_Variant&& __v)
234     {
235       return __get(std::in_place_index<_Np>, std::forward<_Variant>(__v)._M_u);
236     }
238   // Various functions as "vtable" entries, where those vtables are used by
239   // polymorphic operations.
240   template<typename _Lhs, typename _Rhs>
241     constexpr void
242     __erased_ctor(void* __lhs, void* __rhs)
243     { ::new (__lhs) remove_reference_t<_Lhs>(__ref_cast<_Rhs>(__rhs)); }
245   template<typename _Variant, size_t _Np>
246     constexpr void
247     __erased_dtor(_Variant&& __v)
248     {
249       auto&& __element = __get<_Np>(std::forward<_Variant>(__v));
250       using _Type = std::remove_reference_t<decltype(__element)>;
251       __element.~_Type();
252     }
254   template<typename _Lhs, typename _Rhs>
255     constexpr void
256     __erased_assign(void* __lhs, void* __rhs)
257     { __ref_cast<_Lhs>(__lhs) = __ref_cast<_Rhs>(__rhs); }
259   template<typename _Lhs, typename _Rhs>
260     constexpr void
261     __erased_swap(void* __lhs, void* __rhs)
262     {
263       using std::swap;
264       swap(__ref_cast<_Lhs>(__lhs), __ref_cast<_Rhs>(__rhs));
265     }
267 #define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \
268   template<typename _Variant, size_t _Np> \
269     constexpr bool \
270     __erased_##__NAME(const _Variant& __lhs, const _Variant& __rhs) \
271     { \
272       return __get<_Np>(std::forward<_Variant>(__lhs)) \
273           __OP __get<_Np>(std::forward<_Variant>(__rhs)); \
274     }
276   _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less)
277   _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal)
278   _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
279   _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal)
280   _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal)
281   _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater)
283 #undef _VARIANT_RELATION_FUNCTION_TEMPLATE
285   template<typename _Tp>
286     constexpr size_t
287     __erased_hash(void* __t)
288     {
289       return std::hash<remove_cv_t<remove_reference_t<_Tp>>>{}(
290           __ref_cast<_Tp>(__t));
291     }
293   // Defines members and ctors.
294   template<typename... _Types>
295     union _Variadic_union { };
297   template<typename _First, typename... _Rest>
298     union _Variadic_union<_First, _Rest...>
299     {
300       constexpr _Variadic_union() : _M_rest() { }
302       template<typename... _Args>
303         constexpr _Variadic_union(in_place_index_t<0>, _Args&&... __args)
304         : _M_first(in_place_index<0>, std::forward<_Args>(__args)...)
305         { }
307       template<size_t _Np, typename... _Args>
308         constexpr _Variadic_union(in_place_index_t<_Np>, _Args&&... __args)
309         : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...)
310         { }
312       _Uninitialized<_First> _M_first;
313       _Variadic_union<_Rest...> _M_rest;
314     };
316   // Defines index and the dtor, possibly trivial.
317   template<bool __trivially_destructible, typename... _Types>
318     struct _Variant_storage;
320   template <typename... _Types>
321   using __select_index =
322     typename __select_int::_Select_int_base<sizeof...(_Types)+1,
323                                             unsigned char,
324                                             unsigned short>
325     ::type::value_type;
327   template<typename... _Types>
328     struct _Variant_storage<false, _Types...>
329     {
330       template<size_t... __indices>
331         static constexpr void (*_S_vtable[])(const _Variant_storage&) =
332             { &__erased_dtor<const _Variant_storage&, __indices>... };
334       constexpr _Variant_storage() : _M_index(variant_npos) { }
336       template<size_t _Np, typename... _Args>
337         constexpr _Variant_storage(in_place_index_t<_Np>, _Args&&... __args)
338         : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...),
339         _M_index(_Np)
340         { }
342       template<size_t... __indices>
343         constexpr void _M_reset_impl(std::index_sequence<__indices...>)
344         {
345           if (_M_index != __index_type(variant_npos))
346             _S_vtable<__indices...>[_M_index](*this);
347         }
349       void _M_reset()
350       {
351         _M_reset_impl(std::index_sequence_for<_Types...>{});
352         _M_index = variant_npos;
353       }
355       ~_Variant_storage()
356       { _M_reset(); }
358       _Variadic_union<_Types...> _M_u;
359       using __index_type = __select_index<_Types...>;
360       __index_type _M_index;
361     };
363   template<typename... _Types>
364     struct _Variant_storage<true, _Types...>
365     {
366       constexpr _Variant_storage() : _M_index(variant_npos) { }
368       template<size_t _Np, typename... _Args>
369         constexpr _Variant_storage(in_place_index_t<_Np>, _Args&&... __args)
370         : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...),
371         _M_index(_Np)
372         { }
374       void _M_reset()
375       { _M_index = variant_npos; }
377       _Variadic_union<_Types...> _M_u;
378       using __index_type = __select_index<_Types...>;
379       __index_type _M_index;
380     };
382   // Helps SFINAE on special member functions. Otherwise it can live in variant
383   // class.
384   template<typename... _Types>
385     struct _Variant_base :
386       _Variant_storage<(std::is_trivially_destructible_v<_Types> && ...),
387                         _Types...>
388     {
389       using _Storage =
390           _Variant_storage<(std::is_trivially_destructible_v<_Types> && ...),
391                             _Types...>;
393       constexpr
394       _Variant_base()
395       noexcept(is_nothrow_default_constructible_v<
396                  variant_alternative_t<0, variant<_Types...>>>)
397       : _Variant_base(in_place_index<0>) { }
399       _Variant_base(const _Variant_base& __rhs)
400       {
401         if (__rhs._M_valid())
402           {
403             static constexpr void (*_S_vtable[])(void*, void*) =
404               { &__erased_ctor<_Types&, const _Types&>... };
405             _S_vtable[__rhs._M_index](_M_storage(), __rhs._M_storage());
406             this->_M_index = __rhs._M_index;
407           }
408       }
410       _Variant_base(_Variant_base&& __rhs)
411       noexcept((is_nothrow_move_constructible_v<_Types> && ...))
412       {
413         if (__rhs._M_valid())
414           {
415             static constexpr void (*_S_vtable[])(void*, void*) =
416               { &__erased_ctor<_Types&, _Types&&>... };
417             _S_vtable[__rhs._M_index](_M_storage(), __rhs._M_storage());
418             this->_M_index = __rhs._M_index;
419           }
420       }
422       template<size_t _Np, typename... _Args>
423         constexpr explicit
424         _Variant_base(in_place_index_t<_Np> __i, _Args&&... __args)
425         : _Storage(__i, std::forward<_Args>(__args)...)
426         { }
428       _Variant_base&
429       operator=(const _Variant_base& __rhs)
430       {
431         if (this->_M_index == __rhs._M_index)
432           {
433             if (__rhs._M_valid())
434               {
435                 static constexpr void (*_S_vtable[])(void*, void*) =
436                   { &__erased_assign<_Types&, const _Types&>... };
437                 _S_vtable[__rhs._M_index](_M_storage(), __rhs._M_storage());
438               }
439           }
440         else
441           {
442             _Variant_base __tmp(__rhs);
443             this->~_Variant_base();
444             __try
445               {
446                 ::new (this) _Variant_base(std::move(__tmp));
447               }
448             __catch (...)
449               {
450                 this->_M_index = variant_npos;
451                 __throw_exception_again;
452               }
453           }
454         __glibcxx_assert(this->_M_index == __rhs._M_index);
455         return *this;
456       }
458       void _M_destructive_move(_Variant_base&& __rhs)
459       {
460         this->~_Variant_base();
461         __try
462           {
463             ::new (this) _Variant_base(std::move(__rhs));
464           }
465         __catch (...)
466           {
467             this->_M_index = variant_npos;
468             __throw_exception_again;
469           }
470       }
472       _Variant_base&
473       operator=(_Variant_base&& __rhs)
474       noexcept((is_nothrow_move_constructible_v<_Types> && ...)
475           && (is_nothrow_move_assignable_v<_Types> && ...))
476       {
477         if (this->_M_index == __rhs._M_index)
478           {
479             if (__rhs._M_valid())
480               {
481                 static constexpr void (*_S_vtable[])(void*, void*) =
482                   { &__erased_assign<_Types&, _Types&&>... };
483                 _S_vtable[__rhs._M_index](_M_storage(), __rhs._M_storage());
484               }
485           }
486         else
487           {
488             _M_destructive_move(std::move(__rhs));
489           }
490         return *this;
491       }
493       void*
494       _M_storage() const
495       {
496         return const_cast<void*>(static_cast<const void*>(
497             std::addressof(_Storage::_M_u)));
498       }
500       constexpr bool
501       _M_valid() const noexcept
502       {
503         return this->_M_index !=
504           typename _Storage::__index_type(variant_npos);
505       }
506     };
508   // For how many times does _Tp appear in _Tuple?
509   template<typename _Tp, typename _Tuple>
510     struct __tuple_count;
512   template<typename _Tp, typename _Tuple>
513     inline constexpr size_t __tuple_count_v =
514       __tuple_count<_Tp, _Tuple>::value;
516   template<typename _Tp, typename... _Types>
517     struct __tuple_count<_Tp, tuple<_Types...>>
518     : integral_constant<size_t, 0> { };
520   template<typename _Tp, typename _First, typename... _Rest>
521     struct __tuple_count<_Tp, tuple<_First, _Rest...>>
522     : integral_constant<
523         size_t,
524         __tuple_count_v<_Tp, tuple<_Rest...>> + is_same_v<_Tp, _First>> { };
526   // TODO: Reuse this in <tuple> ?
527   template<typename _Tp, typename... _Types>
528     inline constexpr bool __exactly_once =
529       __tuple_count_v<_Tp, tuple<_Types...>> == 1;
531   // Takes _Types and create an overloaded _S_fun for each type.
532   // If a type appears more than once in _Types, create only one overload.
533   template<typename... _Types>
534     struct __overload_set
535     { static void _S_fun(); };
537   template<typename _First, typename... _Rest>
538     struct __overload_set<_First, _Rest...> : __overload_set<_Rest...>
539     {
540       using __overload_set<_Rest...>::_S_fun;
541       static integral_constant<size_t, sizeof...(_Rest)> _S_fun(_First);
542     };
544   template<typename... _Rest>
545     struct __overload_set<void, _Rest...> : __overload_set<_Rest...>
546     {
547       using __overload_set<_Rest...>::_S_fun;
548     };
550   // Helper for variant(_Tp&&) and variant::operator=(_Tp&&).
551   // __accepted_index maps the arbitrary _Tp to an alternative type in _Variant.
552   template<typename _Tp, typename _Variant, typename = void>
553     struct __accepted_index
554     { static constexpr size_t value = variant_npos; };
556   template<typename _Tp, typename... _Types>
557     struct __accepted_index<
558       _Tp, variant<_Types...>,
559       decltype(__overload_set<_Types...>::_S_fun(std::declval<_Tp>()),
560                std::declval<void>())>
561     {
562       static constexpr size_t value = sizeof...(_Types) - 1
563         - decltype(__overload_set<_Types...>::
564                    _S_fun(std::declval<_Tp>()))::value;
565     };
567   // Returns the raw storage for __v.
568   template<typename _Variant>
569     void* __get_storage(_Variant&& __v)
570     { return __v._M_storage(); }
572   // Used for storing multi-dimensional vtable.
573   template<typename _Tp, size_t... _Dimensions>
574     struct _Multi_array
575     {
576       constexpr const _Tp&
577       _M_access() const
578       { return _M_data; }
580       _Tp _M_data;
581     };
583   template<typename _Tp, size_t __first, size_t... __rest>
584     struct _Multi_array<_Tp, __first, __rest...>
585     {
586       template<typename... _Args>
587         constexpr const _Tp&
588         _M_access(size_t __first_index, _Args... __rest_indices) const
589         { return _M_arr[__first_index]._M_access(__rest_indices...); }
591       _Multi_array<_Tp, __rest...> _M_arr[__first];
592     };
594   // Creates a multi-dimensional vtable recursively.
595   //
596   // For example,
597   // visit([](auto, auto){},
598   //       variant<int, char>(),  // typedef'ed as V1
599   //       variant<float, double, long double>())  // typedef'ed as V2
600   // will trigger instantiations of:
601   // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 2, 3>,
602   //                   tuple<V1&&, V2&&>, std::index_sequence<>>
603   //   __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 3>,
604   //                     tuple<V1&&, V2&&>, std::index_sequence<0>>
605   //     __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
606   //                       tuple<V1&&, V2&&>, std::index_sequence<0, 0>>
607   //     __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
608   //                       tuple<V1&&, V2&&>, std::index_sequence<0, 1>>
609   //     __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
610   //                       tuple<V1&&, V2&&>, std::index_sequence<0, 2>>
611   //   __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 3>,
612   //                     tuple<V1&&, V2&&>, std::index_sequence<1>>
613   //     __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
614   //                       tuple<V1&&, V2&&>, std::index_sequence<1, 0>>
615   //     __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
616   //                       tuple<V1&&, V2&&>, std::index_sequence<1, 1>>
617   //     __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
618   //                       tuple<V1&&, V2&&>, std::index_sequence<1, 2>>
619   // The returned multi-dimensional vtable can be fast accessed by the visitor
620   // using index calculation.
621   template<typename _Array_type, typename _Variant_tuple, typename _Index_seq>
622     struct __gen_vtable_impl;
624   template<typename _Result_type, typename _Visitor, size_t... __dimensions,
625            typename... _Variants, size_t... __indices>
626     struct __gen_vtable_impl<
627         _Multi_array<_Result_type (*)(_Visitor, _Variants...), __dimensions...>,
628         tuple<_Variants...>, std::index_sequence<__indices...>>
629     {
630       using _Next =
631           remove_reference_t<typename _Nth_type<sizeof...(__indices),
632                              _Variants...>::type>;
633       using _Array_type =
634           _Multi_array<_Result_type (*)(_Visitor, _Variants...),
635                        __dimensions...>;
637       static constexpr _Array_type
638       _S_apply()
639       {
640         _Array_type __vtable{};
641         _S_apply_all_alts(
642           __vtable, make_index_sequence<variant_size_v<_Next>>());
643         return __vtable;
644       }
646       template<size_t... __var_indices>
647         static constexpr void
648         _S_apply_all_alts(_Array_type& __vtable,
649                           std::index_sequence<__var_indices...>)
650         {
651           (_S_apply_single_alt<__var_indices>(
652              __vtable._M_arr[__var_indices]), ...);
653         }
655       template<size_t __index, typename _Tp>
656         static constexpr void
657         _S_apply_single_alt(_Tp& __element)
658         {
659           using _Alternative = variant_alternative_t<__index, _Next>;
660           __element = __gen_vtable_impl<
661             remove_reference_t<
662               decltype(__element)>, tuple<_Variants...>,
663               std::index_sequence<__indices..., __index>>::_S_apply();
664         }
665     };
667   template<typename _Result_type, typename _Visitor, typename... _Variants,
668            size_t... __indices>
669     struct __gen_vtable_impl<
670       _Multi_array<_Result_type (*)(_Visitor, _Variants...)>,
671                    tuple<_Variants...>, std::index_sequence<__indices...>>
672     {
673       using _Array_type =
674           _Multi_array<_Result_type (*)(_Visitor&&, _Variants...)>;
676       decltype(auto)
677       static constexpr __visit_invoke(_Visitor&& __visitor, _Variants... __vars)
678       {
679         return __invoke(std::forward<_Visitor>(__visitor),
680                         std::get<__indices>(
681                             std::forward<_Variants>(__vars))...);
682       }
684       static constexpr auto
685       _S_apply()
686       { return _Array_type{&__visit_invoke}; }
687     };
689   template<typename _Result_type, typename _Visitor, typename... _Variants>
690     struct __gen_vtable
691     {
692       using _Func_ptr = _Result_type (*)(_Visitor&&, _Variants...);
693       using _Array_type =
694           _Multi_array<_Func_ptr,
695                        variant_size_v<remove_reference_t<_Variants>>...>;
697       static constexpr _Array_type
698       _S_apply()
699       {
700         return __gen_vtable_impl<_Array_type, tuple<_Variants...>,
701                                  std::index_sequence<>>::_S_apply();
702       }
704       static constexpr auto _S_vtable = _S_apply();
705     };
707   template<size_t _Np, typename _Tp>
708     struct _Base_dedup : public _Tp { };
710   template<typename _Variant, typename __indices>
711     struct _Variant_hash_base;
713   template<typename... _Types, size_t... __indices>
714     struct _Variant_hash_base<variant<_Types...>,
715                               std::index_sequence<__indices...>>
716     : _Base_dedup<__indices, __poison_hash<remove_const_t<_Types>>>... { };
718 _GLIBCXX_END_NAMESPACE_VERSION
719 } // namespace __variant
720 } // namespace __detail
722 _GLIBCXX_BEGIN_NAMESPACE_VERSION
724   template<typename _Tp, typename... _Types>
725     inline constexpr bool holds_alternative(const variant<_Types...>& __v)
726     noexcept
727     {
728       static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
729                     "T should occur for exactly once in alternatives");
730       return __v.index() == __detail::__variant::__index_of_v<_Tp, _Types...>;
731     }
733   template<typename _Tp, typename... _Types>
734     constexpr inline _Tp& get(variant<_Types...>& __v)
735     {
736       static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
737                     "T should occur for exactly once in alternatives");
738       static_assert(!is_void_v<_Tp>, "_Tp should not be void");
739       return get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v);
740     }
742   template<typename _Tp, typename... _Types>
743     constexpr inline _Tp&& get(variant<_Types...>&& __v)
744     {
745       static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
746                     "T should occur for exactly once in alternatives");
747       static_assert(!is_void_v<_Tp>, "_Tp should not be void");
748       return get<__detail::__variant::__index_of_v<_Tp, _Types...>>(
749         std::move(__v));
750     }
752   template<typename _Tp, typename... _Types>
753     constexpr inline const _Tp& get(const variant<_Types...>& __v)
754     {
755       static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
756                     "T should occur for exactly once in alternatives");
757       static_assert(!is_void_v<_Tp>, "_Tp should not be void");
758       return get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v);
759     }
761   template<typename _Tp, typename... _Types>
762     constexpr inline const _Tp&& get(const variant<_Types...>&& __v)
763     {
764       static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
765                     "T should occur for exactly once in alternatives");
766       static_assert(!is_void_v<_Tp>, "_Tp should not be void");
767       return get<__detail::__variant::__index_of_v<_Tp, _Types...>>(
768         std::move(__v));
769     }
771   template<size_t _Np, typename... _Types>
772     constexpr inline
773     add_pointer_t<variant_alternative_t<_Np, variant<_Types...>>>
774     get_if(variant<_Types...>* __ptr) noexcept
775     {
776       using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>;
777       static_assert(_Np < sizeof...(_Types),
778                     "The index should be in [0, number of alternatives)");
779       static_assert(!is_void_v<_Alternative_type>, "_Tp should not be void");
780       if (__ptr && __ptr->index() == _Np)
781         return &__detail::__variant::__get<_Np>(*__ptr);
782       return nullptr;
783     }
785   template<size_t _Np, typename... _Types>
786     constexpr inline
787     add_pointer_t<const variant_alternative_t<_Np, variant<_Types...>>>
788     get_if(const variant<_Types...>* __ptr) noexcept
789     {
790       using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>;
791       static_assert(_Np < sizeof...(_Types),
792                     "The index should be in [0, number of alternatives)");
793       static_assert(!is_void_v<_Alternative_type>, "_Tp should not be void");
794       if (__ptr && __ptr->index() == _Np)
795         return &__detail::__variant::__get<_Np>(*__ptr);
796       return nullptr;
797     }
799   template<typename _Tp, typename... _Types>
800     constexpr inline add_pointer_t<_Tp>
801     get_if(variant<_Types...>* __ptr) noexcept
802     {
803       static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
804                     "T should occur for exactly once in alternatives");
805       static_assert(!is_void_v<_Tp>, "_Tp should not be void");
806       return get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>(__ptr);
807     }
809   template<typename _Tp, typename... _Types>
810     constexpr inline add_pointer_t<const _Tp>
811     get_if(const variant<_Types...>* __ptr)
812     noexcept
813     {
814       static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
815                     "T should occur for exactly once in alternatives");
816       static_assert(!is_void_v<_Tp>, "_Tp should not be void");
817       return get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>(__ptr);
818     }
820   struct monostate { };
822 #define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \
823   template<typename... _Types> \
824     constexpr bool operator __OP(const variant<_Types...>& __lhs, \
825                                  const variant<_Types...>& __rhs) \
826     { \
827       return __lhs._M_##__NAME(__rhs, std::index_sequence_for<_Types...>{}); \
828     } \
830   constexpr bool operator __OP(monostate, monostate) noexcept \
831   { return 0 __OP 0; }
833   _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less)
834   _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal)
835   _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
836   _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal)
837   _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal)
838   _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater)
840 #undef _VARIANT_RELATION_FUNCTION_TEMPLATE
842   template<typename _Visitor, typename... _Variants>
843     constexpr decltype(auto) visit(_Visitor&&, _Variants&&...);
845   template<typename... _Types>
846     inline enable_if_t<(is_move_constructible_v<_Types> && ...)
847                         && (is_swappable_v<_Types> && ...)>
848     swap(variant<_Types...>& __lhs, variant<_Types...>& __rhs)
849     noexcept(noexcept(__lhs.swap(__rhs)))
850     { __lhs.swap(__rhs); }
852   template<typename... _Types>
853     enable_if_t<!((is_move_constructible_v<_Types> && ...)
854                    && (is_swappable_v<_Types> && ...))>
855     swap(variant<_Types...>&, variant<_Types...>&) = delete;
857   class bad_variant_access : public exception
858   {
859   public:
860     bad_variant_access() noexcept : _M_reason("Unknown reason") { }
861     const char* what() const noexcept override
862     { return _M_reason; }
864   private:
865     bad_variant_access(const char* __reason) : _M_reason(__reason) { }
867     const char* _M_reason;
869     friend void __throw_bad_variant_access(const char* __what);
870   };
872   inline void
873   __throw_bad_variant_access(const char* __what)
874   { _GLIBCXX_THROW_OR_ABORT(bad_variant_access(__what)); }
876   template<typename... _Types>
877     class variant
878     : private __detail::__variant::_Variant_base<_Types...>,
879       private _Enable_default_constructor<
880         is_default_constructible_v<
881           variant_alternative_t<0, variant<_Types...>>>, variant<_Types...>>,
882       private _Enable_copy_move<
883         (is_copy_constructible_v<_Types> && ...),
884         (is_copy_constructible_v<_Types> && ...)
885              && (is_move_constructible_v<_Types> && ...)
886              && (is_copy_assignable_v<_Types> && ...),
887         (is_move_constructible_v<_Types> && ...),
888         (is_move_constructible_v<_Types> && ...)
889              && (is_move_assignable_v<_Types> && ...),
890         variant<_Types...>>
891     {
892     private:
893       static_assert(sizeof...(_Types) > 0,
894                     "variant must have at least one alternative");
895       static_assert(!(std::is_reference_v<_Types> || ...),
896                     "variant must have no reference alternative");
897       static_assert(!(std::is_void_v<_Types> || ...),
898                     "variant must have no void alternative");
900       using _Base = __detail::__variant::_Variant_base<_Types...>;
901       using _Default_ctor_enabler =
902         _Enable_default_constructor<
903           is_default_constructible_v<
904             variant_alternative_t<0, variant<_Types...>>>, variant<_Types...>>;
906       template<typename _Tp>
907         static constexpr bool
908         __exactly_once = __detail::__variant::__exactly_once<_Tp, _Types...>;
910       template<typename _Tp>
911         static constexpr size_t __accepted_index =
912           __detail::__variant::__accepted_index<_Tp&&, variant>::value;
914       template<size_t _Np, bool = _Np < sizeof...(_Types)>
915         struct __to_type_impl;
917       template<size_t _Np>
918         struct __to_type_impl<_Np, true>
919         { using type = variant_alternative_t<_Np, variant>; };
921       template<size_t _Np>
922         using __to_type = typename __to_type_impl<_Np>::type;
924       template<typename _Tp>
925         using __accepted_type = __to_type<__accepted_index<_Tp>>;
927       template<typename _Tp>
928         static constexpr size_t __index_of =
929           __detail::__variant::__index_of_v<_Tp, _Types...>;
931     public:
932       constexpr variant()
933       noexcept(is_nothrow_default_constructible_v<__to_type<0>>) = default;
934       variant(const variant&) = default;
935       variant(variant&&)
936       noexcept((is_nothrow_move_constructible_v<_Types> && ...)) = default;
938       template<typename _Tp,
939                typename = enable_if_t<__exactly_once<__accepted_type<_Tp&&>>
940                           && is_constructible_v<__accepted_type<_Tp&&>, _Tp&&>
941                           && !is_same_v<decay_t<_Tp>, variant>>>
942         constexpr
943         variant(_Tp&& __t)
944         noexcept(is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp&&>)
945         : variant(in_place_index<__accepted_index<_Tp&&>>, std::forward<_Tp>(__t))
946         { __glibcxx_assert(holds_alternative<__accepted_type<_Tp&&>>(*this)); }
948       template<typename _Tp, typename... _Args,
949                typename = enable_if_t<__exactly_once<_Tp>
950                           && is_constructible_v<_Tp, _Args&&...>>>
951         constexpr explicit
952         variant(in_place_type_t<_Tp>, _Args&&... __args)
953         : variant(in_place_index<__index_of<_Tp>>, std::forward<_Args>(__args)...)
954         { __glibcxx_assert(holds_alternative<_Tp>(*this)); }
956       template<typename _Tp, typename _Up, typename... _Args,
957                typename = enable_if_t<__exactly_once<_Tp>
958                           && is_constructible_v<
959                             _Tp, initializer_list<_Up>&, _Args&&...>>>
960         constexpr explicit
961         variant(in_place_type_t<_Tp>, initializer_list<_Up> __il,
962                 _Args&&... __args)
963         : variant(in_place_index<__index_of<_Tp>>, __il,
964                   std::forward<_Args>(__args)...)
965         { __glibcxx_assert(holds_alternative<_Tp>(*this)); }
967       template<size_t _Np, typename... _Args,
968                typename = enable_if_t<
969                  is_constructible_v<__to_type<_Np>, _Args&&...>>>
970         constexpr explicit
971         variant(in_place_index_t<_Np>, _Args&&... __args)
972         : _Base(in_place_index<_Np>, std::forward<_Args>(__args)...),
973         _Default_ctor_enabler(_Enable_default_constructor_tag{})
974         { __glibcxx_assert(index() == _Np); }
976       template<size_t _Np, typename _Up, typename... _Args,
977                typename = enable_if_t<is_constructible_v<__to_type<_Np>,
978                                       initializer_list<_Up>&, _Args&&...>>>
979         constexpr explicit
980         variant(in_place_index_t<_Np>, initializer_list<_Up> __il,
981                 _Args&&... __args)
982         : _Base(in_place_index<_Np>, __il, std::forward<_Args>(__args)...),
983         _Default_ctor_enabler(_Enable_default_constructor_tag{})
984         { __glibcxx_assert(index() == _Np); }
986       ~variant() = default;
988       variant& operator=(const variant&) = default;
989       variant& operator=(variant&&)
990       noexcept((is_nothrow_move_constructible_v<_Types> && ...)
991           && (is_nothrow_move_assignable_v<_Types> && ...)) = default;
993       template<typename _Tp>
994         enable_if_t<__exactly_once<__accepted_type<_Tp&&>>
995                     && is_constructible_v<__accepted_type<_Tp&&>, _Tp&&>
996                     && is_assignable_v<__accepted_type<_Tp&&>&, _Tp&&>
997                     && !is_same_v<decay_t<_Tp>, variant>, variant&>
998         operator=(_Tp&& __rhs)
999         noexcept(is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp&&>
1000                  && is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp&&>)
1001         {
1002           constexpr auto __index = __accepted_index<_Tp&&>;
1003           if (index() == __index)
1004             std::get<__index>(*this) = std::forward<_Tp>(__rhs);
1005           else
1006             this->emplace<__index>(std::forward<_Tp>(__rhs));
1007           __glibcxx_assert(holds_alternative<__accepted_type<_Tp&&>>(*this));
1008           return *this;
1009         }
1011       template<typename _Tp, typename... _Args>
1012         enable_if_t<is_constructible_v<_Tp, _Args...> && __exactly_once<_Tp>,
1013                     _Tp&>
1014         emplace(_Args&&... __args)
1015         {
1016           auto& ret =
1017             this->emplace<__index_of<_Tp>>(std::forward<_Args>(__args)...);
1018           __glibcxx_assert(holds_alternative<_Tp>(*this));
1019           return ret;
1020         }
1022       template<typename _Tp, typename _Up, typename... _Args>
1023         enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
1024                     && __exactly_once<_Tp>,
1025                     _Tp&>
1026         emplace(initializer_list<_Up> __il, _Args&&... __args)
1027         {
1028           auto& ret =
1029             this->emplace<__index_of<_Tp>>(__il,
1030                                            std::forward<_Args>(__args)...);
1031           __glibcxx_assert(holds_alternative<_Tp>(*this));
1032           return ret;
1033         }
1035       template<size_t _Np, typename... _Args>
1036         enable_if_t<is_constructible_v<variant_alternative_t<_Np, variant>,
1037                                        _Args...>,
1038                     variant_alternative_t<_Np, variant>&>
1039         emplace(_Args&&... __args)
1040         {
1041           static_assert(_Np < sizeof...(_Types),
1042                         "The index should be in [0, number of alternatives)");
1043           this->~variant();
1044           __try
1045             {
1046               ::new (this) variant(in_place_index<_Np>,
1047                                    std::forward<_Args>(__args)...);
1048             }
1049           __catch (...)
1050             {
1051               this->_M_index = variant_npos;
1052               __throw_exception_again;
1053             }
1054           __glibcxx_assert(index() == _Np);
1055           return std::get<_Np>(*this);
1056         }
1058       template<size_t _Np, typename _Up, typename... _Args>
1059         enable_if_t<is_constructible_v<variant_alternative_t<_Np, variant>,
1060                                        initializer_list<_Up>&, _Args...>,
1061                     variant_alternative_t<_Np, variant>&>
1062         emplace(initializer_list<_Up> __il, _Args&&... __args)
1063         {
1064           static_assert(_Np < sizeof...(_Types),
1065                         "The index should be in [0, number of alternatives)");
1066           this->~variant();
1067           __try
1068             {
1069               ::new (this) variant(in_place_index<_Np>, __il,
1070                                    std::forward<_Args>(__args)...);
1071             }
1072           __catch (...)
1073             {
1074               this->_M_index = variant_npos;
1075               __throw_exception_again;
1076             }
1077           __glibcxx_assert(index() == _Np);
1078           return std::get<_Np>(*this);
1079         }
1081       constexpr bool valueless_by_exception() const noexcept
1082       { return !this->_M_valid(); }
1084       constexpr size_t index() const noexcept
1085       {
1086         if (this->_M_index ==
1087             typename _Base::_Storage::__index_type(variant_npos))
1088           return variant_npos;
1089         return this->_M_index;
1090       }
1092       void
1093       swap(variant& __rhs)
1094       noexcept((__is_nothrow_swappable<_Types>::value && ...)
1095                && is_nothrow_move_constructible_v<variant>)
1096       {
1097         if (this->index() == __rhs.index())
1098           {
1099             if (this->_M_valid())
1100               {
1101                 static constexpr void (*_S_vtable[])(void*, void*) =
1102                   { &__detail::__variant::__erased_swap<_Types&, _Types&>... };
1103                 _S_vtable[__rhs._M_index](this->_M_storage(),
1104                                           __rhs._M_storage());
1105               }
1106           }
1107         else if (!this->_M_valid())
1108           {
1109             this->_M_destructive_move(std::move(__rhs));
1110             __rhs._M_reset();
1111           }
1112         else if (!__rhs._M_valid())
1113           {
1114             __rhs._M_destructive_move(std::move(*this));
1115             this->_M_reset();
1116           }
1117         else
1118           {
1119             auto __tmp = std::move(__rhs);
1120             __rhs._M_destructive_move(std::move(*this));
1121             this->_M_destructive_move(std::move(__tmp));
1122           }
1123       }
1125     private:
1126 #define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \
1127       template<size_t... __indices> \
1128         static constexpr bool \
1129         (*_S_erased_##__NAME[])(const variant&, const variant&) = \
1130           { &__detail::__variant::__erased_##__NAME< \
1131                 const variant&, __indices>... }; \
1132       template<size_t... __indices> \
1133         constexpr inline bool \
1134         _M_##__NAME(const variant& __rhs, \
1135                     std::index_sequence<__indices...>) const \
1136         { \
1137           auto __lhs_index = this->index(); \
1138           auto __rhs_index = __rhs.index(); \
1139           if (__lhs_index != __rhs_index || valueless_by_exception()) \
1140             /* Modulo addition. */ \
1141             return __lhs_index + 1 __OP __rhs_index + 1; \
1142           return _S_erased_##__NAME<__indices...>[__lhs_index](*this, __rhs); \
1143         }
1145       _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less)
1146       _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal)
1147       _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
1148       _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal)
1149       _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal)
1150       _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater)
1152 #undef _VARIANT_RELATION_FUNCTION_TEMPLATE
1154       template<size_t _Np, typename _Vp>
1155         friend constexpr decltype(auto) __detail::__variant::
1156 #if _GLIBCXX_INLINE_VERSION
1157         __7:: // Required due to PR c++/59256
1158 #endif
1159         __get(_Vp&& __v);
1161       template<typename _Vp>
1162         friend void* __detail::__variant::
1163 #if _GLIBCXX_INLINE_VERSION
1164         __7:: // Required due to PR c++/59256
1165 #endif
1166         __get_storage(_Vp&& __v);
1168 #define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP) \
1169       template<typename... _Tp> \
1170         friend constexpr bool \
1171         operator __OP(const variant<_Tp...>& __lhs, \
1172                       const variant<_Tp...>& __rhs);
1174       _VARIANT_RELATION_FUNCTION_TEMPLATE(<)
1175       _VARIANT_RELATION_FUNCTION_TEMPLATE(<=)
1176       _VARIANT_RELATION_FUNCTION_TEMPLATE(==)
1177       _VARIANT_RELATION_FUNCTION_TEMPLATE(!=)
1178       _VARIANT_RELATION_FUNCTION_TEMPLATE(>=)
1179       _VARIANT_RELATION_FUNCTION_TEMPLATE(>)
1181 #undef _VARIANT_RELATION_FUNCTION_TEMPLATE
1182     };
1184   template<size_t _Np, typename... _Types>
1185     constexpr variant_alternative_t<_Np, variant<_Types...>>&
1186     get(variant<_Types...>& __v)
1187     {
1188       static_assert(_Np < sizeof...(_Types),
1189                     "The index should be in [0, number of alternatives)");
1190       if (__v.index() != _Np)
1191         __throw_bad_variant_access("Unexpected index");
1192       return __detail::__variant::__get<_Np>(__v);
1193     }
1195   template<size_t _Np, typename... _Types>
1196     constexpr variant_alternative_t<_Np, variant<_Types...>>&&
1197     get(variant<_Types...>&& __v)
1198     {
1199       static_assert(_Np < sizeof...(_Types),
1200                     "The index should be in [0, number of alternatives)");
1201       if (__v.index() != _Np)
1202         __throw_bad_variant_access("Unexpected index");
1203       return __detail::__variant::__get<_Np>(std::move(__v));
1204     }
1206   template<size_t _Np, typename... _Types>
1207     constexpr const variant_alternative_t<_Np, variant<_Types...>>&
1208     get(const variant<_Types...>& __v)
1209     {
1210       static_assert(_Np < sizeof...(_Types),
1211                     "The index should be in [0, number of alternatives)");
1212       if (__v.index() != _Np)
1213         __throw_bad_variant_access("Unexpected index");
1214       return __detail::__variant::__get<_Np>(__v);
1215     }
1217   template<size_t _Np, typename... _Types>
1218     constexpr const variant_alternative_t<_Np, variant<_Types...>>&&
1219     get(const variant<_Types...>&& __v)
1220     {
1221       static_assert(_Np < sizeof...(_Types),
1222                     "The index should be in [0, number of alternatives)");
1223       if (__v.index() != _Np)
1224         __throw_bad_variant_access("Unexpected index");
1225       return __detail::__variant::__get<_Np>(std::move(__v));
1226     }
1228   template<typename _Visitor, typename... _Variants>
1229     constexpr decltype(auto)
1230     visit(_Visitor&& __visitor, _Variants&&... __variants)
1231     {
1232       if ((__variants.valueless_by_exception() || ...))
1233         __throw_bad_variant_access("Unexpected index");
1235       using _Result_type =
1236         decltype(std::forward<_Visitor>(__visitor)(
1237             get<0>(std::forward<_Variants>(__variants))...));
1239       constexpr auto& __vtable = __detail::__variant::__gen_vtable<
1240         _Result_type, _Visitor&&, _Variants&&...>::_S_vtable;
1242       auto __func_ptr = __vtable._M_access(__variants.index()...);
1243       return (*__func_ptr)(std::forward<_Visitor>(__visitor),
1244                            std::forward<_Variants>(__variants)...);
1245     }
1247   template<bool, typename... _Types>
1248     struct __variant_hash_call_base_impl
1249     {
1250       size_t
1251       operator()(const variant<_Types...>& __t) const
1252       noexcept((is_nothrow_invocable_v<hash<decay_t<_Types>>, _Types> && ...))
1253       {
1254         if (!__t.valueless_by_exception())
1255           {
1256             namespace __edv = __detail::__variant;
1257             static constexpr size_t (*_S_vtable[])(void*) =
1258               { &__edv::__erased_hash<const _Types&>... };
1259             return hash<size_t>{}(__t.index())
1260               + _S_vtable[__t.index()](__edv::__get_storage(__t));
1261           }
1262         return hash<size_t>{}(__t.index());
1263       }
1264     };
1266   template<typename... _Types>
1267     struct __variant_hash_call_base_impl<false, _Types...> {};
1269   template<typename... _Types>
1270     using __variant_hash_call_base =
1271     __variant_hash_call_base_impl<(__poison_hash<remove_const_t<_Types>>::
1272                                    __enable_hash_call &&...), _Types...>;
1274   template<typename... _Types>
1275     struct hash<variant<_Types...>>
1276     : private __detail::__variant::_Variant_hash_base<
1277         variant<_Types...>, std::index_sequence_for<_Types...>>,
1278       public __variant_hash_call_base<_Types...>
1279     {
1280       using result_type = size_t;
1281       using argument_type = variant<_Types...>;
1282     };
1284   template<>
1285     struct hash<monostate>
1286     {
1287       using result_type = size_t;
1288       using argument_type = monostate;
1290       size_t
1291       operator()(const monostate& __t) const noexcept
1292       {
1293         constexpr size_t __magic_monostate_hash = -7777;
1294         return __magic_monostate_hash;
1295       }
1296     };
1298 _GLIBCXX_END_NAMESPACE_VERSION
1299 } // namespace std
1301 #endif // C++17
1303 #endif // _GLIBCXX_VARIANT