[libc++] Recommit r363692 to implement P0608R3

Re-apply the change which was reverted in r363764 as-is after
breakages being resolved.  Thanks Eric Fiselier for working
hard on this.

See also: https://bugs.llvm.org/show_bug.cgi?id=42330

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

llvm-svn: 363993
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: 4513f0f0224fd34bbebfdc7aa6bb78a995a6ac7b
diff --git a/include/variant b/include/variant
index 5d0722b..baf1630 100644
--- a/include/variant
+++ b/include/variant
@@ -1098,11 +1098,39 @@
 template <class _Tp, class... _Types>
 struct __overload<_Tp, _Types...> : __overload<_Types...> {
   using __overload<_Types...>::operator();
-  __identity<_Tp> operator()(_Tp) const;
+
+  static auto __test(_Tp (&&)[1]) -> __identity<_Tp>;
+
+  template <class _Up>
+  auto operator()(_Tp, _Up&& __t) const
+      -> decltype(__test({ _VSTD::forward<_Up>(__t) }));
 };
 
+template <class _Base, class _Tp>
+struct __overload_bool : _Base {
+  using _Base::operator();
+
+  template <class _Up, class _Ap = __uncvref_t<_Up>>
+  auto operator()(bool, _Up&&) const
+      -> enable_if_t<is_same_v<_Ap, bool>, __identity<_Tp>>;
+};
+
+template <class... _Types>
+struct __overload<bool, _Types...>
+    : __overload_bool<__overload<_Types...>, bool> {};
+template <class... _Types>
+struct __overload<bool const, _Types...>
+    : __overload_bool<__overload<_Types...>, bool const> {};
+template <class... _Types>
+struct __overload<bool volatile, _Types...>
+    : __overload_bool<__overload<_Types...>, bool volatile> {};
+template <class... _Types>
+struct __overload<bool const volatile, _Types...>
+    : __overload_bool<__overload<_Types...>, bool const volatile> {};
+
 template <class _Tp, class... _Types>
-using __best_match_t = typename result_of_t<__overload<_Types...>(_Tp&&)>::type;
+using __best_match_t =
+    typename invoke_result_t<__overload<_Types...>, _Tp, _Tp>::type;
 
 } // __variant_detail