diff libstdc++-v3/include/std/variant @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
line wrap: on
line diff
--- a/libstdc++-v3/include/std/variant	Thu Oct 25 07:37:49 2018 +0900
+++ b/libstdc++-v3/include/std/variant	Thu Feb 13 11:34:05 2020 +0900
@@ -1,6 +1,6 @@
 // <variant> -*- C++ -*-
 
-// Copyright (C) 2016-2018 Free Software Foundation, Inc.
+// Copyright (C) 2016-2020 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
@@ -68,7 +68,7 @@
 } // namespace __variant
 } // namespace __detail
 
-#define __cpp_lib_variant 201603
+#define __cpp_lib_variant 201606L
 
   template<typename... _Types> class tuple;
   template<typename... _Types> class variant;
@@ -138,11 +138,30 @@
     constexpr variant_alternative_t<_Np, variant<_Types...>> const&&
     get(const variant<_Types...>&&);
 
+  template<typename _Result_type, typename _Visitor, typename... _Variants>
+    constexpr decltype(auto)
+    __do_visit(_Visitor&& __visitor, _Variants&&... __variants);
+
+  template <typename... _Types, typename _Tp>
+    decltype(auto)
+    __variant_cast(_Tp&& __rhs)
+    {
+      if constexpr (is_lvalue_reference_v<_Tp>)
+	{
+	  if constexpr (is_const_v<remove_reference_t<_Tp>>)
+	    return static_cast<const variant<_Types...>&>(__rhs);
+	  else
+	    return static_cast<variant<_Types...>&>(__rhs);
+	}
+      else
+        return static_cast<variant<_Types...>&&>(__rhs);
+    }
+
 namespace __detail
 {
 namespace __variant
 {
-  // Returns the first apparence of _Tp in _Types.
+  // Returns the first appearence of _Tp in _Types.
   // Returns sizeof...(_Types) if _Tp is not in _Types.
   template<typename _Tp, typename... _Types>
     struct __index_of : std::integral_constant<size_t, 0> {};
@@ -155,6 +174,31 @@
       std::integral_constant<size_t, is_same_v<_Tp, _First>
 	? 0 : __index_of_v<_Tp, _Rest...> + 1> {};
 
+  // used for raw visitation
+  struct __variant_cookie {};
+  // used for raw visitation with indices passed in
+  struct __variant_idx_cookie { using type = __variant_idx_cookie; };
+  // Used to enable deduction (and same-type checking) for std::visit:
+  template<typename> struct __deduce_visit_result { };
+
+  // Visit variants that might be valueless.
+  template<typename _Visitor, typename... _Variants>
+    constexpr void
+    __raw_visit(_Visitor&& __visitor, _Variants&&... __variants)
+    {
+      std::__do_visit<__variant_cookie>(std::forward<_Visitor>(__visitor),
+				        std::forward<_Variants>(__variants)...);
+    }
+
+  // Visit variants that might be valueless, passing indices to the visitor.
+  template<typename _Visitor, typename... _Variants>
+    constexpr void
+    __raw_idx_visit(_Visitor&& __visitor, _Variants&&... __variants)
+    {
+      std::__do_visit<__variant_idx_cookie>(std::forward<_Visitor>(__visitor),
+	  std::forward<_Variants>(__variants)...);
+    }
+
   // _Uninitialized<T> is guaranteed to be a literal type, even if T is not.
   // We have to do this, because [basic.types]p10.5.3 (n4606) is not implemented
   // yet. When it's implemented, _Uninitialized<T> can be changed to the alias
@@ -170,20 +214,21 @@
     struct _Uninitialized<_Type, true>
     {
       template<typename... _Args>
-      constexpr _Uninitialized(in_place_index_t<0>, _Args&&... __args)
-      : _M_storage(std::forward<_Args>(__args)...)
-      { }
+	constexpr
+	_Uninitialized(in_place_index_t<0>, _Args&&... __args)
+	: _M_storage(std::forward<_Args>(__args)...)
+	{ }
 
-      constexpr const _Type& _M_get() const &
+      constexpr const _Type& _M_get() const & noexcept
       { return _M_storage; }
 
-      constexpr _Type& _M_get() &
+      constexpr _Type& _M_get() & noexcept
       { return _M_storage; }
 
-      constexpr const _Type&& _M_get() const &&
+      constexpr const _Type&& _M_get() const && noexcept
       { return std::move(_M_storage); }
 
-      constexpr _Type&& _M_get() &&
+      constexpr _Type&& _M_get() && noexcept
       { return std::move(_M_storage); }
 
       _Type _M_storage;
@@ -193,36 +238,36 @@
     struct _Uninitialized<_Type, false>
     {
       template<typename... _Args>
-      constexpr _Uninitialized(in_place_index_t<0>, _Args&&... __args)
-      { ::new (&_M_storage) _Type(std::forward<_Args>(__args)...); }
+	constexpr
+	_Uninitialized(in_place_index_t<0>, _Args&&... __args)
+	{
+	  ::new ((void*)std::addressof(_M_storage))
+	    _Type(std::forward<_Args>(__args)...);
+	}
 
-      const _Type& _M_get() const &
+      const _Type& _M_get() const & noexcept
       { return *_M_storage._M_ptr(); }
 
-      _Type& _M_get() &
+      _Type& _M_get() & noexcept
       { return *_M_storage._M_ptr(); }
 
-      const _Type&& _M_get() const &&
+      const _Type&& _M_get() const && noexcept
       { return std::move(*_M_storage._M_ptr()); }
 
-      _Type&& _M_get() &&
+      _Type&& _M_get() && noexcept
       { return std::move(*_M_storage._M_ptr()); }
 
       __gnu_cxx::__aligned_membuf<_Type> _M_storage;
     };
 
-  template<typename _Ref>
-    _Ref __ref_cast(void* __ptr)
-    {
-      return static_cast<_Ref>(*static_cast<remove_reference_t<_Ref>*>(__ptr));
-    }
-
   template<typename _Union>
-    constexpr decltype(auto) __get(in_place_index_t<0>, _Union&& __u)
+    constexpr decltype(auto)
+    __get(in_place_index_t<0>, _Union&& __u) noexcept
     { return std::forward<_Union>(__u)._M_first._M_get(); }
 
   template<size_t _Np, typename _Union>
-    constexpr decltype(auto) __get(in_place_index_t<_Np>, _Union&& __u)
+    constexpr decltype(auto)
+    __get(in_place_index_t<_Np>, _Union&& __u) noexcept
     {
       return __variant::__get(in_place_index<_Np-1>,
 			      std::forward<_Union>(__u)._M_rest);
@@ -230,69 +275,13 @@
 
   // Returns the typed storage for __v.
   template<size_t _Np, typename _Variant>
-    constexpr decltype(auto) __get(_Variant&& __v)
+    constexpr decltype(auto)
+    __get(_Variant&& __v) noexcept
     {
       return __variant::__get(std::in_place_index<_Np>,
 			      std::forward<_Variant>(__v)._M_u);
     }
 
-  // Various functions as "vtable" entries, where those vtables are used by
-  // polymorphic operations.
-  template<typename _Lhs, typename _Rhs>
-    void
-    __erased_ctor(void* __lhs, void* __rhs)
-    {
-      using _Type = remove_reference_t<_Lhs>;
-      ::new (__lhs) _Type(__variant::__ref_cast<_Rhs>(__rhs));
-    }
-
-  template<typename _Variant, size_t _Np>
-    void
-    __erased_dtor(_Variant&& __v)
-    { std::_Destroy(std::__addressof(__variant::__get<_Np>(__v))); }
-
-  template<typename _Lhs, typename _Rhs>
-    void
-    __erased_assign(void* __lhs, void* __rhs)
-    {
-      __variant::__ref_cast<_Lhs>(__lhs) = __variant::__ref_cast<_Rhs>(__rhs);
-    }
-
-  template<typename _Lhs, typename _Rhs>
-    void
-    __erased_swap(void* __lhs, void* __rhs)
-    {
-      using std::swap;
-      swap(__variant::__ref_cast<_Lhs>(__lhs),
-	   __variant::__ref_cast<_Rhs>(__rhs));
-    }
-
-#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \
-  template<typename _Variant, size_t _Np> \
-    constexpr bool \
-    __erased_##__NAME(const _Variant& __lhs, const _Variant& __rhs) \
-    { \
-      return __variant::__get<_Np>(std::forward<_Variant>(__lhs)) \
-	  __OP __variant::__get<_Np>(std::forward<_Variant>(__rhs)); \
-    }
-
-  _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less)
-  _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal)
-  _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
-  _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal)
-  _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal)
-  _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater)
-
-#undef _VARIANT_RELATION_FUNCTION_TEMPLATE
-
-  template<typename _Tp>
-    size_t
-    __erased_hash(void* __t)
-    {
-      return std::hash<__remove_cvref_t<_Tp>>{}(
-	  __variant::__ref_cast<_Tp>(__t));
-    }
-
   template<typename... _Types>
     struct _Traits
     {
@@ -303,7 +292,7 @@
       static constexpr bool _S_move_ctor =
 	  (is_move_constructible_v<_Types> && ...);
       static constexpr bool _S_copy_assign =
-	  _S_copy_ctor && _S_move_ctor
+	  _S_copy_ctor
 	  && (is_copy_assignable_v<_Types> && ...);
       static constexpr bool _S_move_assign =
 	  _S_move_ctor
@@ -316,9 +305,11 @@
       static constexpr bool _S_trivial_move_ctor =
 	  (is_trivially_move_constructible_v<_Types> && ...);
       static constexpr bool _S_trivial_copy_assign =
-	  _S_trivial_dtor && (is_trivially_copy_assignable_v<_Types> && ...);
+	  _S_trivial_dtor && _S_trivial_copy_ctor
+	  && (is_trivially_copy_assignable_v<_Types> && ...);
       static constexpr bool _S_trivial_move_assign =
-	  _S_trivial_dtor && (is_trivially_move_assignable_v<_Types> && ...);
+	  _S_trivial_dtor && _S_trivial_move_ctor
+	  && (is_trivially_move_assignable_v<_Types> && ...);
 
       // The following nothrow traits are for non-trivial SMFs. Trivial SMFs
       // are always nothrow.
@@ -330,7 +321,8 @@
 	  (is_nothrow_move_constructible_v<_Types> && ...);
       static constexpr bool _S_nothrow_copy_assign = false;
       static constexpr bool _S_nothrow_move_assign =
-	  _S_nothrow_move_ctor && (is_nothrow_move_assignable_v<_Types> && ...);
+	  _S_nothrow_move_ctor
+	  && (is_nothrow_move_assignable_v<_Types> && ...);
     };
 
   // Defines members and ctors.
@@ -356,23 +348,46 @@
       _Variadic_union<_Rest...> _M_rest;
     };
 
+  // _Never_valueless_alt is true for variant alternatives that can
+  // always be placed in a variant without it becoming valueless.
+
+  // For suitably-small, trivially copyable types we can create temporaries
+  // on the stack and then memcpy them into place.
+  template<typename _Tp>
+    struct _Never_valueless_alt
+    : __and_<bool_constant<sizeof(_Tp) <= 256>, is_trivially_copyable<_Tp>>
+    { };
+
+  // Specialize _Never_valueless_alt for other types which have a
+  // non-throwing and cheap move construction and move assignment operator,
+  // so that emplacing the type will provide the strong exception-safety
+  // guarantee, by creating and moving a temporary.
+  // Whether _Never_valueless_alt<T> is true or not affects the ABI of a
+  // variant using that alternative, so we can't change the value later!
+
+  // True if every alternative in _Types... can be emplaced in a variant
+  // without it becoming valueless. If this is true, variant<_Types...>
+  // can never be valueless, which enables some minor optimizations.
+  template <typename... _Types>
+    constexpr bool __never_valueless()
+    {
+      return _Traits<_Types...>::_S_move_assign
+	&& (_Never_valueless_alt<_Types>::value && ...);
+    }
+
   // Defines index and the dtor, possibly trivial.
   template<bool __trivially_destructible, typename... _Types>
     struct _Variant_storage;
 
   template <typename... _Types>
-  using __select_index =
-    typename __select_int::_Select_int_base<sizeof...(_Types),
-					    unsigned char,
-					    unsigned short>::type::value_type;
+    using __select_index =
+      typename __select_int::_Select_int_base<sizeof...(_Types),
+					      unsigned char,
+					      unsigned short>::type::value_type;
 
   template<typename... _Types>
     struct _Variant_storage<false, _Types...>
     {
-      template<size_t... __indices>
-	static constexpr void (*_S_vtable[])(const _Variant_storage&) =
-	    { &__erased_dtor<const _Variant_storage&, __indices>... };
-
       constexpr _Variant_storage() : _M_index(variant_npos) { }
 
       template<size_t _Np, typename... _Args>
@@ -381,16 +396,16 @@
 	_M_index(_Np)
 	{ }
 
-      template<size_t... __indices>
-	constexpr void _M_reset_impl(std::index_sequence<__indices...>)
-	{
-	  if (_M_index != __index_type(variant_npos))
-	    _S_vtable<__indices...>[_M_index](*this);
-	}
-
       void _M_reset()
       {
-	_M_reset_impl(std::index_sequence_for<_Types...>{});
+	if (!_M_valid()) [[unlikely]]
+	  return;
+
+	std::__do_visit<void>([](auto&& __this_mem) mutable
+	  {
+	    std::_Destroy(std::__addressof(__this_mem));
+	  }, __variant_cast<_Types...>(*this));
+
 	_M_index = variant_npos;
       }
 
@@ -398,7 +413,7 @@
       { _M_reset(); }
 
       void*
-      _M_storage() const
+      _M_storage() const noexcept
       {
 	return const_cast<void*>(static_cast<const void*>(
 	    std::addressof(_M_u)));
@@ -407,6 +422,8 @@
       constexpr bool
       _M_valid() const noexcept
       {
+	if constexpr (__variant::__never_valueless<_Types...>())
+	  return true;
 	return this->_M_index != __index_type(variant_npos);
       }
 
@@ -426,11 +443,11 @@
 	_M_index(_Np)
 	{ }
 
-      void _M_reset()
+      void _M_reset() noexcept
       { _M_index = variant_npos; }
 
       void*
-      _M_storage() const
+      _M_storage() const noexcept
       {
 	return const_cast<void*>(static_cast<const void*>(
 	    std::addressof(_M_u)));
@@ -439,7 +456,7 @@
       constexpr bool
       _M_valid() const noexcept
       {
-	if constexpr ((is_scalar_v<_Types> && ...))
+	if constexpr (__variant::__never_valueless<_Types...>())
 	  return true;
 	return this->_M_index != __index_type(variant_npos);
       }
@@ -453,6 +470,27 @@
     using _Variant_storage_alias =
 	_Variant_storage<_Traits<_Types...>::_S_trivial_dtor, _Types...>;
 
+  template<typename _Tp, typename _Up>
+    void __variant_construct_single(_Tp&& __lhs, _Up&& __rhs_mem)
+    {
+      void* __storage = std::addressof(__lhs._M_u);
+      using _Type = remove_reference_t<decltype(__rhs_mem)>;
+      if constexpr (!is_same_v<_Type, __variant_cookie>)
+        ::new (__storage)
+	  _Type(std::forward<decltype(__rhs_mem)>(__rhs_mem));
+    }
+
+  template<typename... _Types, typename _Tp, typename _Up>
+    void __variant_construct(_Tp&& __lhs, _Up&& __rhs)
+    {
+      __lhs._M_index = __rhs._M_index;
+      __variant::__raw_visit([&__lhs](auto&& __rhs_mem) mutable
+        {
+	  __variant_construct_single(std::forward<_Tp>(__lhs),
+	      std::forward<decltype(__rhs_mem)>(__rhs_mem));
+	}, __variant_cast<_Types...>(std::forward<_Up>(__rhs)));
+    }
+
   // The following are (Copy|Move) (ctor|assign) layers for forwarding
   // triviality and handling non-trivial SMF behaviors.
 
@@ -465,13 +503,7 @@
       _Copy_ctor_base(const _Copy_ctor_base& __rhs)
 	  noexcept(_Traits<_Types...>::_S_nothrow_copy_ctor)
       {
-	if (__rhs._M_valid())
-	  {
-	    static constexpr void (*_S_vtable[])(void*, void*) =
-	      { &__erased_ctor<_Types&, const _Types&>... };
-	    _S_vtable[__rhs._M_index](this->_M_storage(), __rhs._M_storage());
-	    this->_M_index = __rhs._M_index;
-	  }
+	__variant_construct<_Types...>(*this, __rhs);
       }
 
       _Copy_ctor_base(_Copy_ctor_base&&) = default;
@@ -499,28 +531,24 @@
       _Move_ctor_base(_Move_ctor_base&& __rhs)
 	  noexcept(_Traits<_Types...>::_S_nothrow_move_ctor)
       {
-	if (__rhs._M_valid())
-	  {
-	    static constexpr void (*_S_vtable[])(void*, void*) =
-	      { &__erased_ctor<_Types&, _Types&&>... };
-	    _S_vtable[__rhs._M_index](this->_M_storage(), __rhs._M_storage());
-	    this->_M_index = __rhs._M_index;
-	  }
+	__variant_construct<_Types...>(*this, std::move(__rhs));
       }
 
-      void _M_destructive_move(_Move_ctor_base&& __rhs)
-      {
-	this->~_Move_ctor_base();
-	__try
-	  {
-	    ::new (this) _Move_ctor_base(std::move(__rhs));
-	  }
-	__catch (...)
-	  {
-	    this->_M_index = variant_npos;
-	    __throw_exception_again;
-	  }
-      }
+      template<typename _Up>
+        void _M_destructive_move(unsigned short __rhs_index, _Up&& __rhs)
+        {
+	  this->_M_reset();
+	  __variant_construct_single(*this, std::forward<_Up>(__rhs));
+	  this->_M_index = __rhs_index;
+	}
+
+      template<typename _Up>
+        void _M_destructive_copy(unsigned short __rhs_index, const _Up& __rhs)
+        {
+	  this->_M_reset();
+	  __variant_construct_single(*this, __rhs);
+	  this->_M_index = __rhs_index;
+	}
 
       _Move_ctor_base(const _Move_ctor_base&) = default;
       _Move_ctor_base& operator=(const _Move_ctor_base&) = default;
@@ -533,11 +561,21 @@
       using _Base = _Copy_ctor_alias<_Types...>;
       using _Base::_Base;
 
-      void _M_destructive_move(_Move_ctor_base&& __rhs)
-      {
-	this->~_Move_ctor_base();
-	::new (this) _Move_ctor_base(std::move(__rhs));
-      }
+      template<typename _Up>
+        void _M_destructive_move(unsigned short __rhs_index, _Up&& __rhs)
+        {
+	  this->_M_reset();
+	  __variant_construct_single(*this, std::forward<_Up>(__rhs));
+	  this->_M_index = __rhs_index;
+	}
+
+      template<typename _Up>
+        void _M_destructive_copy(unsigned short __rhs_index, const _Up& __rhs)
+        {
+	  this->_M_reset();
+	  __variant_construct_single(*this, __rhs);
+	  this->_M_index = __rhs_index;
+	}
     };
 
   template<typename... _Types>
@@ -554,22 +592,34 @@
       operator=(const _Copy_assign_base& __rhs)
 	  noexcept(_Traits<_Types...>::_S_nothrow_copy_assign)
       {
-	if (this->_M_index == __rhs._M_index)
+	__variant::__raw_idx_visit(
+	  [this](auto&& __rhs_mem, auto __rhs_index) mutable
 	  {
-	    if (__rhs._M_valid())
+	    if constexpr (__rhs_index != variant_npos)
 	      {
-		static constexpr void (*_S_vtable[])(void*, void*) =
-		  { &__erased_assign<_Types&, const _Types&>... };
-		_S_vtable[__rhs._M_index](this->_M_storage(),
-					  __rhs._M_storage());
+		if (this->_M_index == __rhs_index)
+		  __variant::__get<__rhs_index>(*this) = __rhs_mem;
+		else
+		  {
+		    using __rhs_type = __remove_cvref_t<decltype(__rhs_mem)>;
+		    if constexpr (is_nothrow_copy_constructible_v<__rhs_type>
+			|| !is_nothrow_move_constructible_v<__rhs_type>)
+		      // The standard says this->emplace<__rhs_type>(__rhs_mem)
+		      // should be used here, but _M_destructive_copy is
+		      // equivalent in this case. Either copy construction
+		      // doesn't throw, so _M_destructive_copy gives strong
+		      // exception safety guarantee, or both copy construction
+		      // and move construction can throw, so emplace only gives
+		      // basic exception safety anyway.
+		      this->_M_destructive_copy(__rhs_index, __rhs_mem);
+		    else
+		      __variant_cast<_Types...>(*this)
+			= variant<_Types...>(__rhs_mem);
+		  }
 	      }
-	  }
-	else
-	  {
-	    _Copy_assign_base __tmp(__rhs);
-	    this->_M_destructive_move(std::move(__tmp));
-	  }
-	__glibcxx_assert(this->_M_index == __rhs._M_index);
+	    else
+	      this->_M_reset();
+	  }, __variant_cast<_Types...>(__rhs));
 	return *this;
       }
 
@@ -587,8 +637,7 @@
 
   template<typename... _Types>
     using _Copy_assign_alias =
-	_Copy_assign_base<_Traits<_Types...>::_S_trivial_copy_assign,
-			  _Types...>;
+      _Copy_assign_base<_Traits<_Types...>::_S_trivial_copy_assign, _Types...>;
 
   template<bool, typename... _Types>
     struct _Move_assign_base : _Copy_assign_alias<_Types...>
@@ -600,22 +649,20 @@
       operator=(_Move_assign_base&& __rhs)
 	  noexcept(_Traits<_Types...>::_S_nothrow_move_assign)
       {
-	if (this->_M_index == __rhs._M_index)
+	__variant::__raw_idx_visit(
+	  [this](auto&& __rhs_mem, auto __rhs_index) mutable
 	  {
-	    if (__rhs._M_valid())
+	    if constexpr (__rhs_index != variant_npos)
 	      {
-		static constexpr void (*_S_vtable[])(void*, void*) =
-		  { &__erased_assign<_Types&, _Types&&>... };
-		_S_vtable[__rhs._M_index]
-		  (this->_M_storage(), __rhs._M_storage());
+		if (this->_M_index == __rhs_index)
+		  __variant::__get<__rhs_index>(*this) = std::move(__rhs_mem);
+		else
+		  __variant_cast<_Types...>(*this)
+		    .template emplace<__rhs_index>(std::move(__rhs_mem));
 	      }
-	  }
-	else
-	  {
-	    _Move_assign_base __tmp(std::move(__rhs));
-	    this->_M_destructive_move(std::move(__tmp));
-	  }
-	__glibcxx_assert(this->_M_index == __rhs._M_index);
+	    else
+	      this->_M_reset();
+	  }, __variant_cast<_Types...>(__rhs));
 	return *this;
       }
 
@@ -633,8 +680,7 @@
 
   template<typename... _Types>
     using _Move_assign_alias =
-	_Move_assign_base<_Traits<_Types...>::_S_trivial_move_assign,
-			  _Types...>;
+      _Move_assign_base<_Traits<_Types...>::_S_trivial_move_assign, _Types...>;
 
   template<typename... _Types>
     struct _Variant_base : _Move_assign_alias<_Types...>
@@ -681,67 +727,154 @@
     inline constexpr bool __exactly_once =
       __tuple_count_v<_Tp, tuple<_Types...>> == 1;
 
-  // Takes _Types and create an overloaded _S_fun for each type.
-  // If a type appears more than once in _Types, create only one overload.
-  template<typename... _Types>
-    struct __overload_set
-    { static void _S_fun(); };
+  // Helper used to check for valid conversions that don't involve narrowing.
+  template<typename _Ti> struct _Arr { _Ti _M_x[1]; };
 
-  template<typename _First, typename... _Rest>
-    struct __overload_set<_First, _Rest...> : __overload_set<_Rest...>
+  // Build an imaginary function FUN(Ti) for each alternative type Ti
+  template<size_t _Ind, typename _Tp, typename _Ti,
+	   bool _Ti_is_cv_bool = is_same_v<remove_cv_t<_Ti>, bool>,
+	   typename = void>
+    struct _Build_FUN
     {
-      using __overload_set<_Rest...>::_S_fun;
-      static integral_constant<size_t, sizeof...(_Rest)> _S_fun(_First);
+      // This function means 'using _Build_FUN<I, T, Ti>::_S_fun;' is valid,
+      // but only static functions will be considered in the call below.
+      void _S_fun();
+    };
+
+  // ... for which Ti x[] = {std::forward<T>(t)}; is well-formed,
+  template<size_t _Ind, typename _Tp, typename _Ti>
+    struct _Build_FUN<_Ind, _Tp, _Ti, false,
+		      void_t<decltype(_Arr<_Ti>{{std::declval<_Tp>()}})>>
+    {
+      // This is the FUN function for type _Ti, with index _Ind
+      static integral_constant<size_t, _Ind> _S_fun(_Ti);
     };
 
-  template<typename... _Rest>
-    struct __overload_set<void, _Rest...> : __overload_set<_Rest...>
+  // ... and if Ti is cv bool, remove_cvref_t<T> is bool.
+  template<size_t _Ind, typename _Tp, typename _Ti>
+    struct _Build_FUN<_Ind, _Tp, _Ti, true,
+		      enable_if_t<is_same_v<__remove_cvref_t<_Tp>, bool>>>
     {
-      using __overload_set<_Rest...>::_S_fun;
+      // This is the FUN function for when _Ti is cv bool, with index _Ind
+      static integral_constant<size_t, _Ind> _S_fun(_Ti);
     };
 
-  // Helper for variant(_Tp&&) and variant::operator=(_Tp&&).
-  // __accepted_index maps an arbitrary _Tp to an alternative type in _Variant
-  // (or to variant_npos).
+  template<typename _Tp, typename _Variant,
+	   typename = make_index_sequence<variant_size_v<_Variant>>>
+    struct _Build_FUNs;
+
+  template<typename _Tp, typename... _Ti, size_t... _Ind>
+    struct _Build_FUNs<_Tp, variant<_Ti...>, index_sequence<_Ind...>>
+    : _Build_FUN<_Ind, _Tp, _Ti>...
+    {
+      using _Build_FUN<_Ind, _Tp, _Ti>::_S_fun...;
+    };
+
+  // The index j of the overload FUN(Tj) selected by overload resolution
+  // for FUN(std::forward<_Tp>(t))
+  template<typename _Tp, typename _Variant>
+    using _FUN_type
+      = decltype(_Build_FUNs<_Tp, _Variant>::_S_fun(std::declval<_Tp>()));
+
+  // The index selected for FUN(std::forward<T>(t)), or variant_npos if none.
   template<typename _Tp, typename _Variant, typename = void>
     struct __accepted_index
-    { static constexpr size_t value = variant_npos; };
+    : integral_constant<size_t, variant_npos>
+    { };
 
-  template<typename _Tp, typename... _Types>
-    struct __accepted_index<
-      _Tp, variant<_Types...>,
-      void_t<decltype(__overload_set<_Types...>::_S_fun(std::declval<_Tp>()))>>
-    {
-      static constexpr size_t value = sizeof...(_Types) - 1
-	- decltype(__overload_set<_Types...>::
-		   _S_fun(std::declval<_Tp>()))::value;
-    };
+  template<typename _Tp, typename _Variant>
+    struct __accepted_index<_Tp, _Variant, void_t<_FUN_type<_Tp, _Variant>>>
+    : _FUN_type<_Tp, _Variant>
+    { };
 
   // Returns the raw storage for __v.
   template<typename _Variant>
-    void* __get_storage(_Variant&& __v)
+    void* __get_storage(_Variant&& __v) noexcept
     { return __v._M_storage(); }
 
-  // Used for storing multi-dimensional vtable.
+  template <typename _Maybe_variant_cookie, typename _Variant>
+    struct _Extra_visit_slot_needed
+    {
+      template <typename> struct _Variant_never_valueless;
+
+      template <typename... _Types>
+	struct _Variant_never_valueless<variant<_Types...>>
+	: bool_constant<__variant::__never_valueless<_Types...>()> {};
+
+      static constexpr bool value =
+	(is_same_v<_Maybe_variant_cookie, __variant_cookie>
+	 || is_same_v<_Maybe_variant_cookie, __variant_idx_cookie>)
+	&& !_Variant_never_valueless<__remove_cvref_t<_Variant>>::value;
+    };
+
+  // Used for storing a multi-dimensional vtable.
   template<typename _Tp, size_t... _Dimensions>
-    struct _Multi_array
+    struct _Multi_array;
+
+  // Partial specialization with rank zero, stores a single _Tp element.
+  template<typename _Tp>
+    struct _Multi_array<_Tp>
     {
-      constexpr const _Tp&
+      template<typename>
+	struct __untag_result
+	: false_type
+	{ using element_type = _Tp; };
+
+      template <typename... _Args>
+	struct __untag_result<const void(*)(_Args...)>
+	: false_type
+	{ using element_type = void(*)(_Args...); };
+
+      template <typename... _Args>
+	struct __untag_result<__variant_cookie(*)(_Args...)>
+	: false_type
+	{ using element_type = void(*)(_Args...); };
+
+      template <typename... _Args>
+	struct __untag_result<__variant_idx_cookie(*)(_Args...)>
+	: false_type
+	{ using element_type = void(*)(_Args...); };
+
+      template <typename _Res, typename... _Args>
+	struct __untag_result<__deduce_visit_result<_Res>(*)(_Args...)>
+	: true_type
+	{ using element_type = _Res(*)(_Args...); };
+
+      using __result_is_deduced = __untag_result<_Tp>;
+
+      constexpr const typename __untag_result<_Tp>::element_type&
       _M_access() const
       { return _M_data; }
 
-      _Tp _M_data;
+      typename __untag_result<_Tp>::element_type _M_data;
     };
 
-  template<typename _Tp, size_t __first, size_t... __rest>
-    struct _Multi_array<_Tp, __first, __rest...>
+  // Partial specialization with rank >= 1.
+  template<typename _Ret,
+	   typename _Visitor,
+	   typename... _Variants,
+	   size_t __first, size_t... __rest>
+    struct _Multi_array<_Ret(*)(_Visitor, _Variants...), __first, __rest...>
     {
+      static constexpr size_t __index =
+	sizeof...(_Variants) - sizeof...(__rest) - 1;
+
+      using _Variant = typename _Nth_type<__index, _Variants...>::type;
+
+      static constexpr int __do_cookie =
+	_Extra_visit_slot_needed<_Ret, _Variant>::value ? 1 : 0;
+
+      using _Tp = _Ret(*)(_Visitor, _Variants...);
+
       template<typename... _Args>
-	constexpr const _Tp&
+	constexpr decltype(auto)
 	_M_access(size_t __first_index, _Args... __rest_indices) const
-	{ return _M_arr[__first_index]._M_access(__rest_indices...); }
+        {
+	  return _M_arr[__first_index + __do_cookie]
+	    ._M_access(__rest_indices...);
+	}
 
-      _Multi_array<_Tp, __rest...> _M_arr[__first];
+      _Multi_array<_Tp, __rest...> _M_arr[__first + __do_cookie];
     };
 
   // Creates a multi-dimensional vtable recursively.
@@ -771,14 +904,21 @@
   //                       tuple<V1&&, V2&&>, std::index_sequence<1, 2>>
   // The returned multi-dimensional vtable can be fast accessed by the visitor
   // using index calculation.
-  template<typename _Array_type, typename _Variant_tuple, typename _Index_seq>
+  template<typename _Array_type, typename _Index_seq>
     struct __gen_vtable_impl;
 
+  // Defines the _S_apply() member that returns a _Multi_array populated
+  // with function pointers that perform the visitation expressions e(m)
+  // for each valid pack of indexes into the variant types _Variants.
+  //
+  // This partial specialization builds up the index sequences by recursively
+  // calling _S_apply() on the next specialization of __gen_vtable_impl.
+  // The base case of the recursion defines the actual function pointers.
   template<typename _Result_type, typename _Visitor, size_t... __dimensions,
 	   typename... _Variants, size_t... __indices>
     struct __gen_vtable_impl<
 	_Multi_array<_Result_type (*)(_Visitor, _Variants...), __dimensions...>,
-	tuple<_Variants...>, std::index_sequence<__indices...>>
+	std::index_sequence<__indices...>>
     {
       using _Next =
 	  remove_reference_t<typename _Nth_type<sizeof...(__indices),
@@ -801,35 +941,83 @@
 	_S_apply_all_alts(_Array_type& __vtable,
 			  std::index_sequence<__var_indices...>)
 	{
-	  (_S_apply_single_alt<__var_indices>(
-	     __vtable._M_arr[__var_indices]), ...);
+	  if constexpr (_Extra_visit_slot_needed<_Result_type, _Next>::value)
+	    (_S_apply_single_alt<true, __var_indices>(
+	      __vtable._M_arr[__var_indices + 1],
+	      &(__vtable._M_arr[0])), ...);
+	  else
+	    (_S_apply_single_alt<false, __var_indices>(
+	      __vtable._M_arr[__var_indices]), ...);
 	}
 
-      template<size_t __index, typename _Tp>
+      template<bool __do_cookie, size_t __index, typename _Tp>
 	static constexpr void
-	_S_apply_single_alt(_Tp& __element)
+	_S_apply_single_alt(_Tp& __element, _Tp* __cookie_element = nullptr)
 	{
-	  using _Alternative = variant_alternative_t<__index, _Next>;
-	  __element = __gen_vtable_impl<
-	    remove_reference_t<decltype(__element)>, tuple<_Variants...>,
-	    std::index_sequence<__indices..., __index>>::_S_apply();
+	  if constexpr (__do_cookie)
+	    {
+	      __element = __gen_vtable_impl<
+		_Tp,
+		std::index_sequence<__indices..., __index>>::_S_apply();
+	      *__cookie_element = __gen_vtable_impl<
+		_Tp,
+		std::index_sequence<__indices..., variant_npos>>::_S_apply();
+	    }
+	  else
+	    {
+	      __element = __gen_vtable_impl<
+		remove_reference_t<decltype(__element)>,
+		std::index_sequence<__indices..., __index>>::_S_apply();
+	    }
 	}
     };
 
+  // This partial specialization is the base case for the recursion.
+  // It populates a _Multi_array element with the address of a function
+  // that invokes the visitor with the alternatives specified by __indices.
   template<typename _Result_type, typename _Visitor, typename... _Variants,
 	   size_t... __indices>
     struct __gen_vtable_impl<
       _Multi_array<_Result_type (*)(_Visitor, _Variants...)>,
-		   tuple<_Variants...>, std::index_sequence<__indices...>>
+		   std::index_sequence<__indices...>>
     {
       using _Array_type =
-	  _Multi_array<_Result_type (*)(_Visitor&&, _Variants...)>;
+	  _Multi_array<_Result_type (*)(_Visitor, _Variants...)>;
+
+      template<size_t __index, typename _Variant>
+	static constexpr decltype(auto)
+	__element_by_index_or_cookie(_Variant&& __var) noexcept
+        {
+	  if constexpr (__index != variant_npos)
+	    return __variant::__get<__index>(std::forward<_Variant>(__var));
+	  else
+	    return __variant_cookie{};
+	}
 
       static constexpr decltype(auto)
       __visit_invoke(_Visitor&& __visitor, _Variants... __vars)
       {
-	return std::__invoke(std::forward<_Visitor>(__visitor),
-	    __variant::__get<__indices>(std::forward<_Variants>(__vars))...);
+	if constexpr (is_same_v<_Result_type, __variant_idx_cookie>)
+	  // For raw visitation using indices, pass the indices to the visitor
+	  // and discard the return value:
+	  std::__invoke(std::forward<_Visitor>(__visitor),
+	      __element_by_index_or_cookie<__indices>(
+		std::forward<_Variants>(__vars))...,
+	      integral_constant<size_t, __indices>()...);
+	else if constexpr (is_same_v<_Result_type, __variant_cookie>)
+	  // For raw visitation without indices, and discard the return value:
+	  std::__invoke(std::forward<_Visitor>(__visitor),
+	      __element_by_index_or_cookie<__indices>(
+		std::forward<_Variants>(__vars))...);
+	else if constexpr (_Array_type::__result_is_deduced::value)
+	  // For the usual std::visit case deduce the return value:
+	  return std::__invoke(std::forward<_Visitor>(__visitor),
+	      __element_by_index_or_cookie<__indices>(
+		std::forward<_Variants>(__vars))...);
+	else // for std::visit<R> use INVOKE<R>
+	  return std::__invoke_r<_Result_type>(
+	      std::forward<_Visitor>(__visitor),
+	      __variant::__get<__indices>(std::forward<_Variants>(__vars))...);
       }
 
       static constexpr auto
@@ -840,19 +1028,12 @@
   template<typename _Result_type, typename _Visitor, typename... _Variants>
     struct __gen_vtable
     {
-      using _Func_ptr = _Result_type (*)(_Visitor&&, _Variants...);
       using _Array_type =
-	  _Multi_array<_Func_ptr,
+	  _Multi_array<_Result_type (*)(_Visitor, _Variants...),
 		       variant_size_v<remove_reference_t<_Variants>>...>;
 
-      static constexpr _Array_type
-      _S_apply()
-      {
-	return __gen_vtable_impl<_Array_type, tuple<_Variants...>,
-				 std::index_sequence<>>::_S_apply();
-      }
-
-      static constexpr auto _S_vtable = _S_apply();
+      static constexpr _Array_type _S_vtable
+	= __gen_vtable_impl<_Array_type, std::index_sequence<>>::_S_apply();
     };
 
   template<size_t _Np, typename _Tp>
@@ -869,12 +1050,22 @@
 } // namespace __variant
 } // namespace __detail
 
+  template<size_t _Np, typename _Variant, typename... _Args>
+    void __variant_construct_by_index(_Variant& __v, _Args&&... __args)
+    {
+      __v._M_index = _Np;
+      auto&& __storage = __detail::__variant::__get<_Np>(__v);
+      ::new ((void*)std::addressof(__storage))
+        remove_reference_t<decltype(__storage)>
+	  (std::forward<_Args>(__args)...);
+    }
+
   template<typename _Tp, typename... _Types>
     constexpr bool
     holds_alternative(const variant<_Types...>& __v) noexcept
     {
       static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
-		    "T should occur for exactly once in alternatives");
+		    "T must occur exactly once in alternatives");
       return __v.index() == __detail::__variant::__index_of_v<_Tp, _Types...>;
     }
 
@@ -882,8 +1073,8 @@
     constexpr _Tp& get(variant<_Types...>& __v)
     {
       static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
-		    "T should occur for exactly once in alternatives");
-      static_assert(!is_void_v<_Tp>, "_Tp should not be void");
+		    "T must occur exactly once in alternatives");
+      static_assert(!is_void_v<_Tp>, "_Tp must not be void");
       return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v);
     }
 
@@ -891,8 +1082,8 @@
     constexpr _Tp&& get(variant<_Types...>&& __v)
     {
       static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
-		    "T should occur for exactly once in alternatives");
-      static_assert(!is_void_v<_Tp>, "_Tp should not be void");
+		    "T must occur exactly once in alternatives");
+      static_assert(!is_void_v<_Tp>, "_Tp must not be void");
       return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(
 	std::move(__v));
     }
@@ -901,8 +1092,8 @@
     constexpr const _Tp& get(const variant<_Types...>& __v)
     {
       static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
-		    "T should occur for exactly once in alternatives");
-      static_assert(!is_void_v<_Tp>, "_Tp should not be void");
+		    "T must occur exactly once in alternatives");
+      static_assert(!is_void_v<_Tp>, "_Tp must not be void");
       return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v);
     }
 
@@ -910,8 +1101,8 @@
     constexpr const _Tp&& get(const variant<_Types...>&& __v)
     {
       static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
-		    "T should occur for exactly once in alternatives");
-      static_assert(!is_void_v<_Tp>, "_Tp should not be void");
+		    "T must occur exactly once in alternatives");
+      static_assert(!is_void_v<_Tp>, "_Tp must not be void");
       return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(
 	std::move(__v));
     }
@@ -922,10 +1113,10 @@
     {
       using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>;
       static_assert(_Np < sizeof...(_Types),
-		    "The index should be in [0, number of alternatives)");
-      static_assert(!is_void_v<_Alternative_type>, "_Tp should not be void");
+		    "The index must be in [0, number of alternatives)");
+      static_assert(!is_void_v<_Alternative_type>, "_Tp must not be void");
       if (__ptr && __ptr->index() == _Np)
-	return &__detail::__variant::__get<_Np>(*__ptr);
+	return std::addressof(__detail::__variant::__get<_Np>(*__ptr));
       return nullptr;
     }
 
@@ -936,10 +1127,10 @@
     {
       using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>;
       static_assert(_Np < sizeof...(_Types),
-		    "The index should be in [0, number of alternatives)");
-      static_assert(!is_void_v<_Alternative_type>, "_Tp should not be void");
+		    "The index must be in [0, number of alternatives)");
+      static_assert(!is_void_v<_Alternative_type>, "_Tp must not be void");
       if (__ptr && __ptr->index() == _Np)
-	return &__detail::__variant::__get<_Np>(*__ptr);
+	return std::addressof(__detail::__variant::__get<_Np>(*__ptr));
       return nullptr;
     }
 
@@ -948,20 +1139,19 @@
     get_if(variant<_Types...>* __ptr) noexcept
     {
       static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
-		    "T should occur for exactly once in alternatives");
-      static_assert(!is_void_v<_Tp>, "_Tp should not be void");
+		    "T must occur exactly once in alternatives");
+      static_assert(!is_void_v<_Tp>, "_Tp must not be void");
       return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>(
 	  __ptr);
     }
 
   template<typename _Tp, typename... _Types>
     constexpr add_pointer_t<const _Tp>
-    get_if(const variant<_Types...>* __ptr)
-    noexcept
+    get_if(const variant<_Types...>* __ptr) noexcept
     {
       static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>,
-		    "T should occur for exactly once in alternatives");
-      static_assert(!is_void_v<_Tp>, "_Tp should not be void");
+		    "T must occur exactly once in alternatives");
+      static_assert(!is_void_v<_Tp>, "_Tp must not be void");
       return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>(
 	  __ptr);
     }
@@ -973,7 +1163,24 @@
     constexpr bool operator __OP(const variant<_Types...>& __lhs, \
 				 const variant<_Types...>& __rhs) \
     { \
-      return __lhs._M_##__NAME(__rhs, std::index_sequence_for<_Types...>{}); \
+      bool __ret = true; \
+      __detail::__variant::__raw_idx_visit( \
+        [&__ret, &__lhs] (auto&& __rhs_mem, auto __rhs_index) mutable \
+        { \
+	  if constexpr (__rhs_index != variant_npos) \
+	    { \
+	      if (__lhs.index() == __rhs_index) \
+	        { \
+		  auto& __this_mem = std::get<__rhs_index>(__lhs);	\
+                  __ret = __this_mem __OP __rhs_mem; \
+                } \
+	      else \
+		__ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \
+            } \
+          else \
+            __ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \
+	}, __rhs); \
+      return __ret; \
     } \
 \
   constexpr bool operator __OP(monostate, monostate) noexcept \
@@ -1006,22 +1213,34 @@
   class bad_variant_access : public exception
   {
   public:
-    bad_variant_access() noexcept : _M_reason("Unknown reason") { }
+    bad_variant_access() noexcept { }
+
     const char* what() const noexcept override
     { return _M_reason; }
 
   private:
-    bad_variant_access(const char* __reason) : _M_reason(__reason) { }
+    bad_variant_access(const char* __reason) noexcept : _M_reason(__reason) { }
 
-    const char* _M_reason;
+    // Must point to a string with static storage duration:
+    const char* _M_reason = "bad variant access";
 
     friend void __throw_bad_variant_access(const char* __what);
   };
 
+  // Must only be called with a string literal
   inline void
   __throw_bad_variant_access(const char* __what)
   { _GLIBCXX_THROW_OR_ABORT(bad_variant_access(__what)); }
 
+  inline void
+  __throw_bad_variant_access(bool __valueless)
+  {
+    if (__valueless) [[__unlikely__]]
+      __throw_bad_variant_access("std::get: variant is valueless");
+    else
+      __throw_bad_variant_access("std::get: wrong index for variant");
+  }
+
   template<typename... _Types>
     class variant
     : private __detail::__variant::_Variant_base<_Types...>,
@@ -1036,6 +1255,12 @@
 	variant<_Types...>>
     {
     private:
+      template <typename... _UTypes, typename _Tp>
+	friend decltype(auto) __variant_cast(_Tp&&);
+      template<size_t _Np, typename _Variant, typename... _Args>
+	friend void __variant_construct_by_index(_Variant& __v,
+						 _Args&&... __args);
+
       static_assert(sizeof...(_Types) > 0,
 		    "variant must have at least one alternative");
       static_assert(!(std::is_reference_v<_Types> || ...),
@@ -1050,24 +1275,21 @@
 	    variant<_Types...>>;
 
       template<typename _Tp>
+	static constexpr bool __not_self
+	  = !is_same_v<__remove_cvref_t<_Tp>, variant>;
+
+      template<typename _Tp>
 	static constexpr bool
 	__exactly_once = __detail::__variant::__exactly_once<_Tp, _Types...>;
 
       template<typename _Tp>
-	static constexpr size_t __accepted_index =
-	  __detail::__variant::__accepted_index<_Tp&&, variant>::value;
-
-      template<size_t _Np, bool = _Np < sizeof...(_Types)>
-	struct __to_type_impl;
+	static constexpr size_t __accepted_index
+	  = __detail::__variant::__accepted_index<_Tp, variant>::value;
 
-      template<size_t _Np>
-	struct __to_type_impl<_Np, true>
-	{ using type = variant_alternative_t<_Np, variant>; };
+      template<size_t _Np, typename = enable_if_t<(_Np < sizeof...(_Types))>>
+	using __to_type = variant_alternative_t<_Np, variant>;
 
-      template<size_t _Np>
-	using __to_type = typename __to_type_impl<_Np>::type;
-
-      template<typename _Tp>
+      template<typename _Tp, typename = enable_if_t<__not_self<_Tp>>>
 	using __accepted_type = __to_type<__accepted_index<_Tp>>;
 
       template<typename _Tp>
@@ -1076,6 +1298,17 @@
 
       using _Traits = __detail::__variant::_Traits<_Types...>;
 
+      template<typename _Tp>
+	struct __is_in_place_tag : false_type { };
+      template<typename _Tp>
+	struct __is_in_place_tag<in_place_type_t<_Tp>> : true_type { };
+      template<size_t _Np>
+	struct __is_in_place_tag<in_place_index_t<_Np>> : true_type { };
+
+      template<typename _Tp>
+	static constexpr bool __not_in_place_tag
+	  = !__is_in_place_tag<__remove_cvref_t<_Tp>>::value;
+
     public:
       variant() = default;
       variant(const variant& __rhs) = default;
@@ -1085,71 +1318,80 @@
       ~variant() = default;
 
       template<typename _Tp,
-	       typename = enable_if_t<!is_same_v<decay_t<_Tp>, variant>>,
-	       typename = enable_if_t<(sizeof...(_Types)>0)>,
-	       typename = enable_if_t<__exactly_once<__accepted_type<_Tp&&>>
-			  && is_constructible_v<__accepted_type<_Tp&&>, _Tp&&>>>
+	       typename = enable_if_t<sizeof...(_Types) != 0>,
+	       typename = enable_if_t<__not_in_place_tag<_Tp>>,
+	       typename _Tj = __accepted_type<_Tp&&>,
+	       typename = enable_if_t<__exactly_once<_Tj>
+				      && is_constructible_v<_Tj, _Tp>>>
 	constexpr
 	variant(_Tp&& __t)
-	noexcept(is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp&&>)
-	: variant(in_place_index<__accepted_index<_Tp&&>>,
+	noexcept(is_nothrow_constructible_v<_Tj, _Tp>)
+	: variant(in_place_index<__accepted_index<_Tp>>,
 		  std::forward<_Tp>(__t))
-	{ __glibcxx_assert(holds_alternative<__accepted_type<_Tp&&>>(*this)); }
+	{ }
 
       template<typename _Tp, typename... _Args,
 	       typename = enable_if_t<__exactly_once<_Tp>
-			  && is_constructible_v<_Tp, _Args&&...>>>
+				      && is_constructible_v<_Tp, _Args...>>>
 	constexpr explicit
 	variant(in_place_type_t<_Tp>, _Args&&... __args)
 	: variant(in_place_index<__index_of<_Tp>>,
 		  std::forward<_Args>(__args)...)
-	{ __glibcxx_assert(holds_alternative<_Tp>(*this)); }
+	{ }
 
       template<typename _Tp, typename _Up, typename... _Args,
 	       typename = enable_if_t<__exactly_once<_Tp>
-			  && is_constructible_v<
-			    _Tp, initializer_list<_Up>&, _Args&&...>>>
+				      && is_constructible_v<_Tp,
+					   initializer_list<_Up>&, _Args...>>>
 	constexpr explicit
 	variant(in_place_type_t<_Tp>, initializer_list<_Up> __il,
 		_Args&&... __args)
 	: variant(in_place_index<__index_of<_Tp>>, __il,
 		  std::forward<_Args>(__args)...)
-	{ __glibcxx_assert(holds_alternative<_Tp>(*this)); }
+	{ }
 
       template<size_t _Np, typename... _Args,
-	       typename = enable_if_t<
-		 is_constructible_v<__to_type<_Np>, _Args&&...>>>
+	       typename _Tp = __to_type<_Np>,
+	       typename = enable_if_t<is_constructible_v<_Tp, _Args...>>>
 	constexpr explicit
 	variant(in_place_index_t<_Np>, _Args&&... __args)
 	: _Base(in_place_index<_Np>, std::forward<_Args>(__args)...),
 	_Default_ctor_enabler(_Enable_default_constructor_tag{})
-	{ __glibcxx_assert(index() == _Np); }
+	{ }
 
       template<size_t _Np, typename _Up, typename... _Args,
-	       typename = enable_if_t<is_constructible_v<__to_type<_Np>,
-				      initializer_list<_Up>&, _Args&&...>>>
+	       typename _Tp = __to_type<_Np>,
+	       typename = enable_if_t<is_constructible_v<_Tp,
+							 initializer_list<_Up>&,
+							 _Args...>>>
 	constexpr explicit
 	variant(in_place_index_t<_Np>, initializer_list<_Up> __il,
 		_Args&&... __args)
 	: _Base(in_place_index<_Np>, __il, std::forward<_Args>(__args)...),
 	_Default_ctor_enabler(_Enable_default_constructor_tag{})
-	{ __glibcxx_assert(index() == _Np); }
+	{ }
 
       template<typename _Tp>
 	enable_if_t<__exactly_once<__accepted_type<_Tp&&>>
-		    && is_constructible_v<__accepted_type<_Tp&&>, _Tp&&>
-		    && is_assignable_v<__accepted_type<_Tp&&>&, _Tp&&>
-		    && !is_same_v<decay_t<_Tp>, variant>, variant&>
+		    && is_constructible_v<__accepted_type<_Tp&&>, _Tp>
+		    && is_assignable_v<__accepted_type<_Tp&&>&, _Tp>,
+		    variant&>
 	operator=(_Tp&& __rhs)
-	noexcept(is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp&&>
-		 && is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp&&>)
+	noexcept(is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp>
+		 && is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp>)
 	{
-	  constexpr auto __index = __accepted_index<_Tp&&>;
+	  constexpr auto __index = __accepted_index<_Tp>;
 	  if (index() == __index)
 	    std::get<__index>(*this) = std::forward<_Tp>(__rhs);
 	  else
-	    this->emplace<__index>(std::forward<_Tp>(__rhs));
-	  __glibcxx_assert(holds_alternative<__accepted_type<_Tp&&>>(*this));
+	    {
+	      using _Tj = __accepted_type<_Tp&&>;
+	      if constexpr (is_nothrow_constructible_v<_Tj, _Tp>
+			    || !is_nothrow_move_constructible_v<_Tj>)
+		this->emplace<__index>(std::forward<_Tp>(__rhs));
+	      else
+		operator=(variant(std::forward<_Tp>(__rhs)));
+	    }
 	  return *this;
 	}
 
@@ -1158,10 +1400,8 @@
 		    _Tp&>
 	emplace(_Args&&... __args)
 	{
-	  auto& ret =
-	    this->emplace<__index_of<_Tp>>(std::forward<_Args>(__args)...);
-	  __glibcxx_assert(holds_alternative<_Tp>(*this));
-	  return ret;
+	  constexpr size_t __index = __index_of<_Tp>;
+	  return this->emplace<__index>(std::forward<_Args>(__args)...);
 	}
 
       template<typename _Tp, typename _Up, typename... _Args>
@@ -1170,11 +1410,8 @@
 		    _Tp&>
 	emplace(initializer_list<_Up> __il, _Args&&... __args)
 	{
-	  auto& ret =
-	    this->emplace<__index_of<_Tp>>(__il,
-					   std::forward<_Args>(__args)...);
-	  __glibcxx_assert(holds_alternative<_Tp>(*this));
-	  return ret;
+	  constexpr size_t __index = __index_of<_Tp>;
+	  return this->emplace<__index>(__il, std::forward<_Args>(__args)...);
 	}
 
       template<size_t _Np, typename... _Args>
@@ -1184,19 +1421,49 @@
 	emplace(_Args&&... __args)
 	{
 	  static_assert(_Np < sizeof...(_Types),
-			"The index should be in [0, number of alternatives)");
-	  this->~variant();
-	  __try
+			"The index must be in [0, number of alternatives)");
+	  using type = variant_alternative_t<_Np, variant>;
+	  // Provide the strong exception-safety guarantee when possible,
+	  // to avoid becoming valueless.
+	  if constexpr (is_nothrow_constructible_v<type, _Args...>)
 	    {
-	      ::new (this) variant(in_place_index<_Np>,
-				   std::forward<_Args>(__args)...);
+	      this->_M_reset();
+	      __variant_construct_by_index<_Np>(*this,
+		  std::forward<_Args>(__args)...);
+	    }
+	  else if constexpr (is_scalar_v<type>)
+	    {
+	      // This might invoke a potentially-throwing conversion operator:
+	      const type __tmp(std::forward<_Args>(__args)...);
+	      // But these steps won't throw:
+	      this->_M_reset();
+	      __variant_construct_by_index<_Np>(*this, __tmp);
 	    }
-	  __catch (...)
+	  else if constexpr (__detail::__variant::_Never_valueless_alt<type>()
+	      && _Traits::_S_move_assign)
+	    {
+	      // This construction might throw:
+	      variant __tmp(in_place_index<_Np>,
+			    std::forward<_Args>(__args)...);
+	      // But _Never_valueless_alt<type> means this won't:
+	      *this = std::move(__tmp);
+	    }
+	  else
 	    {
-	      this->_M_index = variant_npos;
-	      __throw_exception_again;
+	      // This case only provides the basic exception-safety guarantee,
+	      // i.e. the variant can become valueless.
+	      this->_M_reset();
+	      __try
+		{
+		  __variant_construct_by_index<_Np>(*this,
+		    std::forward<_Args>(__args)...);
+		}
+	      __catch (...)
+		{
+		  this->_M_index = variant_npos;
+		  __throw_exception_again;
+		}
 	    }
-	  __glibcxx_assert(index() == _Np);
 	  return std::get<_Np>(*this);
 	}
 
@@ -1207,19 +1474,43 @@
 	emplace(initializer_list<_Up> __il, _Args&&... __args)
 	{
 	  static_assert(_Np < sizeof...(_Types),
-			"The index should be in [0, number of alternatives)");
-	  this->~variant();
-	  __try
+			"The index must be in [0, number of alternatives)");
+	  using type = variant_alternative_t<_Np, variant>;
+	  // Provide the strong exception-safety guarantee when possible,
+	  // to avoid becoming valueless.
+	  if constexpr (is_nothrow_constructible_v<type,
+						   initializer_list<_Up>&,
+						   _Args...>)
 	    {
-	      ::new (this) variant(in_place_index<_Np>, __il,
-				   std::forward<_Args>(__args)...);
+	      this->_M_reset();
+	      __variant_construct_by_index<_Np>(*this, __il,
+		  std::forward<_Args>(__args)...);
 	    }
-	  __catch (...)
+	  else if constexpr (__detail::__variant::_Never_valueless_alt<type>()
+	      && _Traits::_S_move_assign)
+	    {
+	      // This construction might throw:
+	      variant __tmp(in_place_index<_Np>, __il,
+			    std::forward<_Args>(__args)...);
+	      // But _Never_valueless_alt<type> means this won't:
+	      *this = std::move(__tmp);
+	    }
+	  else
 	    {
-	      this->_M_index = variant_npos;
-	      __throw_exception_again;
+	      // This case only provides the basic exception-safety guarantee,
+	      // i.e. the variant can become valueless.
+	      this->_M_reset();
+	      __try
+		{
+		  __variant_construct_by_index<_Np>(*this, __il,
+		    std::forward<_Args>(__args)...);
+		}
+	      __catch (...)
+		{
+		  this->_M_index = variant_npos;
+		  __throw_exception_again;
+		}
 	    }
-	  __glibcxx_assert(index() == _Np);
 	  return std::get<_Np>(*this);
 	}
 
@@ -1228,10 +1519,13 @@
 
       constexpr size_t index() const noexcept
       {
-	if (this->_M_index ==
-	    typename _Base::__index_type(variant_npos))
-	  return variant_npos;
-	return this->_M_index;
+	using __index_type = typename _Base::__index_type;
+	if constexpr (__detail::__variant::__never_valueless<_Types...>())
+	  return this->_M_index;
+	else if constexpr (sizeof...(_Types) <= __index_type(-1) / 2)
+	  return make_signed_t<__index_type>(this->_M_index);
+	else
+	  return size_t(__index_type(this->_M_index + 1)) - 1;
       }
 
       void
@@ -1239,62 +1533,47 @@
       noexcept((__is_nothrow_swappable<_Types>::value && ...)
 	       && is_nothrow_move_constructible_v<variant>)
       {
-	if (this->index() == __rhs.index())
-	  {
-	    if (this->_M_valid())
-	      {
-		static constexpr void (*_S_vtable[])(void*, void*) =
-		  { &__detail::__variant::__erased_swap<_Types&, _Types&>... };
-		_S_vtable[__rhs._M_index](this->_M_storage(),
-					  __rhs._M_storage());
-	      }
-	  }
-	else if (!this->_M_valid())
+	__detail::__variant::__raw_idx_visit(
+	  [this, &__rhs](auto&& __rhs_mem, auto __rhs_index) mutable
 	  {
-	    this->_M_destructive_move(std::move(__rhs));
-	    __rhs._M_reset();
-	  }
-	else if (!__rhs._M_valid())
-	  {
-	    __rhs._M_destructive_move(std::move(*this));
-	    this->_M_reset();
-	  }
-	else
-	  {
-	    auto __tmp = std::move(__rhs);
-	    __rhs._M_destructive_move(std::move(*this));
-	    this->_M_destructive_move(std::move(__tmp));
-	  }
+	    if constexpr (__rhs_index != variant_npos)
+	      {
+		if (this->index() == __rhs_index)
+		  {
+		    auto& __this_mem =
+		      std::get<__rhs_index>(*this);
+		    using std::swap;
+		    swap(__this_mem, __rhs_mem);
+		  }
+		else
+		  {
+		    if (!this->valueless_by_exception()) [[__likely__]]
+		      {
+			auto __tmp(std::move(__rhs_mem));
+			__rhs = std::move(*this);
+			this->_M_destructive_move(__rhs_index,
+						  std::move(__tmp));
+		      }
+		    else
+		      {
+			this->_M_destructive_move(__rhs_index,
+						  std::move(__rhs_mem));
+			__rhs._M_reset();
+		      }
+		  }
+	      }
+	    else
+	      {
+		if (!this->valueless_by_exception()) [[__likely__]]
+		  {
+		    __rhs = std::move(*this);
+		    this->_M_reset();
+		  }
+	      }
+	  }, __rhs);
       }
 
     private:
-#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \
-      template<size_t... __indices> \
-	static constexpr bool \
-	(*_S_erased_##__NAME[])(const variant&, const variant&) = \
-	  { &__detail::__variant::__erased_##__NAME< \
-		const variant&, __indices>... }; \
-      template<size_t... __indices> \
-	constexpr bool \
-	_M_##__NAME(const variant& __rhs, \
-		    std::index_sequence<__indices...>) const \
-	{ \
-	  auto __lhs_index = this->index(); \
-	  auto __rhs_index = __rhs.index(); \
-	  if (__lhs_index != __rhs_index || valueless_by_exception()) \
-	    /* Modulo addition. */ \
-	    return __lhs_index + 1 __OP __rhs_index + 1; \
-	  return _S_erased_##__NAME<__indices...>[__lhs_index](*this, __rhs); \
-	}
-
-      _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less)
-      _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal)
-      _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
-      _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal)
-      _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal)
-      _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater)
-
-#undef _VARIANT_RELATION_FUNCTION_TEMPLATE
 
 #if defined(__clang__) && __clang_major__ <= 7
     public:
@@ -1303,10 +1582,12 @@
 #endif
 
       template<size_t _Np, typename _Vp>
-	friend constexpr decltype(auto) __detail::__variant::__get(_Vp&& __v);
+	friend constexpr decltype(auto)
+	__detail::__variant::__get(_Vp&& __v) noexcept;
 
       template<typename _Vp>
-	friend void* __detail::__variant::__get_storage(_Vp&& __v);
+	friend void*
+	__detail::__variant::__get_storage(_Vp&& __v) noexcept;
 
 #define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP) \
       template<typename... _Tp> \
@@ -1329,9 +1610,9 @@
     get(variant<_Types...>& __v)
     {
       static_assert(_Np < sizeof...(_Types),
-		    "The index should be in [0, number of alternatives)");
+		    "The index must be in [0, number of alternatives)");
       if (__v.index() != _Np)
-	__throw_bad_variant_access("Unexpected index");
+	__throw_bad_variant_access(__v.valueless_by_exception());
       return __detail::__variant::__get<_Np>(__v);
     }
 
@@ -1340,9 +1621,9 @@
     get(variant<_Types...>&& __v)
     {
       static_assert(_Np < sizeof...(_Types),
-		    "The index should be in [0, number of alternatives)");
+		    "The index must be in [0, number of alternatives)");
       if (__v.index() != _Np)
-	__throw_bad_variant_access("Unexpected index");
+	__throw_bad_variant_access(__v.valueless_by_exception());
       return __detail::__variant::__get<_Np>(std::move(__v));
     }
 
@@ -1351,9 +1632,9 @@
     get(const variant<_Types...>& __v)
     {
       static_assert(_Np < sizeof...(_Types),
-		    "The index should be in [0, number of alternatives)");
+		    "The index must be in [0, number of alternatives)");
       if (__v.index() != _Np)
-	__throw_bad_variant_access("Unexpected index");
+	__throw_bad_variant_access(__v.valueless_by_exception());
       return __detail::__variant::__get<_Np>(__v);
     }
 
@@ -1362,23 +1643,16 @@
     get(const variant<_Types...>&& __v)
     {
       static_assert(_Np < sizeof...(_Types),
-		    "The index should be in [0, number of alternatives)");
+		    "The index must be in [0, number of alternatives)");
       if (__v.index() != _Np)
-	__throw_bad_variant_access("Unexpected index");
+	__throw_bad_variant_access(__v.valueless_by_exception());
       return __detail::__variant::__get<_Np>(std::move(__v));
     }
 
-  template<typename _Visitor, typename... _Variants>
+  template<typename _Result_type, typename _Visitor, typename... _Variants>
     constexpr decltype(auto)
-    visit(_Visitor&& __visitor, _Variants&&... __variants)
+    __do_visit(_Visitor&& __visitor, _Variants&&... __variants)
     {
-      if ((__variants.valueless_by_exception() || ...))
-	__throw_bad_variant_access("Unexpected index");
-
-      using _Result_type =
-	decltype(std::forward<_Visitor>(__visitor)(
-	    std::get<0>(std::forward<_Variants>(__variants))...));
-
       constexpr auto& __vtable = __detail::__variant::__gen_vtable<
 	_Result_type, _Visitor&&, _Variants&&...>::_S_vtable;
 
@@ -1387,6 +1661,35 @@
 			   std::forward<_Variants>(__variants)...);
     }
 
+  template<typename _Visitor, typename... _Variants>
+    constexpr decltype(auto)
+    visit(_Visitor&& __visitor, _Variants&&... __variants)
+    {
+      if ((__variants.valueless_by_exception() || ...))
+	__throw_bad_variant_access("std::visit: variant is valueless");
+
+      using _Result_type = std::invoke_result_t<_Visitor,
+	decltype(std::get<0>(std::declval<_Variants>()))...>;
+
+      using _Tag = __detail::__variant::__deduce_visit_result<_Result_type>;
+
+      return std::__do_visit<_Tag>(std::forward<_Visitor>(__visitor),
+				   std::forward<_Variants>(__variants)...);
+    }
+
+#if __cplusplus > 201703L
+  template<typename _Res, typename _Visitor, typename... _Variants>
+    constexpr _Res
+    visit(_Visitor&& __visitor, _Variants&&... __variants)
+    {
+      if ((__variants.valueless_by_exception() || ...))
+	__throw_bad_variant_access("std::visit<R>: variant is valueless");
+
+      return std::__do_visit<_Res>(std::forward<_Visitor>(__visitor),
+				   std::forward<_Variants>(__variants)...);
+    }
+#endif
+
   template<bool, typename... _Types>
     struct __variant_hash_call_base_impl
     {
@@ -1394,15 +1697,19 @@
       operator()(const variant<_Types...>& __t) const
       noexcept((is_nothrow_invocable_v<hash<decay_t<_Types>>, _Types> && ...))
       {
-	if (!__t.valueless_by_exception())
+	size_t __ret;
+	__detail::__variant::__raw_visit(
+	  [&__t, &__ret](auto&& __t_mem) mutable
 	  {
-	    namespace __edv = __detail::__variant;
-	    static constexpr size_t (*_S_vtable[])(void*) =
-	      { &__edv::__erased_hash<const _Types&>... };
-	    return hash<size_t>{}(__t.index())
-	      + _S_vtable[__t.index()](__edv::__get_storage(__t));
-	  }
-	return hash<size_t>{}(__t.index());
+	    using _Type = __remove_cvref_t<decltype(__t_mem)>;
+	    if constexpr (!is_same_v<_Type,
+			             __detail::__variant::__variant_cookie>)
+	      __ret = std::hash<size_t>{}(__t.index())
+		      + std::hash<_Type>{}(__t_mem);
+	    else
+	      __ret = std::hash<size_t>{}(__t.index());
+	  }, __t);
+	return __ret;
       }
     };
 
@@ -1431,7 +1738,7 @@
       using argument_type [[__deprecated__]] = monostate;
 
       size_t
-      operator()(const monostate& __t) const noexcept
+      operator()(const monostate&) const noexcept
       {
 	constexpr size_t __magic_monostate_hash = -7777;
 	return __magic_monostate_hash;