xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/std/variant (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj// <variant> -*- C++ -*-
238fd1498Szrj
338fd1498Szrj// Copyright (C) 2016-2018 Free Software Foundation, Inc.
438fd1498Szrj//
538fd1498Szrj// This file is part of the GNU ISO C++ Library.  This library is free
638fd1498Szrj// software; you can redistribute it and/or modify it under the
738fd1498Szrj// terms of the GNU General Public License as published by the
838fd1498Szrj// Free Software Foundation; either version 3, or (at your option)
938fd1498Szrj// any later version.
1038fd1498Szrj
1138fd1498Szrj// This library is distributed in the hope that it will be useful,
1238fd1498Szrj// but WITHOUT ANY WARRANTY; without even the implied warranty of
1338fd1498Szrj// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1438fd1498Szrj// GNU General Public License for more details.
1538fd1498Szrj
1638fd1498Szrj// Under Section 7 of GPL version 3, you are granted additional
1738fd1498Szrj// permissions described in the GCC Runtime Library Exception, version
1838fd1498Szrj// 3.1, as published by the Free Software Foundation.
1938fd1498Szrj
2038fd1498Szrj// You should have received a copy of the GNU General Public License and
2138fd1498Szrj// a copy of the GCC Runtime Library Exception along with this program;
2238fd1498Szrj// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2338fd1498Szrj// <http://www.gnu.org/licenses/>.
2438fd1498Szrj
2538fd1498Szrj/** @file variant
2638fd1498Szrj *  This is the <variant> C++ Library header.
2738fd1498Szrj */
2838fd1498Szrj
2938fd1498Szrj#ifndef _GLIBCXX_VARIANT
3038fd1498Szrj#define _GLIBCXX_VARIANT 1
3138fd1498Szrj
3238fd1498Szrj#pragma GCC system_header
3338fd1498Szrj
3438fd1498Szrj#if __cplusplus >= 201703L
3538fd1498Szrj
3638fd1498Szrj#include <type_traits>
3738fd1498Szrj#include <utility>
3838fd1498Szrj#include <bits/enable_special_members.h>
3938fd1498Szrj#include <bits/functexcept.h>
4038fd1498Szrj#include <bits/move.h>
4138fd1498Szrj#include <bits/functional_hash.h>
4238fd1498Szrj#include <bits/invoke.h>
4338fd1498Szrj#include <ext/aligned_buffer.h>
4438fd1498Szrj#include <bits/parse_numbers.h>
4538fd1498Szrj#include <bits/stl_iterator_base_types.h>
4638fd1498Szrj#include <bits/stl_iterator_base_funcs.h>
4738fd1498Szrj#include <bits/stl_construct.h>
4838fd1498Szrj
4938fd1498Szrjnamespace std _GLIBCXX_VISIBILITY(default)
5038fd1498Szrj{
5138fd1498Szrj_GLIBCXX_BEGIN_NAMESPACE_VERSION
5238fd1498Szrj
5338fd1498Szrjnamespace __detail
5438fd1498Szrj{
5538fd1498Szrjnamespace __variant
5638fd1498Szrj{
5738fd1498Szrj  template<size_t _Np, typename... _Types>
5838fd1498Szrj    struct _Nth_type;
5938fd1498Szrj
6038fd1498Szrj  template<size_t _Np, typename _First, typename... _Rest>
6138fd1498Szrj    struct _Nth_type<_Np, _First, _Rest...>
6238fd1498Szrj    : _Nth_type<_Np-1, _Rest...> { };
6338fd1498Szrj
6438fd1498Szrj  template<typename _First, typename... _Rest>
6538fd1498Szrj    struct _Nth_type<0, _First, _Rest...>
6638fd1498Szrj    { using type = _First; };
6738fd1498Szrj
6838fd1498Szrj} // namespace __variant
6938fd1498Szrj} // namespace __detail
7038fd1498Szrj
7138fd1498Szrj#define __cpp_lib_variant 201603
7238fd1498Szrj
7338fd1498Szrj  template<typename... _Types> class tuple;
7438fd1498Szrj  template<typename... _Types> class variant;
7538fd1498Szrj  template <typename> struct hash;
7638fd1498Szrj
7738fd1498Szrj  template<typename _Variant>
7838fd1498Szrj    struct variant_size;
7938fd1498Szrj
8038fd1498Szrj  template<typename _Variant>
8138fd1498Szrj    struct variant_size<const _Variant> : variant_size<_Variant> {};
8238fd1498Szrj
8338fd1498Szrj  template<typename _Variant>
8438fd1498Szrj    struct variant_size<volatile _Variant> : variant_size<_Variant> {};
8538fd1498Szrj
8638fd1498Szrj  template<typename _Variant>
8738fd1498Szrj    struct variant_size<const volatile _Variant> : variant_size<_Variant> {};
8838fd1498Szrj
8938fd1498Szrj  template<typename... _Types>
9038fd1498Szrj    struct variant_size<variant<_Types...>>
9138fd1498Szrj    : std::integral_constant<size_t, sizeof...(_Types)> {};
9238fd1498Szrj
9338fd1498Szrj  template<typename _Variant>
9438fd1498Szrj    inline constexpr size_t variant_size_v = variant_size<_Variant>::value;
9538fd1498Szrj
9638fd1498Szrj  template<size_t _Np, typename _Variant>
9738fd1498Szrj    struct variant_alternative;
9838fd1498Szrj
9938fd1498Szrj  template<size_t _Np, typename _First, typename... _Rest>
10038fd1498Szrj    struct variant_alternative<_Np, variant<_First, _Rest...>>
10138fd1498Szrj    : variant_alternative<_Np-1, variant<_Rest...>> {};
10238fd1498Szrj
10338fd1498Szrj  template<typename _First, typename... _Rest>
10438fd1498Szrj    struct variant_alternative<0, variant<_First, _Rest...>>
10538fd1498Szrj    { using type = _First; };
10638fd1498Szrj
10738fd1498Szrj  template<size_t _Np, typename _Variant>
10838fd1498Szrj    using variant_alternative_t =
10938fd1498Szrj      typename variant_alternative<_Np, _Variant>::type;
11038fd1498Szrj
11138fd1498Szrj  template<size_t _Np, typename _Variant>
11238fd1498Szrj    struct variant_alternative<_Np, const _Variant>
11338fd1498Szrj    { using type = add_const_t<variant_alternative_t<_Np, _Variant>>; };
11438fd1498Szrj
11538fd1498Szrj  template<size_t _Np, typename _Variant>
11638fd1498Szrj    struct variant_alternative<_Np, volatile _Variant>
11738fd1498Szrj    { using type = add_volatile_t<variant_alternative_t<_Np, _Variant>>; };
11838fd1498Szrj
11938fd1498Szrj  template<size_t _Np, typename _Variant>
12038fd1498Szrj    struct variant_alternative<_Np, const volatile _Variant>
12138fd1498Szrj    { using type = add_cv_t<variant_alternative_t<_Np, _Variant>>; };
12238fd1498Szrj
12338fd1498Szrj  inline constexpr size_t variant_npos = -1;
12438fd1498Szrj
12538fd1498Szrj  template<size_t _Np, typename... _Types>
12638fd1498Szrj    constexpr variant_alternative_t<_Np, variant<_Types...>>&
12738fd1498Szrj    get(variant<_Types...>&);
12838fd1498Szrj
12938fd1498Szrj  template<size_t _Np, typename... _Types>
13038fd1498Szrj    constexpr variant_alternative_t<_Np, variant<_Types...>>&&
13138fd1498Szrj    get(variant<_Types...>&&);
13238fd1498Szrj
13338fd1498Szrj  template<size_t _Np, typename... _Types>
13438fd1498Szrj    constexpr variant_alternative_t<_Np, variant<_Types...>> const&
13538fd1498Szrj    get(const variant<_Types...>&);
13638fd1498Szrj
13738fd1498Szrj  template<size_t _Np, typename... _Types>
13838fd1498Szrj    constexpr variant_alternative_t<_Np, variant<_Types...>> const&&
13938fd1498Szrj    get(const variant<_Types...>&&);
14038fd1498Szrj
14138fd1498Szrjnamespace __detail
14238fd1498Szrj{
14338fd1498Szrjnamespace __variant
14438fd1498Szrj{
14538fd1498Szrj  // Returns the first apparence of _Tp in _Types.
14638fd1498Szrj  // Returns sizeof...(_Types) if _Tp is not in _Types.
14738fd1498Szrj  template<typename _Tp, typename... _Types>
14838fd1498Szrj    struct __index_of : std::integral_constant<size_t, 0> {};
14938fd1498Szrj
15038fd1498Szrj  template<typename _Tp, typename... _Types>
15138fd1498Szrj    inline constexpr size_t __index_of_v = __index_of<_Tp, _Types...>::value;
15238fd1498Szrj
15338fd1498Szrj  template<typename _Tp, typename _First, typename... _Rest>
15438fd1498Szrj    struct __index_of<_Tp, _First, _Rest...> :
15538fd1498Szrj      std::integral_constant<size_t, is_same_v<_Tp, _First>
15638fd1498Szrj	? 0 : __index_of_v<_Tp, _Rest...> + 1> {};
15738fd1498Szrj
15838fd1498Szrj  // _Uninitialized<T> is guaranteed to be a literal type, even if T is not.
15938fd1498Szrj  // We have to do this, because [basic.types]p10.5.3 (n4606) is not implemented
16038fd1498Szrj  // yet. When it's implemented, _Uninitialized<T> can be changed to the alias
16138fd1498Szrj  // to T, therefore equivalent to being removed entirely.
16238fd1498Szrj  //
16338fd1498Szrj  // Another reason we may not want to remove _Uninitialzied<T> may be that, we
16438fd1498Szrj  // want _Uninitialized<T> to be trivially destructible, no matter whether T
16538fd1498Szrj  // is; but we will see.
16638fd1498Szrj  template<typename _Type, bool = std::is_literal_type_v<_Type>>
16738fd1498Szrj    struct _Uninitialized;
16838fd1498Szrj
16938fd1498Szrj  template<typename _Type>
17038fd1498Szrj    struct _Uninitialized<_Type, true>
17138fd1498Szrj    {
17238fd1498Szrj      template<typename... _Args>
17338fd1498Szrj      constexpr _Uninitialized(in_place_index_t<0>, _Args&&... __args)
17438fd1498Szrj      : _M_storage(std::forward<_Args>(__args)...)
17538fd1498Szrj      { }
17638fd1498Szrj
17738fd1498Szrj      constexpr const _Type& _M_get() const &
17838fd1498Szrj      { return _M_storage; }
17938fd1498Szrj
18038fd1498Szrj      constexpr _Type& _M_get() &
18138fd1498Szrj      { return _M_storage; }
18238fd1498Szrj
18338fd1498Szrj      constexpr const _Type&& _M_get() const &&
18438fd1498Szrj      { return std::move(_M_storage); }
18538fd1498Szrj
18638fd1498Szrj      constexpr _Type&& _M_get() &&
18738fd1498Szrj      { return std::move(_M_storage); }
18838fd1498Szrj
18938fd1498Szrj      _Type _M_storage;
19038fd1498Szrj    };
19138fd1498Szrj
19238fd1498Szrj  template<typename _Type>
19338fd1498Szrj    struct _Uninitialized<_Type, false>
19438fd1498Szrj    {
19538fd1498Szrj      template<typename... _Args>
19638fd1498Szrj      constexpr _Uninitialized(in_place_index_t<0>, _Args&&... __args)
19738fd1498Szrj      { ::new (&_M_storage) _Type(std::forward<_Args>(__args)...); }
19838fd1498Szrj
19938fd1498Szrj      const _Type& _M_get() const &
20038fd1498Szrj      { return *_M_storage._M_ptr(); }
20138fd1498Szrj
20238fd1498Szrj      _Type& _M_get() &
20338fd1498Szrj      { return *_M_storage._M_ptr(); }
20438fd1498Szrj
20538fd1498Szrj      const _Type&& _M_get() const &&
20638fd1498Szrj      { return std::move(*_M_storage._M_ptr()); }
20738fd1498Szrj
20838fd1498Szrj      _Type&& _M_get() &&
20938fd1498Szrj      { return std::move(*_M_storage._M_ptr()); }
21038fd1498Szrj
21138fd1498Szrj      __gnu_cxx::__aligned_membuf<_Type> _M_storage;
21238fd1498Szrj    };
21338fd1498Szrj
21438fd1498Szrj  template<typename _Ref>
21538fd1498Szrj    _Ref __ref_cast(void* __ptr)
21638fd1498Szrj    {
21738fd1498Szrj      return static_cast<_Ref>(*static_cast<remove_reference_t<_Ref>*>(__ptr));
21838fd1498Szrj    }
21938fd1498Szrj
22038fd1498Szrj  template<typename _Union>
22138fd1498Szrj    constexpr decltype(auto) __get(in_place_index_t<0>, _Union&& __u)
22238fd1498Szrj    { return std::forward<_Union>(__u)._M_first._M_get(); }
22338fd1498Szrj
22438fd1498Szrj  template<size_t _Np, typename _Union>
22538fd1498Szrj    constexpr decltype(auto) __get(in_place_index_t<_Np>, _Union&& __u)
22638fd1498Szrj    {
22738fd1498Szrj      return __variant::__get(in_place_index<_Np-1>,
22838fd1498Szrj			      std::forward<_Union>(__u)._M_rest);
22938fd1498Szrj    }
23038fd1498Szrj
23138fd1498Szrj  // Returns the typed storage for __v.
23238fd1498Szrj  template<size_t _Np, typename _Variant>
23338fd1498Szrj    constexpr decltype(auto) __get(_Variant&& __v)
23438fd1498Szrj    {
23538fd1498Szrj      return __variant::__get(std::in_place_index<_Np>,
23638fd1498Szrj			      std::forward<_Variant>(__v)._M_u);
23738fd1498Szrj    }
23838fd1498Szrj
23938fd1498Szrj  // Various functions as "vtable" entries, where those vtables are used by
24038fd1498Szrj  // polymorphic operations.
24138fd1498Szrj  template<typename _Lhs, typename _Rhs>
24238fd1498Szrj    void
24338fd1498Szrj    __erased_ctor(void* __lhs, void* __rhs)
24438fd1498Szrj    {
24538fd1498Szrj      using _Type = remove_reference_t<_Lhs>;
24638fd1498Szrj      ::new (__lhs) _Type(__variant::__ref_cast<_Rhs>(__rhs));
24738fd1498Szrj    }
24838fd1498Szrj
24938fd1498Szrj  template<typename _Variant, size_t _Np>
25038fd1498Szrj    void
25138fd1498Szrj    __erased_dtor(_Variant&& __v)
252*58e805e6Szrj    { std::_Destroy(std::__addressof(__variant::__get<_Np>(__v))); }
25338fd1498Szrj
25438fd1498Szrj  template<typename _Lhs, typename _Rhs>
25538fd1498Szrj    void
25638fd1498Szrj    __erased_assign(void* __lhs, void* __rhs)
25738fd1498Szrj    {
25838fd1498Szrj      __variant::__ref_cast<_Lhs>(__lhs) = __variant::__ref_cast<_Rhs>(__rhs);
25938fd1498Szrj    }
26038fd1498Szrj
26138fd1498Szrj  template<typename _Lhs, typename _Rhs>
26238fd1498Szrj    void
26338fd1498Szrj    __erased_swap(void* __lhs, void* __rhs)
26438fd1498Szrj    {
26538fd1498Szrj      using std::swap;
26638fd1498Szrj      swap(__variant::__ref_cast<_Lhs>(__lhs),
26738fd1498Szrj	   __variant::__ref_cast<_Rhs>(__rhs));
26838fd1498Szrj    }
26938fd1498Szrj
27038fd1498Szrj#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \
27138fd1498Szrj  template<typename _Variant, size_t _Np> \
27238fd1498Szrj    constexpr bool \
27338fd1498Szrj    __erased_##__NAME(const _Variant& __lhs, const _Variant& __rhs) \
27438fd1498Szrj    { \
27538fd1498Szrj      return __variant::__get<_Np>(std::forward<_Variant>(__lhs)) \
27638fd1498Szrj	  __OP __variant::__get<_Np>(std::forward<_Variant>(__rhs)); \
27738fd1498Szrj    }
27838fd1498Szrj
27938fd1498Szrj  _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less)
28038fd1498Szrj  _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal)
28138fd1498Szrj  _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
28238fd1498Szrj  _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal)
28338fd1498Szrj  _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal)
28438fd1498Szrj  _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater)
28538fd1498Szrj
28638fd1498Szrj#undef _VARIANT_RELATION_FUNCTION_TEMPLATE
28738fd1498Szrj
28838fd1498Szrj  template<typename _Tp>
28938fd1498Szrj    size_t
29038fd1498Szrj    __erased_hash(void* __t)
29138fd1498Szrj    {
29238fd1498Szrj      return std::hash<remove_cv_t<remove_reference_t<_Tp>>>{}(
29338fd1498Szrj	  __variant::__ref_cast<_Tp>(__t));
29438fd1498Szrj    }
29538fd1498Szrj
29638fd1498Szrj  template<typename... _Types>
29738fd1498Szrj    struct _Traits
29838fd1498Szrj    {
29938fd1498Szrj      static constexpr bool _S_default_ctor =
30038fd1498Szrj	  is_default_constructible_v<typename _Nth_type<0, _Types...>::type>;
30138fd1498Szrj      static constexpr bool _S_copy_ctor =
30238fd1498Szrj	  (is_copy_constructible_v<_Types> && ...);
30338fd1498Szrj      static constexpr bool _S_move_ctor =
30438fd1498Szrj	  (is_move_constructible_v<_Types> && ...);
30538fd1498Szrj      static constexpr bool _S_copy_assign =
30638fd1498Szrj	  _S_copy_ctor && _S_move_ctor
30738fd1498Szrj	  && (is_copy_assignable_v<_Types> && ...);
30838fd1498Szrj      static constexpr bool _S_move_assign =
30938fd1498Szrj	  _S_move_ctor
31038fd1498Szrj	  && (is_move_assignable_v<_Types> && ...);
31138fd1498Szrj
31238fd1498Szrj      static constexpr bool _S_trivial_dtor =
31338fd1498Szrj	  (is_trivially_destructible_v<_Types> && ...);
31438fd1498Szrj      static constexpr bool _S_trivial_copy_ctor =
31538fd1498Szrj	  (is_trivially_copy_constructible_v<_Types> && ...);
31638fd1498Szrj      static constexpr bool _S_trivial_move_ctor =
31738fd1498Szrj	  (is_trivially_move_constructible_v<_Types> && ...);
31838fd1498Szrj      static constexpr bool _S_trivial_copy_assign =
31938fd1498Szrj	  _S_trivial_dtor && (is_trivially_copy_assignable_v<_Types> && ...);
32038fd1498Szrj      static constexpr bool _S_trivial_move_assign =
32138fd1498Szrj	  _S_trivial_dtor && (is_trivially_move_assignable_v<_Types> && ...);
32238fd1498Szrj
32338fd1498Szrj      // The following nothrow traits are for non-trivial SMFs. Trivial SMFs
32438fd1498Szrj      // are always nothrow.
32538fd1498Szrj      static constexpr bool _S_nothrow_default_ctor =
32638fd1498Szrj	  is_nothrow_default_constructible_v<
32738fd1498Szrj	      typename _Nth_type<0, _Types...>::type>;
32838fd1498Szrj      static constexpr bool _S_nothrow_copy_ctor = false;
32938fd1498Szrj      static constexpr bool _S_nothrow_move_ctor =
33038fd1498Szrj	  (is_nothrow_move_constructible_v<_Types> && ...);
33138fd1498Szrj      static constexpr bool _S_nothrow_copy_assign = false;
33238fd1498Szrj      static constexpr bool _S_nothrow_move_assign =
33338fd1498Szrj	  _S_nothrow_move_ctor && (is_nothrow_move_assignable_v<_Types> && ...);
33438fd1498Szrj    };
33538fd1498Szrj
33638fd1498Szrj  // Defines members and ctors.
33738fd1498Szrj  template<typename... _Types>
33838fd1498Szrj    union _Variadic_union { };
33938fd1498Szrj
34038fd1498Szrj  template<typename _First, typename... _Rest>
34138fd1498Szrj    union _Variadic_union<_First, _Rest...>
34238fd1498Szrj    {
34338fd1498Szrj      constexpr _Variadic_union() : _M_rest() { }
34438fd1498Szrj
34538fd1498Szrj      template<typename... _Args>
34638fd1498Szrj	constexpr _Variadic_union(in_place_index_t<0>, _Args&&... __args)
34738fd1498Szrj	: _M_first(in_place_index<0>, std::forward<_Args>(__args)...)
34838fd1498Szrj	{ }
34938fd1498Szrj
35038fd1498Szrj      template<size_t _Np, typename... _Args>
35138fd1498Szrj	constexpr _Variadic_union(in_place_index_t<_Np>, _Args&&... __args)
35238fd1498Szrj	: _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...)
35338fd1498Szrj	{ }
35438fd1498Szrj
35538fd1498Szrj      _Uninitialized<_First> _M_first;
35638fd1498Szrj      _Variadic_union<_Rest...> _M_rest;
35738fd1498Szrj    };
35838fd1498Szrj
35938fd1498Szrj  // Defines index and the dtor, possibly trivial.
36038fd1498Szrj  template<bool __trivially_destructible, typename... _Types>
36138fd1498Szrj    struct _Variant_storage;
36238fd1498Szrj
36338fd1498Szrj  template <typename... _Types>
36438fd1498Szrj  using __select_index =
36538fd1498Szrj    typename __select_int::_Select_int_base<sizeof...(_Types) + 1,
36638fd1498Szrj					    unsigned char,
36738fd1498Szrj					    unsigned short>::type::value_type;
36838fd1498Szrj
36938fd1498Szrj  template<typename... _Types>
37038fd1498Szrj    struct _Variant_storage<false, _Types...>
37138fd1498Szrj    {
37238fd1498Szrj      template<size_t... __indices>
37338fd1498Szrj	static constexpr void (*_S_vtable[])(const _Variant_storage&) =
37438fd1498Szrj	    { &__erased_dtor<const _Variant_storage&, __indices>... };
37538fd1498Szrj
37638fd1498Szrj      constexpr _Variant_storage() : _M_index(variant_npos) { }
37738fd1498Szrj
37838fd1498Szrj      template<size_t _Np, typename... _Args>
37938fd1498Szrj	constexpr _Variant_storage(in_place_index_t<_Np>, _Args&&... __args)
38038fd1498Szrj	: _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...),
38138fd1498Szrj	_M_index(_Np)
38238fd1498Szrj	{ }
38338fd1498Szrj
38438fd1498Szrj      template<size_t... __indices>
38538fd1498Szrj	constexpr void _M_reset_impl(std::index_sequence<__indices...>)
38638fd1498Szrj	{
38738fd1498Szrj	  if (_M_index != __index_type(variant_npos))
38838fd1498Szrj	    _S_vtable<__indices...>[_M_index](*this);
38938fd1498Szrj	}
39038fd1498Szrj
39138fd1498Szrj      void _M_reset()
39238fd1498Szrj      {
39338fd1498Szrj	_M_reset_impl(std::index_sequence_for<_Types...>{});
39438fd1498Szrj	_M_index = variant_npos;
39538fd1498Szrj      }
39638fd1498Szrj
39738fd1498Szrj      ~_Variant_storage()
39838fd1498Szrj      { _M_reset(); }
39938fd1498Szrj
40038fd1498Szrj      void*
40138fd1498Szrj      _M_storage() const
40238fd1498Szrj      {
40338fd1498Szrj	return const_cast<void*>(static_cast<const void*>(
40438fd1498Szrj	    std::addressof(_M_u)));
40538fd1498Szrj      }
40638fd1498Szrj
40738fd1498Szrj      constexpr bool
40838fd1498Szrj      _M_valid() const noexcept
40938fd1498Szrj      {
41038fd1498Szrj	return this->_M_index != __index_type(variant_npos);
41138fd1498Szrj      }
41238fd1498Szrj
41338fd1498Szrj      _Variadic_union<_Types...> _M_u;
41438fd1498Szrj      using __index_type = __select_index<_Types...>;
41538fd1498Szrj      __index_type _M_index;
41638fd1498Szrj    };
41738fd1498Szrj
41838fd1498Szrj  template<typename... _Types>
41938fd1498Szrj    struct _Variant_storage<true, _Types...>
42038fd1498Szrj    {
42138fd1498Szrj      constexpr _Variant_storage() : _M_index(variant_npos) { }
42238fd1498Szrj
42338fd1498Szrj      template<size_t _Np, typename... _Args>
42438fd1498Szrj	constexpr _Variant_storage(in_place_index_t<_Np>, _Args&&... __args)
42538fd1498Szrj	: _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...),
42638fd1498Szrj	_M_index(_Np)
42738fd1498Szrj	{ }
42838fd1498Szrj
42938fd1498Szrj      void _M_reset()
43038fd1498Szrj      { _M_index = variant_npos; }
43138fd1498Szrj
43238fd1498Szrj      void*
43338fd1498Szrj      _M_storage() const
43438fd1498Szrj      {
43538fd1498Szrj	return const_cast<void*>(static_cast<const void*>(
43638fd1498Szrj	    std::addressof(_M_u)));
43738fd1498Szrj      }
43838fd1498Szrj
43938fd1498Szrj      constexpr bool
44038fd1498Szrj      _M_valid() const noexcept
44138fd1498Szrj      {
44238fd1498Szrj	return this->_M_index != __index_type(variant_npos);
44338fd1498Szrj      }
44438fd1498Szrj
44538fd1498Szrj      _Variadic_union<_Types...> _M_u;
44638fd1498Szrj      using __index_type = __select_index<_Types...>;
44738fd1498Szrj      __index_type _M_index;
44838fd1498Szrj    };
44938fd1498Szrj
45038fd1498Szrj  template<typename... _Types>
45138fd1498Szrj    using _Variant_storage_alias =
45238fd1498Szrj	_Variant_storage<_Traits<_Types...>::_S_trivial_dtor, _Types...>;
45338fd1498Szrj
45438fd1498Szrj  // The following are (Copy|Move) (ctor|assign) layers for forwarding
45538fd1498Szrj  // triviality and handling non-trivial SMF behaviors.
45638fd1498Szrj
45738fd1498Szrj  template<bool, typename... _Types>
45838fd1498Szrj    struct _Copy_ctor_base : _Variant_storage_alias<_Types...>
45938fd1498Szrj    {
46038fd1498Szrj      using _Base = _Variant_storage_alias<_Types...>;
46138fd1498Szrj      using _Base::_Base;
46238fd1498Szrj
46338fd1498Szrj      _Copy_ctor_base(const _Copy_ctor_base& __rhs)
46438fd1498Szrj	  noexcept(_Traits<_Types...>::_S_nothrow_copy_ctor)
46538fd1498Szrj      {
46638fd1498Szrj	if (__rhs._M_valid())
46738fd1498Szrj	  {
46838fd1498Szrj	    static constexpr void (*_S_vtable[])(void*, void*) =
46938fd1498Szrj	      { &__erased_ctor<_Types&, const _Types&>... };
47038fd1498Szrj	    _S_vtable[__rhs._M_index](this->_M_storage(), __rhs._M_storage());
47138fd1498Szrj	    this->_M_index = __rhs._M_index;
47238fd1498Szrj	  }
47338fd1498Szrj      }
47438fd1498Szrj
47538fd1498Szrj      _Copy_ctor_base(_Copy_ctor_base&&) = default;
47638fd1498Szrj      _Copy_ctor_base& operator=(const _Copy_ctor_base&) = default;
47738fd1498Szrj      _Copy_ctor_base& operator=(_Copy_ctor_base&&) = default;
47838fd1498Szrj    };
47938fd1498Szrj
48038fd1498Szrj  template<typename... _Types>
48138fd1498Szrj    struct _Copy_ctor_base<true, _Types...> : _Variant_storage_alias<_Types...>
48238fd1498Szrj    {
48338fd1498Szrj      using _Base = _Variant_storage_alias<_Types...>;
48438fd1498Szrj      using _Base::_Base;
48538fd1498Szrj    };
48638fd1498Szrj
48738fd1498Szrj  template<typename... _Types>
48838fd1498Szrj    using _Copy_ctor_alias =
48938fd1498Szrj	_Copy_ctor_base<_Traits<_Types...>::_S_trivial_copy_ctor, _Types...>;
49038fd1498Szrj
49138fd1498Szrj  template<bool, typename... _Types>
49238fd1498Szrj    struct _Move_ctor_base : _Copy_ctor_alias<_Types...>
49338fd1498Szrj    {
49438fd1498Szrj      using _Base = _Copy_ctor_alias<_Types...>;
49538fd1498Szrj      using _Base::_Base;
49638fd1498Szrj
49738fd1498Szrj      _Move_ctor_base(_Move_ctor_base&& __rhs)
49838fd1498Szrj	  noexcept(_Traits<_Types...>::_S_nothrow_move_ctor)
49938fd1498Szrj      {
50038fd1498Szrj	if (__rhs._M_valid())
50138fd1498Szrj	  {
50238fd1498Szrj	    static constexpr void (*_S_vtable[])(void*, void*) =
50338fd1498Szrj	      { &__erased_ctor<_Types&, _Types&&>... };
50438fd1498Szrj	    _S_vtable[__rhs._M_index](this->_M_storage(), __rhs._M_storage());
50538fd1498Szrj	    this->_M_index = __rhs._M_index;
50638fd1498Szrj	  }
50738fd1498Szrj      }
50838fd1498Szrj
509*58e805e6Szrj      void _M_destructive_move(_Move_ctor_base&& __rhs)
510*58e805e6Szrj      {
511*58e805e6Szrj	this->~_Move_ctor_base();
512*58e805e6Szrj	__try
513*58e805e6Szrj	  {
514*58e805e6Szrj	    ::new (this) _Move_ctor_base(std::move(__rhs));
515*58e805e6Szrj	  }
516*58e805e6Szrj	__catch (...)
517*58e805e6Szrj	  {
518*58e805e6Szrj	    this->_M_index = variant_npos;
519*58e805e6Szrj	    __throw_exception_again;
520*58e805e6Szrj	  }
521*58e805e6Szrj      }
522*58e805e6Szrj
52338fd1498Szrj      _Move_ctor_base(const _Move_ctor_base&) = default;
52438fd1498Szrj      _Move_ctor_base& operator=(const _Move_ctor_base&) = default;
52538fd1498Szrj      _Move_ctor_base& operator=(_Move_ctor_base&&) = default;
52638fd1498Szrj    };
52738fd1498Szrj
52838fd1498Szrj  template<typename... _Types>
52938fd1498Szrj    struct _Move_ctor_base<true, _Types...> : _Copy_ctor_alias<_Types...>
53038fd1498Szrj    {
53138fd1498Szrj      using _Base = _Copy_ctor_alias<_Types...>;
53238fd1498Szrj      using _Base::_Base;
533*58e805e6Szrj
534*58e805e6Szrj      void _M_destructive_move(_Move_ctor_base&& __rhs)
535*58e805e6Szrj      {
536*58e805e6Szrj	this->~_Move_ctor_base();
537*58e805e6Szrj	::new (this) _Move_ctor_base(std::move(__rhs));
538*58e805e6Szrj      }
53938fd1498Szrj    };
54038fd1498Szrj
54138fd1498Szrj  template<typename... _Types>
54238fd1498Szrj    using _Move_ctor_alias =
54338fd1498Szrj	_Move_ctor_base<_Traits<_Types...>::_S_trivial_move_ctor, _Types...>;
54438fd1498Szrj
54538fd1498Szrj  template<bool, typename... _Types>
54638fd1498Szrj    struct _Copy_assign_base : _Move_ctor_alias<_Types...>
54738fd1498Szrj    {
54838fd1498Szrj      using _Base = _Move_ctor_alias<_Types...>;
54938fd1498Szrj      using _Base::_Base;
55038fd1498Szrj
55138fd1498Szrj      _Copy_assign_base&
55238fd1498Szrj      operator=(const _Copy_assign_base& __rhs)
55338fd1498Szrj	  noexcept(_Traits<_Types...>::_S_nothrow_copy_assign)
55438fd1498Szrj      {
55538fd1498Szrj	if (this->_M_index == __rhs._M_index)
55638fd1498Szrj	  {
55738fd1498Szrj	    if (__rhs._M_valid())
55838fd1498Szrj	      {
55938fd1498Szrj		static constexpr void (*_S_vtable[])(void*, void*) =
56038fd1498Szrj		  { &__erased_assign<_Types&, const _Types&>... };
561*58e805e6Szrj		_S_vtable[__rhs._M_index](this->_M_storage(),
562*58e805e6Szrj					  __rhs._M_storage());
56338fd1498Szrj	      }
56438fd1498Szrj	  }
56538fd1498Szrj	else
56638fd1498Szrj	  {
56738fd1498Szrj	    _Copy_assign_base __tmp(__rhs);
568*58e805e6Szrj	    this->_M_destructive_move(std::move(__tmp));
56938fd1498Szrj	  }
57038fd1498Szrj	__glibcxx_assert(this->_M_index == __rhs._M_index);
57138fd1498Szrj	return *this;
57238fd1498Szrj      }
57338fd1498Szrj
57438fd1498Szrj      _Copy_assign_base(const _Copy_assign_base&) = default;
57538fd1498Szrj      _Copy_assign_base(_Copy_assign_base&&) = default;
57638fd1498Szrj      _Copy_assign_base& operator=(_Copy_assign_base&&) = default;
57738fd1498Szrj    };
57838fd1498Szrj
57938fd1498Szrj  template<typename... _Types>
58038fd1498Szrj    struct _Copy_assign_base<true, _Types...> : _Move_ctor_alias<_Types...>
58138fd1498Szrj    {
58238fd1498Szrj      using _Base = _Move_ctor_alias<_Types...>;
58338fd1498Szrj      using _Base::_Base;
58438fd1498Szrj    };
58538fd1498Szrj
58638fd1498Szrj  template<typename... _Types>
58738fd1498Szrj    using _Copy_assign_alias =
58838fd1498Szrj	_Copy_assign_base<_Traits<_Types...>::_S_trivial_copy_assign,
58938fd1498Szrj			  _Types...>;
59038fd1498Szrj
59138fd1498Szrj  template<bool, typename... _Types>
59238fd1498Szrj    struct _Move_assign_base : _Copy_assign_alias<_Types...>
59338fd1498Szrj    {
59438fd1498Szrj      using _Base = _Copy_assign_alias<_Types...>;
59538fd1498Szrj      using _Base::_Base;
59638fd1498Szrj
59738fd1498Szrj      _Move_assign_base&
59838fd1498Szrj      operator=(_Move_assign_base&& __rhs)
59938fd1498Szrj	  noexcept(_Traits<_Types...>::_S_nothrow_move_assign)
60038fd1498Szrj      {
60138fd1498Szrj	if (this->_M_index == __rhs._M_index)
60238fd1498Szrj	  {
60338fd1498Szrj	    if (__rhs._M_valid())
60438fd1498Szrj	      {
60538fd1498Szrj		static constexpr void (*_S_vtable[])(void*, void*) =
60638fd1498Szrj		  { &__erased_assign<_Types&, _Types&&>... };
60738fd1498Szrj		_S_vtable[__rhs._M_index]
60838fd1498Szrj		  (this->_M_storage(), __rhs._M_storage());
60938fd1498Szrj	      }
61038fd1498Szrj	  }
61138fd1498Szrj	else
61238fd1498Szrj	  {
61338fd1498Szrj	    _Move_assign_base __tmp(std::move(__rhs));
614*58e805e6Szrj	    this->_M_destructive_move(std::move(__tmp));
61538fd1498Szrj	  }
61638fd1498Szrj	__glibcxx_assert(this->_M_index == __rhs._M_index);
61738fd1498Szrj	return *this;
61838fd1498Szrj      }
61938fd1498Szrj
62038fd1498Szrj      _Move_assign_base(const _Move_assign_base&) = default;
62138fd1498Szrj      _Move_assign_base(_Move_assign_base&&) = default;
62238fd1498Szrj      _Move_assign_base& operator=(const _Move_assign_base&) = default;
62338fd1498Szrj    };
62438fd1498Szrj
62538fd1498Szrj  template<typename... _Types>
62638fd1498Szrj    struct _Move_assign_base<true, _Types...> : _Copy_assign_alias<_Types...>
62738fd1498Szrj    {
62838fd1498Szrj      using _Base = _Copy_assign_alias<_Types...>;
62938fd1498Szrj      using _Base::_Base;
63038fd1498Szrj    };
63138fd1498Szrj
63238fd1498Szrj  template<typename... _Types>
63338fd1498Szrj    using _Move_assign_alias =
63438fd1498Szrj	_Move_assign_base<_Traits<_Types...>::_S_trivial_move_assign,
63538fd1498Szrj			  _Types...>;
63638fd1498Szrj
63738fd1498Szrj  template<typename... _Types>
63838fd1498Szrj    struct _Variant_base : _Move_assign_alias<_Types...>
63938fd1498Szrj    {
64038fd1498Szrj      using _Base = _Move_assign_alias<_Types...>;
64138fd1498Szrj
64238fd1498Szrj      constexpr
64338fd1498Szrj      _Variant_base()
64438fd1498Szrj	  noexcept(_Traits<_Types...>::_S_nothrow_default_ctor)
64538fd1498Szrj      : _Variant_base(in_place_index<0>) { }
64638fd1498Szrj
64738fd1498Szrj      template<size_t _Np, typename... _Args>
64838fd1498Szrj	constexpr explicit
64938fd1498Szrj	_Variant_base(in_place_index_t<_Np> __i, _Args&&... __args)
65038fd1498Szrj	: _Base(__i, std::forward<_Args>(__args)...)
65138fd1498Szrj	{ }
65238fd1498Szrj
65338fd1498Szrj      _Variant_base(const _Variant_base&) = default;
65438fd1498Szrj      _Variant_base(_Variant_base&&) = default;
65538fd1498Szrj      _Variant_base& operator=(const _Variant_base&) = default;
65638fd1498Szrj      _Variant_base& operator=(_Variant_base&&) = default;
65738fd1498Szrj    };
65838fd1498Szrj
65938fd1498Szrj  // For how many times does _Tp appear in _Tuple?
66038fd1498Szrj  template<typename _Tp, typename _Tuple>
66138fd1498Szrj    struct __tuple_count;
66238fd1498Szrj
66338fd1498Szrj  template<typename _Tp, typename _Tuple>
66438fd1498Szrj    inline constexpr size_t __tuple_count_v =
66538fd1498Szrj      __tuple_count<_Tp, _Tuple>::value;
66638fd1498Szrj
66738fd1498Szrj  template<typename _Tp, typename... _Types>
66838fd1498Szrj    struct __tuple_count<_Tp, tuple<_Types...>>
66938fd1498Szrj    : integral_constant<size_t, 0> { };
67038fd1498Szrj
67138fd1498Szrj  template<typename _Tp, typename _First, typename... _Rest>
67238fd1498Szrj    struct __tuple_count<_Tp, tuple<_First, _Rest...>>
67338fd1498Szrj    : integral_constant<
67438fd1498Szrj	size_t,
67538fd1498Szrj	__tuple_count_v<_Tp, tuple<_Rest...>> + is_same_v<_Tp, _First>> { };
67638fd1498Szrj
67738fd1498Szrj  // TODO: Reuse this in <tuple> ?
67838fd1498Szrj  template<typename _Tp, typename... _Types>
67938fd1498Szrj    inline constexpr bool __exactly_once =
68038fd1498Szrj      __tuple_count_v<_Tp, tuple<_Types...>> == 1;
68138fd1498Szrj
68238fd1498Szrj  // Takes _Types and create an overloaded _S_fun for each type.
68338fd1498Szrj  // If a type appears more than once in _Types, create only one overload.
68438fd1498Szrj  template<typename... _Types>
68538fd1498Szrj    struct __overload_set
68638fd1498Szrj    { static void _S_fun(); };
68738fd1498Szrj
68838fd1498Szrj  template<typename _First, typename... _Rest>
68938fd1498Szrj    struct __overload_set<_First, _Rest...> : __overload_set<_Rest...>
69038fd1498Szrj    {
69138fd1498Szrj      using __overload_set<_Rest...>::_S_fun;
69238fd1498Szrj      static integral_constant<size_t, sizeof...(_Rest)> _S_fun(_First);
69338fd1498Szrj    };
69438fd1498Szrj
69538fd1498Szrj  template<typename... _Rest>
69638fd1498Szrj    struct __overload_set<void, _Rest...> : __overload_set<_Rest...>
69738fd1498Szrj    {
69838fd1498Szrj      using __overload_set<_Rest...>::_S_fun;
69938fd1498Szrj    };
70038fd1498Szrj
70138fd1498Szrj  // Helper for variant(_Tp&&) and variant::operator=(_Tp&&).
70238fd1498Szrj  // __accepted_index maps the arbitrary _Tp to an alternative type in _Variant.
70338fd1498Szrj  template<typename _Tp, typename _Variant, typename = void>
70438fd1498Szrj    struct __accepted_index
70538fd1498Szrj    { static constexpr size_t value = variant_npos; };
70638fd1498Szrj
70738fd1498Szrj  template<typename _Tp, typename... _Types>
70838fd1498Szrj    struct __accepted_index<
70938fd1498Szrj      _Tp, variant<_Types...>,
71038fd1498Szrj      decltype(__overload_set<_Types...>::_S_fun(std::declval<_Tp>()),
71138fd1498Szrj	       std::declval<void>())>
71238fd1498Szrj    {
71338fd1498Szrj      static constexpr size_t value = sizeof...(_Types) - 1
71438fd1498Szrj	- decltype(__overload_set<_Types...>::
71538fd1498Szrj		   _S_fun(std::declval<_Tp>()))::value;
71638fd1498Szrj    };
71738fd1498Szrj
71838fd1498Szrj  // Returns the raw storage for __v.
71938fd1498Szrj  template<typename _Variant>
72038fd1498Szrj    void* __get_storage(_Variant&& __v)
72138fd1498Szrj    { return __v._M_storage(); }
72238fd1498Szrj
72338fd1498Szrj  // Used for storing multi-dimensional vtable.
72438fd1498Szrj  template<typename _Tp, size_t... _Dimensions>
72538fd1498Szrj    struct _Multi_array
72638fd1498Szrj    {
72738fd1498Szrj      constexpr const _Tp&
72838fd1498Szrj      _M_access() const
72938fd1498Szrj      { return _M_data; }
73038fd1498Szrj
73138fd1498Szrj      _Tp _M_data;
73238fd1498Szrj    };
73338fd1498Szrj
73438fd1498Szrj  template<typename _Tp, size_t __first, size_t... __rest>
73538fd1498Szrj    struct _Multi_array<_Tp, __first, __rest...>
73638fd1498Szrj    {
73738fd1498Szrj      template<typename... _Args>
73838fd1498Szrj	constexpr const _Tp&
73938fd1498Szrj	_M_access(size_t __first_index, _Args... __rest_indices) const
74038fd1498Szrj	{ return _M_arr[__first_index]._M_access(__rest_indices...); }
74138fd1498Szrj
74238fd1498Szrj      _Multi_array<_Tp, __rest...> _M_arr[__first];
74338fd1498Szrj    };
74438fd1498Szrj
74538fd1498Szrj  // Creates a multi-dimensional vtable recursively.
74638fd1498Szrj  //
74738fd1498Szrj  // For example,
74838fd1498Szrj  // visit([](auto, auto){},
74938fd1498Szrj  //       variant<int, char>(),  // typedef'ed as V1
75038fd1498Szrj  //       variant<float, double, long double>())  // typedef'ed as V2
75138fd1498Szrj  // will trigger instantiations of:
75238fd1498Szrj  // __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 2, 3>,
75338fd1498Szrj  //                   tuple<V1&&, V2&&>, std::index_sequence<>>
75438fd1498Szrj  //   __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 3>,
75538fd1498Szrj  //                     tuple<V1&&, V2&&>, std::index_sequence<0>>
75638fd1498Szrj  //     __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
75738fd1498Szrj  //                       tuple<V1&&, V2&&>, std::index_sequence<0, 0>>
75838fd1498Szrj  //     __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
75938fd1498Szrj  //                       tuple<V1&&, V2&&>, std::index_sequence<0, 1>>
76038fd1498Szrj  //     __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
76138fd1498Szrj  //                       tuple<V1&&, V2&&>, std::index_sequence<0, 2>>
76238fd1498Szrj  //   __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&), 3>,
76338fd1498Szrj  //                     tuple<V1&&, V2&&>, std::index_sequence<1>>
76438fd1498Szrj  //     __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
76538fd1498Szrj  //                       tuple<V1&&, V2&&>, std::index_sequence<1, 0>>
76638fd1498Szrj  //     __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
76738fd1498Szrj  //                       tuple<V1&&, V2&&>, std::index_sequence<1, 1>>
76838fd1498Szrj  //     __gen_vtable_impl<_Multi_array<void(*)(V1&&, V2&&)>,
76938fd1498Szrj  //                       tuple<V1&&, V2&&>, std::index_sequence<1, 2>>
77038fd1498Szrj  // The returned multi-dimensional vtable can be fast accessed by the visitor
77138fd1498Szrj  // using index calculation.
77238fd1498Szrj  template<typename _Array_type, typename _Variant_tuple, typename _Index_seq>
77338fd1498Szrj    struct __gen_vtable_impl;
77438fd1498Szrj
77538fd1498Szrj  template<typename _Result_type, typename _Visitor, size_t... __dimensions,
77638fd1498Szrj	   typename... _Variants, size_t... __indices>
77738fd1498Szrj    struct __gen_vtable_impl<
77838fd1498Szrj	_Multi_array<_Result_type (*)(_Visitor, _Variants...), __dimensions...>,
77938fd1498Szrj	tuple<_Variants...>, std::index_sequence<__indices...>>
78038fd1498Szrj    {
78138fd1498Szrj      using _Next =
78238fd1498Szrj	  remove_reference_t<typename _Nth_type<sizeof...(__indices),
78338fd1498Szrj			     _Variants...>::type>;
78438fd1498Szrj      using _Array_type =
78538fd1498Szrj	  _Multi_array<_Result_type (*)(_Visitor, _Variants...),
78638fd1498Szrj		       __dimensions...>;
78738fd1498Szrj
78838fd1498Szrj      static constexpr _Array_type
78938fd1498Szrj      _S_apply()
79038fd1498Szrj      {
79138fd1498Szrj	_Array_type __vtable{};
79238fd1498Szrj	_S_apply_all_alts(
79338fd1498Szrj	  __vtable, make_index_sequence<variant_size_v<_Next>>());
79438fd1498Szrj	return __vtable;
79538fd1498Szrj      }
79638fd1498Szrj
79738fd1498Szrj      template<size_t... __var_indices>
79838fd1498Szrj	static constexpr void
79938fd1498Szrj	_S_apply_all_alts(_Array_type& __vtable,
80038fd1498Szrj			  std::index_sequence<__var_indices...>)
80138fd1498Szrj	{
80238fd1498Szrj	  (_S_apply_single_alt<__var_indices>(
80338fd1498Szrj	     __vtable._M_arr[__var_indices]), ...);
80438fd1498Szrj	}
80538fd1498Szrj
80638fd1498Szrj      template<size_t __index, typename _Tp>
80738fd1498Szrj	static constexpr void
80838fd1498Szrj	_S_apply_single_alt(_Tp& __element)
80938fd1498Szrj	{
81038fd1498Szrj	  using _Alternative = variant_alternative_t<__index, _Next>;
81138fd1498Szrj	  __element = __gen_vtable_impl<
81238fd1498Szrj	    remove_reference_t<
81338fd1498Szrj	      decltype(__element)>, tuple<_Variants...>,
81438fd1498Szrj	      std::index_sequence<__indices..., __index>>::_S_apply();
81538fd1498Szrj	}
81638fd1498Szrj    };
81738fd1498Szrj
81838fd1498Szrj  template<typename _Result_type, typename _Visitor, typename... _Variants,
81938fd1498Szrj	   size_t... __indices>
82038fd1498Szrj    struct __gen_vtable_impl<
82138fd1498Szrj      _Multi_array<_Result_type (*)(_Visitor, _Variants...)>,
82238fd1498Szrj		   tuple<_Variants...>, std::index_sequence<__indices...>>
82338fd1498Szrj    {
82438fd1498Szrj      using _Array_type =
82538fd1498Szrj	  _Multi_array<_Result_type (*)(_Visitor&&, _Variants...)>;
82638fd1498Szrj
82738fd1498Szrj      decltype(auto)
82838fd1498Szrj      static constexpr __visit_invoke(_Visitor&& __visitor, _Variants... __vars)
82938fd1498Szrj      {
830*58e805e6Szrj	return std::__invoke(std::forward<_Visitor>(__visitor),
831*58e805e6Szrj	    std::get<__indices>(std::forward<_Variants>(__vars))...);
83238fd1498Szrj      }
83338fd1498Szrj
83438fd1498Szrj      static constexpr auto
83538fd1498Szrj      _S_apply()
83638fd1498Szrj      { return _Array_type{&__visit_invoke}; }
83738fd1498Szrj    };
83838fd1498Szrj
83938fd1498Szrj  template<typename _Result_type, typename _Visitor, typename... _Variants>
84038fd1498Szrj    struct __gen_vtable
84138fd1498Szrj    {
84238fd1498Szrj      using _Func_ptr = _Result_type (*)(_Visitor&&, _Variants...);
84338fd1498Szrj      using _Array_type =
84438fd1498Szrj	  _Multi_array<_Func_ptr,
84538fd1498Szrj		       variant_size_v<remove_reference_t<_Variants>>...>;
84638fd1498Szrj
84738fd1498Szrj      static constexpr _Array_type
84838fd1498Szrj      _S_apply()
84938fd1498Szrj      {
85038fd1498Szrj	return __gen_vtable_impl<_Array_type, tuple<_Variants...>,
85138fd1498Szrj				 std::index_sequence<>>::_S_apply();
85238fd1498Szrj      }
85338fd1498Szrj
85438fd1498Szrj      static constexpr auto _S_vtable = _S_apply();
85538fd1498Szrj    };
85638fd1498Szrj
85738fd1498Szrj  template<size_t _Np, typename _Tp>
85838fd1498Szrj    struct _Base_dedup : public _Tp { };
85938fd1498Szrj
86038fd1498Szrj  template<typename _Variant, typename __indices>
86138fd1498Szrj    struct _Variant_hash_base;
86238fd1498Szrj
86338fd1498Szrj  template<typename... _Types, size_t... __indices>
86438fd1498Szrj    struct _Variant_hash_base<variant<_Types...>,
86538fd1498Szrj			      std::index_sequence<__indices...>>
86638fd1498Szrj    : _Base_dedup<__indices, __poison_hash<remove_const_t<_Types>>>... { };
86738fd1498Szrj
86838fd1498Szrj} // namespace __variant
86938fd1498Szrj} // namespace __detail
87038fd1498Szrj
87138fd1498Szrj  template<typename _Tp, typename... _Types>
87238fd1498Szrj    inline constexpr bool holds_alternative(const variant<_Types...>& __v)
87338fd1498Szrj    noexcept
87438fd1498Szrj    {
87538fd1498Szrj      static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
87638fd1498Szrj		    "T should occur for exactly once in alternatives");
87738fd1498Szrj      return __v.index() == __detail::__variant::__index_of_v<_Tp, _Types...>;
87838fd1498Szrj    }
87938fd1498Szrj
88038fd1498Szrj  template<typename _Tp, typename... _Types>
88138fd1498Szrj    constexpr inline _Tp& get(variant<_Types...>& __v)
88238fd1498Szrj    {
88338fd1498Szrj      static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
88438fd1498Szrj		    "T should occur for exactly once in alternatives");
88538fd1498Szrj      static_assert(!is_void_v<_Tp>, "_Tp should not be void");
88638fd1498Szrj      return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v);
88738fd1498Szrj    }
88838fd1498Szrj
88938fd1498Szrj  template<typename _Tp, typename... _Types>
89038fd1498Szrj    constexpr inline _Tp&& get(variant<_Types...>&& __v)
89138fd1498Szrj    {
89238fd1498Szrj      static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
89338fd1498Szrj		    "T should occur for exactly once in alternatives");
89438fd1498Szrj      static_assert(!is_void_v<_Tp>, "_Tp should not be void");
89538fd1498Szrj      return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(
89638fd1498Szrj	std::move(__v));
89738fd1498Szrj    }
89838fd1498Szrj
89938fd1498Szrj  template<typename _Tp, typename... _Types>
90038fd1498Szrj    constexpr inline const _Tp& get(const variant<_Types...>& __v)
90138fd1498Szrj    {
90238fd1498Szrj      static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
90338fd1498Szrj		    "T should occur for exactly once in alternatives");
90438fd1498Szrj      static_assert(!is_void_v<_Tp>, "_Tp should not be void");
90538fd1498Szrj      return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v);
90638fd1498Szrj    }
90738fd1498Szrj
90838fd1498Szrj  template<typename _Tp, typename... _Types>
90938fd1498Szrj    constexpr inline const _Tp&& get(const variant<_Types...>&& __v)
91038fd1498Szrj    {
91138fd1498Szrj      static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
91238fd1498Szrj		    "T should occur for exactly once in alternatives");
91338fd1498Szrj      static_assert(!is_void_v<_Tp>, "_Tp should not be void");
91438fd1498Szrj      return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(
91538fd1498Szrj	std::move(__v));
91638fd1498Szrj    }
91738fd1498Szrj
91838fd1498Szrj  template<size_t _Np, typename... _Types>
91938fd1498Szrj    constexpr inline
92038fd1498Szrj    add_pointer_t<variant_alternative_t<_Np, variant<_Types...>>>
92138fd1498Szrj    get_if(variant<_Types...>* __ptr) noexcept
92238fd1498Szrj    {
92338fd1498Szrj      using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>;
92438fd1498Szrj      static_assert(_Np < sizeof...(_Types),
92538fd1498Szrj		    "The index should be in [0, number of alternatives)");
92638fd1498Szrj      static_assert(!is_void_v<_Alternative_type>, "_Tp should not be void");
92738fd1498Szrj      if (__ptr && __ptr->index() == _Np)
92838fd1498Szrj	return &__detail::__variant::__get<_Np>(*__ptr);
92938fd1498Szrj      return nullptr;
93038fd1498Szrj    }
93138fd1498Szrj
93238fd1498Szrj  template<size_t _Np, typename... _Types>
93338fd1498Szrj    constexpr inline
93438fd1498Szrj    add_pointer_t<const variant_alternative_t<_Np, variant<_Types...>>>
93538fd1498Szrj    get_if(const variant<_Types...>* __ptr) noexcept
93638fd1498Szrj    {
93738fd1498Szrj      using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>;
93838fd1498Szrj      static_assert(_Np < sizeof...(_Types),
93938fd1498Szrj		    "The index should be in [0, number of alternatives)");
94038fd1498Szrj      static_assert(!is_void_v<_Alternative_type>, "_Tp should not be void");
94138fd1498Szrj      if (__ptr && __ptr->index() == _Np)
94238fd1498Szrj	return &__detail::__variant::__get<_Np>(*__ptr);
94338fd1498Szrj      return nullptr;
94438fd1498Szrj    }
94538fd1498Szrj
94638fd1498Szrj  template<typename _Tp, typename... _Types>
94738fd1498Szrj    constexpr inline add_pointer_t<_Tp>
94838fd1498Szrj    get_if(variant<_Types...>* __ptr) noexcept
94938fd1498Szrj    {
95038fd1498Szrj      static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
95138fd1498Szrj		    "T should occur for exactly once in alternatives");
95238fd1498Szrj      static_assert(!is_void_v<_Tp>, "_Tp should not be void");
95338fd1498Szrj      return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>(
95438fd1498Szrj	  __ptr);
95538fd1498Szrj    }
95638fd1498Szrj
95738fd1498Szrj  template<typename _Tp, typename... _Types>
95838fd1498Szrj    constexpr inline add_pointer_t<const _Tp>
95938fd1498Szrj    get_if(const variant<_Types...>* __ptr)
96038fd1498Szrj    noexcept
96138fd1498Szrj    {
96238fd1498Szrj      static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
96338fd1498Szrj		    "T should occur for exactly once in alternatives");
96438fd1498Szrj      static_assert(!is_void_v<_Tp>, "_Tp should not be void");
96538fd1498Szrj      return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>(
96638fd1498Szrj	  __ptr);
96738fd1498Szrj    }
96838fd1498Szrj
96938fd1498Szrj  struct monostate { };
97038fd1498Szrj
97138fd1498Szrj#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \
97238fd1498Szrj  template<typename... _Types> \
97338fd1498Szrj    constexpr bool operator __OP(const variant<_Types...>& __lhs, \
97438fd1498Szrj				 const variant<_Types...>& __rhs) \
97538fd1498Szrj    { \
97638fd1498Szrj      return __lhs._M_##__NAME(__rhs, std::index_sequence_for<_Types...>{}); \
97738fd1498Szrj    } \
97838fd1498Szrj\
97938fd1498Szrj  constexpr bool operator __OP(monostate, monostate) noexcept \
98038fd1498Szrj  { return 0 __OP 0; }
98138fd1498Szrj
98238fd1498Szrj  _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less)
98338fd1498Szrj  _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal)
98438fd1498Szrj  _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
98538fd1498Szrj  _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal)
98638fd1498Szrj  _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal)
98738fd1498Szrj  _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater)
98838fd1498Szrj
98938fd1498Szrj#undef _VARIANT_RELATION_FUNCTION_TEMPLATE
99038fd1498Szrj
99138fd1498Szrj  template<typename _Visitor, typename... _Variants>
99238fd1498Szrj    constexpr decltype(auto) visit(_Visitor&&, _Variants&&...);
99338fd1498Szrj
99438fd1498Szrj  template<typename... _Types>
99538fd1498Szrj    inline enable_if_t<(is_move_constructible_v<_Types> && ...)
99638fd1498Szrj			&& (is_swappable_v<_Types> && ...)>
99738fd1498Szrj    swap(variant<_Types...>& __lhs, variant<_Types...>& __rhs)
99838fd1498Szrj    noexcept(noexcept(__lhs.swap(__rhs)))
99938fd1498Szrj    { __lhs.swap(__rhs); }
100038fd1498Szrj
100138fd1498Szrj  template<typename... _Types>
100238fd1498Szrj    enable_if_t<!((is_move_constructible_v<_Types> && ...)
100338fd1498Szrj		   && (is_swappable_v<_Types> && ...))>
100438fd1498Szrj    swap(variant<_Types...>&, variant<_Types...>&) = delete;
100538fd1498Szrj
100638fd1498Szrj  class bad_variant_access : public exception
100738fd1498Szrj  {
100838fd1498Szrj  public:
100938fd1498Szrj    bad_variant_access() noexcept : _M_reason("Unknown reason") { }
101038fd1498Szrj    const char* what() const noexcept override
101138fd1498Szrj    { return _M_reason; }
101238fd1498Szrj
101338fd1498Szrj  private:
101438fd1498Szrj    bad_variant_access(const char* __reason) : _M_reason(__reason) { }
101538fd1498Szrj
101638fd1498Szrj    const char* _M_reason;
101738fd1498Szrj
101838fd1498Szrj    friend void __throw_bad_variant_access(const char* __what);
101938fd1498Szrj  };
102038fd1498Szrj
102138fd1498Szrj  inline void
102238fd1498Szrj  __throw_bad_variant_access(const char* __what)
102338fd1498Szrj  { _GLIBCXX_THROW_OR_ABORT(bad_variant_access(__what)); }
102438fd1498Szrj
102538fd1498Szrj  template<typename... _Types>
102638fd1498Szrj    class variant
102738fd1498Szrj    : private __detail::__variant::_Variant_base<_Types...>,
102838fd1498Szrj      private _Enable_default_constructor<
102938fd1498Szrj	__detail::__variant::_Traits<_Types...>::_S_default_ctor,
103038fd1498Szrj	  variant<_Types...>>,
103138fd1498Szrj      private _Enable_copy_move<
103238fd1498Szrj	__detail::__variant::_Traits<_Types...>::_S_copy_ctor,
103338fd1498Szrj	__detail::__variant::_Traits<_Types...>::_S_copy_assign,
103438fd1498Szrj	__detail::__variant::_Traits<_Types...>::_S_move_ctor,
103538fd1498Szrj	__detail::__variant::_Traits<_Types...>::_S_move_assign,
103638fd1498Szrj	variant<_Types...>>
103738fd1498Szrj    {
103838fd1498Szrj    private:
103938fd1498Szrj      static_assert(sizeof...(_Types) > 0,
104038fd1498Szrj		    "variant must have at least one alternative");
104138fd1498Szrj      static_assert(!(std::is_reference_v<_Types> || ...),
104238fd1498Szrj		    "variant must have no reference alternative");
104338fd1498Szrj      static_assert(!(std::is_void_v<_Types> || ...),
104438fd1498Szrj		    "variant must have no void alternative");
104538fd1498Szrj
104638fd1498Szrj      using _Base = __detail::__variant::_Variant_base<_Types...>;
104738fd1498Szrj      using _Default_ctor_enabler =
104838fd1498Szrj	_Enable_default_constructor<
104938fd1498Szrj	  __detail::__variant::_Traits<_Types...>::_S_default_ctor,
105038fd1498Szrj	    variant<_Types...>>;
105138fd1498Szrj
105238fd1498Szrj      template<typename _Tp>
105338fd1498Szrj	static constexpr bool
105438fd1498Szrj	__exactly_once = __detail::__variant::__exactly_once<_Tp, _Types...>;
105538fd1498Szrj
105638fd1498Szrj      template<typename _Tp>
105738fd1498Szrj	static constexpr size_t __accepted_index =
105838fd1498Szrj	  __detail::__variant::__accepted_index<_Tp&&, variant>::value;
105938fd1498Szrj
106038fd1498Szrj      template<size_t _Np, bool = _Np < sizeof...(_Types)>
106138fd1498Szrj	struct __to_type_impl;
106238fd1498Szrj
106338fd1498Szrj      template<size_t _Np>
106438fd1498Szrj	struct __to_type_impl<_Np, true>
106538fd1498Szrj	{ using type = variant_alternative_t<_Np, variant>; };
106638fd1498Szrj
106738fd1498Szrj      template<size_t _Np>
106838fd1498Szrj	using __to_type = typename __to_type_impl<_Np>::type;
106938fd1498Szrj
107038fd1498Szrj      template<typename _Tp>
107138fd1498Szrj	using __accepted_type = __to_type<__accepted_index<_Tp>>;
107238fd1498Szrj
107338fd1498Szrj      template<typename _Tp>
107438fd1498Szrj	static constexpr size_t __index_of =
107538fd1498Szrj	  __detail::__variant::__index_of_v<_Tp, _Types...>;
107638fd1498Szrj
107738fd1498Szrj      using _Traits = __detail::__variant::_Traits<_Types...>;
107838fd1498Szrj
107938fd1498Szrj    public:
108038fd1498Szrj      variant() = default;
108138fd1498Szrj      variant(const variant& __rhs) = default;
108238fd1498Szrj      variant(variant&&) = default;
108338fd1498Szrj      variant& operator=(const variant&) = default;
108438fd1498Szrj      variant& operator=(variant&&) = default;
108538fd1498Szrj      ~variant() = default;
108638fd1498Szrj
108738fd1498Szrj      template<typename _Tp,
108838fd1498Szrj	       typename = enable_if_t<!is_same_v<decay_t<_Tp>, variant>>,
108938fd1498Szrj	       typename = enable_if_t<(sizeof...(_Types)>0)>,
109038fd1498Szrj	       typename = enable_if_t<__exactly_once<__accepted_type<_Tp&&>>
109138fd1498Szrj			  && is_constructible_v<__accepted_type<_Tp&&>, _Tp&&>>>
109238fd1498Szrj	constexpr
109338fd1498Szrj	variant(_Tp&& __t)
109438fd1498Szrj	noexcept(is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp&&>)
109538fd1498Szrj	: variant(in_place_index<__accepted_index<_Tp&&>>,
109638fd1498Szrj		  std::forward<_Tp>(__t))
109738fd1498Szrj	{ __glibcxx_assert(holds_alternative<__accepted_type<_Tp&&>>(*this)); }
109838fd1498Szrj
109938fd1498Szrj      template<typename _Tp, typename... _Args,
110038fd1498Szrj	       typename = enable_if_t<__exactly_once<_Tp>
110138fd1498Szrj			  && is_constructible_v<_Tp, _Args&&...>>>
110238fd1498Szrj	constexpr explicit
110338fd1498Szrj	variant(in_place_type_t<_Tp>, _Args&&... __args)
110438fd1498Szrj	: variant(in_place_index<__index_of<_Tp>>,
110538fd1498Szrj		  std::forward<_Args>(__args)...)
110638fd1498Szrj	{ __glibcxx_assert(holds_alternative<_Tp>(*this)); }
110738fd1498Szrj
110838fd1498Szrj      template<typename _Tp, typename _Up, typename... _Args,
110938fd1498Szrj	       typename = enable_if_t<__exactly_once<_Tp>
111038fd1498Szrj			  && is_constructible_v<
111138fd1498Szrj			    _Tp, initializer_list<_Up>&, _Args&&...>>>
111238fd1498Szrj	constexpr explicit
111338fd1498Szrj	variant(in_place_type_t<_Tp>, initializer_list<_Up> __il,
111438fd1498Szrj		_Args&&... __args)
111538fd1498Szrj	: variant(in_place_index<__index_of<_Tp>>, __il,
111638fd1498Szrj		  std::forward<_Args>(__args)...)
111738fd1498Szrj	{ __glibcxx_assert(holds_alternative<_Tp>(*this)); }
111838fd1498Szrj
111938fd1498Szrj      template<size_t _Np, typename... _Args,
112038fd1498Szrj	       typename = enable_if_t<
112138fd1498Szrj		 is_constructible_v<__to_type<_Np>, _Args&&...>>>
112238fd1498Szrj	constexpr explicit
112338fd1498Szrj	variant(in_place_index_t<_Np>, _Args&&... __args)
112438fd1498Szrj	: _Base(in_place_index<_Np>, std::forward<_Args>(__args)...),
112538fd1498Szrj	_Default_ctor_enabler(_Enable_default_constructor_tag{})
112638fd1498Szrj	{ __glibcxx_assert(index() == _Np); }
112738fd1498Szrj
112838fd1498Szrj      template<size_t _Np, typename _Up, typename... _Args,
112938fd1498Szrj	       typename = enable_if_t<is_constructible_v<__to_type<_Np>,
113038fd1498Szrj				      initializer_list<_Up>&, _Args&&...>>>
113138fd1498Szrj	constexpr explicit
113238fd1498Szrj	variant(in_place_index_t<_Np>, initializer_list<_Up> __il,
113338fd1498Szrj		_Args&&... __args)
113438fd1498Szrj	: _Base(in_place_index<_Np>, __il, std::forward<_Args>(__args)...),
113538fd1498Szrj	_Default_ctor_enabler(_Enable_default_constructor_tag{})
113638fd1498Szrj	{ __glibcxx_assert(index() == _Np); }
113738fd1498Szrj
113838fd1498Szrj      template<typename _Tp>
113938fd1498Szrj	enable_if_t<__exactly_once<__accepted_type<_Tp&&>>
114038fd1498Szrj		    && is_constructible_v<__accepted_type<_Tp&&>, _Tp&&>
114138fd1498Szrj		    && is_assignable_v<__accepted_type<_Tp&&>&, _Tp&&>
114238fd1498Szrj		    && !is_same_v<decay_t<_Tp>, variant>, variant&>
114338fd1498Szrj	operator=(_Tp&& __rhs)
114438fd1498Szrj	noexcept(is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp&&>
114538fd1498Szrj		 && is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp&&>)
114638fd1498Szrj	{
114738fd1498Szrj	  constexpr auto __index = __accepted_index<_Tp&&>;
114838fd1498Szrj	  if (index() == __index)
114938fd1498Szrj	    std::get<__index>(*this) = std::forward<_Tp>(__rhs);
115038fd1498Szrj	  else
115138fd1498Szrj	    this->emplace<__index>(std::forward<_Tp>(__rhs));
115238fd1498Szrj	  __glibcxx_assert(holds_alternative<__accepted_type<_Tp&&>>(*this));
115338fd1498Szrj	  return *this;
115438fd1498Szrj	}
115538fd1498Szrj
115638fd1498Szrj      template<typename _Tp, typename... _Args>
115738fd1498Szrj	enable_if_t<is_constructible_v<_Tp, _Args...> && __exactly_once<_Tp>,
115838fd1498Szrj		    _Tp&>
115938fd1498Szrj	emplace(_Args&&... __args)
116038fd1498Szrj	{
116138fd1498Szrj	  auto& ret =
116238fd1498Szrj	    this->emplace<__index_of<_Tp>>(std::forward<_Args>(__args)...);
116338fd1498Szrj	  __glibcxx_assert(holds_alternative<_Tp>(*this));
116438fd1498Szrj	  return ret;
116538fd1498Szrj	}
116638fd1498Szrj
116738fd1498Szrj      template<typename _Tp, typename _Up, typename... _Args>
116838fd1498Szrj	enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
116938fd1498Szrj		    && __exactly_once<_Tp>,
117038fd1498Szrj		    _Tp&>
117138fd1498Szrj	emplace(initializer_list<_Up> __il, _Args&&... __args)
117238fd1498Szrj	{
117338fd1498Szrj	  auto& ret =
117438fd1498Szrj	    this->emplace<__index_of<_Tp>>(__il,
117538fd1498Szrj					   std::forward<_Args>(__args)...);
117638fd1498Szrj	  __glibcxx_assert(holds_alternative<_Tp>(*this));
117738fd1498Szrj	  return ret;
117838fd1498Szrj	}
117938fd1498Szrj
118038fd1498Szrj      template<size_t _Np, typename... _Args>
118138fd1498Szrj	enable_if_t<is_constructible_v<variant_alternative_t<_Np, variant>,
118238fd1498Szrj				       _Args...>,
118338fd1498Szrj		    variant_alternative_t<_Np, variant>&>
118438fd1498Szrj	emplace(_Args&&... __args)
118538fd1498Szrj	{
118638fd1498Szrj	  static_assert(_Np < sizeof...(_Types),
118738fd1498Szrj			"The index should be in [0, number of alternatives)");
118838fd1498Szrj	  this->~variant();
118938fd1498Szrj	  __try
119038fd1498Szrj	    {
119138fd1498Szrj	      ::new (this) variant(in_place_index<_Np>,
119238fd1498Szrj				   std::forward<_Args>(__args)...);
119338fd1498Szrj	    }
119438fd1498Szrj	  __catch (...)
119538fd1498Szrj	    {
119638fd1498Szrj	      this->_M_index = variant_npos;
119738fd1498Szrj	      __throw_exception_again;
119838fd1498Szrj	    }
119938fd1498Szrj	  __glibcxx_assert(index() == _Np);
120038fd1498Szrj	  return std::get<_Np>(*this);
120138fd1498Szrj	}
120238fd1498Szrj
120338fd1498Szrj      template<size_t _Np, typename _Up, typename... _Args>
120438fd1498Szrj	enable_if_t<is_constructible_v<variant_alternative_t<_Np, variant>,
120538fd1498Szrj				       initializer_list<_Up>&, _Args...>,
120638fd1498Szrj		    variant_alternative_t<_Np, variant>&>
120738fd1498Szrj	emplace(initializer_list<_Up> __il, _Args&&... __args)
120838fd1498Szrj	{
120938fd1498Szrj	  static_assert(_Np < sizeof...(_Types),
121038fd1498Szrj			"The index should be in [0, number of alternatives)");
121138fd1498Szrj	  this->~variant();
121238fd1498Szrj	  __try
121338fd1498Szrj	    {
121438fd1498Szrj	      ::new (this) variant(in_place_index<_Np>, __il,
121538fd1498Szrj				   std::forward<_Args>(__args)...);
121638fd1498Szrj	    }
121738fd1498Szrj	  __catch (...)
121838fd1498Szrj	    {
121938fd1498Szrj	      this->_M_index = variant_npos;
122038fd1498Szrj	      __throw_exception_again;
122138fd1498Szrj	    }
122238fd1498Szrj	  __glibcxx_assert(index() == _Np);
122338fd1498Szrj	  return std::get<_Np>(*this);
122438fd1498Szrj	}
122538fd1498Szrj
122638fd1498Szrj      constexpr bool valueless_by_exception() const noexcept
122738fd1498Szrj      { return !this->_M_valid(); }
122838fd1498Szrj
122938fd1498Szrj      constexpr size_t index() const noexcept
123038fd1498Szrj      {
123138fd1498Szrj	if (this->_M_index ==
123238fd1498Szrj	    typename _Base::__index_type(variant_npos))
123338fd1498Szrj	  return variant_npos;
123438fd1498Szrj	return this->_M_index;
123538fd1498Szrj      }
123638fd1498Szrj
123738fd1498Szrj      void
123838fd1498Szrj      swap(variant& __rhs)
123938fd1498Szrj      noexcept((__is_nothrow_swappable<_Types>::value && ...)
124038fd1498Szrj	       && is_nothrow_move_constructible_v<variant>)
124138fd1498Szrj      {
124238fd1498Szrj	if (this->index() == __rhs.index())
124338fd1498Szrj	  {
124438fd1498Szrj	    if (this->_M_valid())
124538fd1498Szrj	      {
124638fd1498Szrj		static constexpr void (*_S_vtable[])(void*, void*) =
124738fd1498Szrj		  { &__detail::__variant::__erased_swap<_Types&, _Types&>... };
124838fd1498Szrj		_S_vtable[__rhs._M_index](this->_M_storage(),
124938fd1498Szrj					  __rhs._M_storage());
125038fd1498Szrj	      }
125138fd1498Szrj	  }
125238fd1498Szrj	else if (!this->_M_valid())
125338fd1498Szrj	  {
125438fd1498Szrj	    this->_M_destructive_move(std::move(__rhs));
125538fd1498Szrj	    __rhs._M_reset();
125638fd1498Szrj	  }
125738fd1498Szrj	else if (!__rhs._M_valid())
125838fd1498Szrj	  {
125938fd1498Szrj	    __rhs._M_destructive_move(std::move(*this));
126038fd1498Szrj	    this->_M_reset();
126138fd1498Szrj	  }
126238fd1498Szrj	else
126338fd1498Szrj	  {
126438fd1498Szrj	    auto __tmp = std::move(__rhs);
126538fd1498Szrj	    __rhs._M_destructive_move(std::move(*this));
126638fd1498Szrj	    this->_M_destructive_move(std::move(__tmp));
126738fd1498Szrj	  }
126838fd1498Szrj      }
126938fd1498Szrj
127038fd1498Szrj    private:
127138fd1498Szrj#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \
127238fd1498Szrj      template<size_t... __indices> \
127338fd1498Szrj	static constexpr bool \
127438fd1498Szrj	(*_S_erased_##__NAME[])(const variant&, const variant&) = \
127538fd1498Szrj	  { &__detail::__variant::__erased_##__NAME< \
127638fd1498Szrj		const variant&, __indices>... }; \
127738fd1498Szrj      template<size_t... __indices> \
127838fd1498Szrj	constexpr inline bool \
127938fd1498Szrj	_M_##__NAME(const variant& __rhs, \
128038fd1498Szrj		    std::index_sequence<__indices...>) const \
128138fd1498Szrj	{ \
128238fd1498Szrj	  auto __lhs_index = this->index(); \
128338fd1498Szrj	  auto __rhs_index = __rhs.index(); \
128438fd1498Szrj	  if (__lhs_index != __rhs_index || valueless_by_exception()) \
128538fd1498Szrj	    /* Modulo addition. */ \
128638fd1498Szrj	    return __lhs_index + 1 __OP __rhs_index + 1; \
128738fd1498Szrj	  return _S_erased_##__NAME<__indices...>[__lhs_index](*this, __rhs); \
128838fd1498Szrj	}
128938fd1498Szrj
129038fd1498Szrj      _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less)
129138fd1498Szrj      _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal)
129238fd1498Szrj      _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
129338fd1498Szrj      _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal)
129438fd1498Szrj      _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal)
129538fd1498Szrj      _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater)
129638fd1498Szrj
129738fd1498Szrj#undef _VARIANT_RELATION_FUNCTION_TEMPLATE
129838fd1498Szrj
129938fd1498Szrj#ifdef __clang__
130038fd1498Szrj    public:
130138fd1498Szrj      using _Base::_M_u; // See https://bugs.llvm.org/show_bug.cgi?id=31852
130238fd1498Szrj    private:
130338fd1498Szrj#endif
130438fd1498Szrj
130538fd1498Szrj      template<size_t _Np, typename _Vp>
130638fd1498Szrj	friend constexpr decltype(auto) __detail::__variant::__get(_Vp&& __v);
130738fd1498Szrj
130838fd1498Szrj      template<typename _Vp>
130938fd1498Szrj	friend void* __detail::__variant::__get_storage(_Vp&& __v);
131038fd1498Szrj
131138fd1498Szrj#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP) \
131238fd1498Szrj      template<typename... _Tp> \
131338fd1498Szrj	friend constexpr bool \
131438fd1498Szrj	operator __OP(const variant<_Tp...>& __lhs, \
131538fd1498Szrj		      const variant<_Tp...>& __rhs);
131638fd1498Szrj
131738fd1498Szrj      _VARIANT_RELATION_FUNCTION_TEMPLATE(<)
131838fd1498Szrj      _VARIANT_RELATION_FUNCTION_TEMPLATE(<=)
131938fd1498Szrj      _VARIANT_RELATION_FUNCTION_TEMPLATE(==)
132038fd1498Szrj      _VARIANT_RELATION_FUNCTION_TEMPLATE(!=)
132138fd1498Szrj      _VARIANT_RELATION_FUNCTION_TEMPLATE(>=)
132238fd1498Szrj      _VARIANT_RELATION_FUNCTION_TEMPLATE(>)
132338fd1498Szrj
132438fd1498Szrj#undef _VARIANT_RELATION_FUNCTION_TEMPLATE
132538fd1498Szrj    };
132638fd1498Szrj
132738fd1498Szrj  template<size_t _Np, typename... _Types>
132838fd1498Szrj    constexpr variant_alternative_t<_Np, variant<_Types...>>&
132938fd1498Szrj    get(variant<_Types...>& __v)
133038fd1498Szrj    {
133138fd1498Szrj      static_assert(_Np < sizeof...(_Types),
133238fd1498Szrj		    "The index should be in [0, number of alternatives)");
133338fd1498Szrj      if (__v.index() != _Np)
133438fd1498Szrj	__throw_bad_variant_access("Unexpected index");
133538fd1498Szrj      return __detail::__variant::__get<_Np>(__v);
133638fd1498Szrj    }
133738fd1498Szrj
133838fd1498Szrj  template<size_t _Np, typename... _Types>
133938fd1498Szrj    constexpr variant_alternative_t<_Np, variant<_Types...>>&&
134038fd1498Szrj    get(variant<_Types...>&& __v)
134138fd1498Szrj    {
134238fd1498Szrj      static_assert(_Np < sizeof...(_Types),
134338fd1498Szrj		    "The index should be in [0, number of alternatives)");
134438fd1498Szrj      if (__v.index() != _Np)
134538fd1498Szrj	__throw_bad_variant_access("Unexpected index");
134638fd1498Szrj      return __detail::__variant::__get<_Np>(std::move(__v));
134738fd1498Szrj    }
134838fd1498Szrj
134938fd1498Szrj  template<size_t _Np, typename... _Types>
135038fd1498Szrj    constexpr const variant_alternative_t<_Np, variant<_Types...>>&
135138fd1498Szrj    get(const variant<_Types...>& __v)
135238fd1498Szrj    {
135338fd1498Szrj      static_assert(_Np < sizeof...(_Types),
135438fd1498Szrj		    "The index should be in [0, number of alternatives)");
135538fd1498Szrj      if (__v.index() != _Np)
135638fd1498Szrj	__throw_bad_variant_access("Unexpected index");
135738fd1498Szrj      return __detail::__variant::__get<_Np>(__v);
135838fd1498Szrj    }
135938fd1498Szrj
136038fd1498Szrj  template<size_t _Np, typename... _Types>
136138fd1498Szrj    constexpr const variant_alternative_t<_Np, variant<_Types...>>&&
136238fd1498Szrj    get(const variant<_Types...>&& __v)
136338fd1498Szrj    {
136438fd1498Szrj      static_assert(_Np < sizeof...(_Types),
136538fd1498Szrj		    "The index should be in [0, number of alternatives)");
136638fd1498Szrj      if (__v.index() != _Np)
136738fd1498Szrj	__throw_bad_variant_access("Unexpected index");
136838fd1498Szrj      return __detail::__variant::__get<_Np>(std::move(__v));
136938fd1498Szrj    }
137038fd1498Szrj
137138fd1498Szrj  template<typename _Visitor, typename... _Variants>
137238fd1498Szrj    constexpr decltype(auto)
137338fd1498Szrj    visit(_Visitor&& __visitor, _Variants&&... __variants)
137438fd1498Szrj    {
137538fd1498Szrj      if ((__variants.valueless_by_exception() || ...))
137638fd1498Szrj	__throw_bad_variant_access("Unexpected index");
137738fd1498Szrj
137838fd1498Szrj      using _Result_type =
137938fd1498Szrj	decltype(std::forward<_Visitor>(__visitor)(
1380*58e805e6Szrj	    std::get<0>(std::forward<_Variants>(__variants))...));
138138fd1498Szrj
138238fd1498Szrj      constexpr auto& __vtable = __detail::__variant::__gen_vtable<
138338fd1498Szrj	_Result_type, _Visitor&&, _Variants&&...>::_S_vtable;
138438fd1498Szrj
138538fd1498Szrj      auto __func_ptr = __vtable._M_access(__variants.index()...);
138638fd1498Szrj      return (*__func_ptr)(std::forward<_Visitor>(__visitor),
138738fd1498Szrj			   std::forward<_Variants>(__variants)...);
138838fd1498Szrj    }
138938fd1498Szrj
139038fd1498Szrj  template<bool, typename... _Types>
139138fd1498Szrj    struct __variant_hash_call_base_impl
139238fd1498Szrj    {
139338fd1498Szrj      size_t
139438fd1498Szrj      operator()(const variant<_Types...>& __t) const
139538fd1498Szrj      noexcept((is_nothrow_invocable_v<hash<decay_t<_Types>>, _Types> && ...))
139638fd1498Szrj      {
139738fd1498Szrj	if (!__t.valueless_by_exception())
139838fd1498Szrj	  {
139938fd1498Szrj	    namespace __edv = __detail::__variant;
140038fd1498Szrj	    static constexpr size_t (*_S_vtable[])(void*) =
140138fd1498Szrj	      { &__edv::__erased_hash<const _Types&>... };
140238fd1498Szrj	    return hash<size_t>{}(__t.index())
140338fd1498Szrj	      + _S_vtable[__t.index()](__edv::__get_storage(__t));
140438fd1498Szrj	  }
140538fd1498Szrj	return hash<size_t>{}(__t.index());
140638fd1498Szrj      }
140738fd1498Szrj    };
140838fd1498Szrj
140938fd1498Szrj  template<typename... _Types>
141038fd1498Szrj    struct __variant_hash_call_base_impl<false, _Types...> {};
141138fd1498Szrj
141238fd1498Szrj  template<typename... _Types>
141338fd1498Szrj    using __variant_hash_call_base =
141438fd1498Szrj    __variant_hash_call_base_impl<(__poison_hash<remove_const_t<_Types>>::
141538fd1498Szrj				   __enable_hash_call &&...), _Types...>;
141638fd1498Szrj
141738fd1498Szrj  template<typename... _Types>
141838fd1498Szrj    struct hash<variant<_Types...>>
141938fd1498Szrj    : private __detail::__variant::_Variant_hash_base<
142038fd1498Szrj	variant<_Types...>, std::index_sequence_for<_Types...>>,
142138fd1498Szrj      public __variant_hash_call_base<_Types...>
142238fd1498Szrj    {
142338fd1498Szrj      using result_type [[__deprecated__]] = size_t;
142438fd1498Szrj      using argument_type [[__deprecated__]] = variant<_Types...>;
142538fd1498Szrj    };
142638fd1498Szrj
142738fd1498Szrj  template<>
142838fd1498Szrj    struct hash<monostate>
142938fd1498Szrj    {
143038fd1498Szrj      using result_type [[__deprecated__]] = size_t;
143138fd1498Szrj      using argument_type [[__deprecated__]] = monostate;
143238fd1498Szrj
143338fd1498Szrj      size_t
143438fd1498Szrj      operator()(const monostate& __t) const noexcept
143538fd1498Szrj      {
143638fd1498Szrj	constexpr size_t __magic_monostate_hash = -7777;
143738fd1498Szrj	return __magic_monostate_hash;
143838fd1498Szrj      }
143938fd1498Szrj    };
144038fd1498Szrj
144138fd1498Szrj  template<typename... _Types>
144238fd1498Szrj    struct __is_fast_hash<hash<variant<_Types...>>>
144338fd1498Szrj    : bool_constant<(__is_fast_hash<_Types>::value && ...)>
144438fd1498Szrj    { };
144538fd1498Szrj
144638fd1498Szrj_GLIBCXX_END_NAMESPACE_VERSION
144738fd1498Szrj} // namespace std
144838fd1498Szrj
144938fd1498Szrj#endif // C++17
145038fd1498Szrj
145138fd1498Szrj#endif // _GLIBCXX_VARIANT
1452