[libc++] Implement P0655R1 visit<R>: Explicit Return Type for visit

Differential Revision: https://reviews.llvm.org/D92044

GitOrigin-RevId: 51faba35fd81fbd3af407a29c136895a718ccd96
diff --git a/include/variant b/include/variant
index daa3dd2..cb46f09 100644
--- a/include/variant
+++ b/include/variant
@@ -169,6 +169,9 @@
   template <class Visitor, class... Variants>
   constexpr see below visit(Visitor&&, Variants&&...);
 
+  template <class R, class Visitor, class... Variants>
+  constexpr R visit(Visitor&&, Variants&&...); // since C++20
+
   // 20.7.7, class monostate
   struct monostate;
 
@@ -583,6 +586,16 @@
         __make_value_visitor(_VSTD::forward<_Visitor>(__visitor)),
         _VSTD::forward<_Vs>(__vs)...);
   }
+#if _LIBCPP_STD_VER > 17
+  template <class _Rp, class _Visitor, class... _Vs>
+  inline _LIBCPP_INLINE_VISIBILITY
+  static constexpr _Rp __visit_value(_Visitor&& __visitor,
+                                     _Vs&&... __vs) {
+    return __visit_alt(
+        __make_value_visitor<_Rp>(_VSTD::forward<_Visitor>(__visitor)),
+        _VSTD::forward<_Vs>(__vs)...);
+  }
+#endif
 
 private:
   template <class _Visitor, class... _Values>
@@ -605,12 +618,43 @@
     _Visitor&& __visitor;
   };
 
+#if _LIBCPP_STD_VER > 17
+  template <class _Rp, class _Visitor>
+  struct __value_visitor_return_type {
+    template <class... _Alts>
+    inline _LIBCPP_INLINE_VISIBILITY
+    constexpr _Rp operator()(_Alts&&... __alts) const {
+      __std_visit_exhaustive_visitor_check<
+          _Visitor,
+          decltype((_VSTD::forward<_Alts>(__alts).__value))...>();
+      if constexpr (is_void_v<_Rp>) {
+        _VSTD::__invoke_constexpr(_VSTD::forward<_Visitor>(__visitor),
+                                  _VSTD::forward<_Alts>(__alts).__value...);
+      }
+      else {
+        return _VSTD::__invoke_constexpr(_VSTD::forward<_Visitor>(__visitor),
+                                         _VSTD::forward<_Alts>(__alts).__value...);
+      }
+    }
+
+    _Visitor&& __visitor;
+  };
+#endif
+
   template <class _Visitor>
   inline _LIBCPP_INLINE_VISIBILITY
   static constexpr auto __make_value_visitor(_Visitor&& __visitor) {
     return __value_visitor<_Visitor>{_VSTD::forward<_Visitor>(__visitor)};
   }
+
+#if _LIBCPP_STD_VER > 17
+  template <class _Rp, class _Visitor>
+  inline _LIBCPP_INLINE_VISIBILITY
+  static constexpr auto __make_value_visitor(_Visitor&& __visitor) {
+    return __value_visitor_return_type<_Rp, _Visitor>{_VSTD::forward<_Visitor>(__visitor)};
+  }
 };
+#endif
 
 } // namespace __visitation
 
@@ -1594,18 +1638,37 @@
 template <class _Visitor, class... _Vs>
 inline _LIBCPP_INLINE_VISIBILITY
 _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
+constexpr void __throw_if_valueless(_Visitor&& __visitor, _Vs&&... __vs) {
+  const bool __valueless = (... || __vs.valueless_by_exception());
+  if (__valueless) {
+      __throw_bad_variant_access();
+  }
+}
+
+template <class _Visitor, class... _Vs>
+inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
 constexpr decltype(auto) visit(_Visitor&& __visitor, _Vs&&... __vs) {
   using __variant_detail::__visitation::__variant;
-  bool __results[] = {__vs.valueless_by_exception()...};
-  for (bool __result : __results) {
-    if (__result) {
-      __throw_bad_variant_access();
-    }
-  }
+  _VSTD::__throw_if_valueless(_VSTD::forward<_Visitor>(__visitor),
+                              _VSTD::forward<_Vs>(__vs)...);
   return __variant::__visit_value(_VSTD::forward<_Visitor>(__visitor),
                                   _VSTD::forward<_Vs>(__vs)...);
 }
 
+#if _LIBCPP_STD_VER > 17
+template <class _Rp, class _Visitor, class... _Vs>
+inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
+constexpr _Rp visit(_Visitor&& __visitor, _Vs&&... __vs) {
+  using __variant_detail::__visitation::__variant;
+  _VSTD::__throw_if_valueless(_VSTD::forward<_Visitor>(__visitor),
+                              _VSTD::forward<_Vs>(__vs)...);
+  return __variant::__visit_value<_Rp>(_VSTD::forward<_Visitor>(__visitor),
+                                       _VSTD::forward<_Vs>(__vs)...);
+}
+#endif
+
 struct _LIBCPP_TEMPLATE_VIS monostate {};
 
 inline _LIBCPP_INLINE_VISIBILITY