Skip to content

[libc++] Refactor<__type_traits/is_swappable.h> #86822

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 18, 2024

Conversation

philnik777
Copy link
Contributor

@philnik777 philnik777 commented Mar 27, 2024

This changes the is_swappable implementation to use variable templates first and basing the class templates on that. This avoids instantiating them when the _v versions are used, which are generally less resource intensive.

Copy link

github-actions bot commented Mar 27, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@philnik777 philnik777 force-pushed the refactor_is_swappable branch 5 times, most recently from 05f9348 to e3c0ee6 Compare April 5, 2024 15:02
@philnik777 philnik777 force-pushed the refactor_is_swappable branch from e3c0ee6 to 85a9463 Compare April 14, 2024 07:29
@philnik777 philnik777 force-pushed the refactor_is_swappable branch from 85a9463 to c513031 Compare April 22, 2024 09:59
@philnik777 philnik777 force-pushed the refactor_is_swappable branch from c513031 to 4bfa699 Compare June 1, 2024 09:26
@philnik777 philnik777 marked this pull request as ready for review June 17, 2024 11:15
@philnik777 philnik777 requested a review from a team as a code owner June 17, 2024 11:15
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jun 17, 2024
@llvmbot
Copy link
Member

llvmbot commented Jun 17, 2024

@llvm/pr-subscribers-libcxx

Author: Nikolas Klauser (philnik777)

Changes

Patch is 43.19 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/86822.diff

27 Files Affected:

  • (modified) libcxx/include/__hash_table (+8-9)
  • (modified) libcxx/include/__memory/compressed_pair.h (+2-2)
  • (modified) libcxx/include/__memory/swap_allocator.h (+2-2)
  • (modified) libcxx/include/__memory/unique_ptr.h (+1-1)
  • (modified) libcxx/include/__split_buffer (+2-2)
  • (modified) libcxx/include/__tree (+6-7)
  • (modified) libcxx/include/__type_traits/is_swappable.h (+35-65)
  • (modified) libcxx/include/__utility/pair.h (+5-5)
  • (modified) libcxx/include/__utility/swap.h (+2-2)
  • (modified) libcxx/include/array (+2-3)
  • (modified) libcxx/include/deque (+3-2)
  • (modified) libcxx/include/experimental/propagate_const (+2-3)
  • (modified) libcxx/include/forward_list (+3-3)
  • (modified) libcxx/include/list (+3-4)
  • (modified) libcxx/include/map (+4-4)
  • (modified) libcxx/include/queue (+5-5)
  • (modified) libcxx/include/regex (+1-5)
  • (modified) libcxx/include/set (+2-4)
  • (modified) libcxx/include/stack (+2-2)
  • (modified) libcxx/include/string (+2-2)
  • (modified) libcxx/include/tuple (+11-11)
  • (modified) libcxx/include/unordered_map (+6-6)
  • (modified) libcxx/include/unordered_set (+2-2)
  • (modified) libcxx/include/vector (+4-4)
  • (modified) libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable_include_order.pass.cpp (+13-14)
  • (modified) libcxx/test/support/nasty_containers.h (+12-8)
  • (modified) libcxx/test/support/poisoned_hash_helper.h (+1-1)
diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index a705117d0173f..ec007f28b9523 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -928,13 +928,12 @@ public:
 
   _LIBCPP_HIDE_FROM_ABI void swap(__hash_table& __u)
 #if _LIBCPP_STD_VER <= 11
-      _NOEXCEPT_(__is_nothrow_swappable<hasher>::value&& __is_nothrow_swappable<key_equal>::value &&
+      _NOEXCEPT_(__is_nothrow_swappable_v<hasher>&& __is_nothrow_swappable_v<key_equal> &&
                  (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
-                  __is_nothrow_swappable<__pointer_allocator>::value) &&
-                 (!__node_traits::propagate_on_container_swap::value ||
-                  __is_nothrow_swappable<__node_allocator>::value));
+                  __is_nothrow_swappable_v<__pointer_allocator>) &&
+                 (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>));
 #else
-      _NOEXCEPT_(__is_nothrow_swappable<hasher>::value&& __is_nothrow_swappable<key_equal>::value);
+      _NOEXCEPT_(__is_nothrow_swappable_v<hasher>&& __is_nothrow_swappable_v<key_equal>);
 #endif
 
   _LIBCPP_HIDE_FROM_ABI size_type max_bucket_count() const _NOEXCEPT { return max_size(); }
@@ -1985,12 +1984,12 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(const _Key& __k) c
 template <class _Tp, class _Hash, class _Equal, class _Alloc>
 void __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
 #if _LIBCPP_STD_VER <= 11
-    _NOEXCEPT_(__is_nothrow_swappable<hasher>::value&& __is_nothrow_swappable<key_equal>::value &&
+    _NOEXCEPT_(__is_nothrow_swappable_v<hasher>&& __is_nothrow_swappable_v<key_equal> &&
                (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
-                __is_nothrow_swappable<__pointer_allocator>::value) &&
-               (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable<__node_allocator>::value))
+                __is_nothrow_swappable_v<__pointer_allocator>) &&
+               (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>))
 #else
-    _NOEXCEPT_(__is_nothrow_swappable<hasher>::value&& __is_nothrow_swappable<key_equal>::value)
+    _NOEXCEPT_(__is_nothrow_swappable_v<hasher>&& __is_nothrow_swappable_v<key_equal>)
 #endif
 {
   _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
diff --git a/libcxx/include/__memory/compressed_pair.h b/libcxx/include/__memory/compressed_pair.h
index 328849d7cc12d..40e5cfc35fb04 100644
--- a/libcxx/include/__memory/compressed_pair.h
+++ b/libcxx/include/__memory/compressed_pair.h
@@ -150,7 +150,7 @@ class __compressed_pair : private __compressed_pair_elem<_T1, 0>, private __comp
   }
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void swap(__compressed_pair& __x)
-      _NOEXCEPT_(__is_nothrow_swappable<_T1>::value&& __is_nothrow_swappable<_T2>::value) {
+      _NOEXCEPT_(__is_nothrow_swappable_v<_T1>&& __is_nothrow_swappable_v<_T2>) {
     using std::swap;
     swap(first(), __x.first());
     swap(second(), __x.second());
@@ -160,7 +160,7 @@ class __compressed_pair : private __compressed_pair_elem<_T1, 0>, private __comp
 template <class _T1, class _T2>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
 swap(__compressed_pair<_T1, _T2>& __x, __compressed_pair<_T1, _T2>& __y)
-    _NOEXCEPT_(__is_nothrow_swappable<_T1>::value&& __is_nothrow_swappable<_T2>::value) {
+    _NOEXCEPT_(__is_nothrow_swappable_v<_T1>&& __is_nothrow_swappable_v<_T2>) {
   __x.swap(__y);
 }
 
diff --git a/libcxx/include/__memory/swap_allocator.h b/libcxx/include/__memory/swap_allocator.h
index f2c5090563913..b17e082a43c9f 100644
--- a/libcxx/include/__memory/swap_allocator.h
+++ b/libcxx/include/__memory/swap_allocator.h
@@ -26,7 +26,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __swap_allocator(_Alloc
 #if _LIBCPP_STD_VER >= 14
     _NOEXCEPT
 #else
-    _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value)
+    _NOEXCEPT_(__is_nothrow_swappable_v<_Alloc>)
 #endif
 {
   using std::swap;
@@ -42,7 +42,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __swap_allocator
 #if _LIBCPP_STD_VER >= 14
     _NOEXCEPT
 #else
-    _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value)
+    _NOEXCEPT_(__is_nothrow_swappable_v<_Alloc>)
 #endif
 {
   std::__swap_allocator(
diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h
index 46d9405e31596..3bd02a7cc26aa 100644
--- a/libcxx/include/__memory/unique_ptr.h
+++ b/libcxx/include/__memory/unique_ptr.h
@@ -471,7 +471,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void swap(unique_ptr& __u) _NOEXCEPT { __ptr_.swap(__u.__ptr_); }
 };
 
-template <class _Tp, class _Dp, __enable_if_t<__is_swappable<_Dp>::value, int> = 0>
+template <class _Tp, class _Dp, __enable_if_t<__is_swappable_v<_Dp>, int> = 0>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void
 swap(unique_ptr<_Tp, _Dp>& __x, unique_ptr<_Tp, _Dp>& __y) _NOEXCEPT {
   __x.swap(__y);
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index c68349e0979c9..12e34326c92ce 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -187,7 +187,7 @@ public:
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last, true_type) _NOEXCEPT;
 
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__split_buffer& __x)
-      _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<__alloc_rr>::value);
+      _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__alloc_rr>);
 
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const;
 
@@ -409,7 +409,7 @@ __split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c)
 
 template <class _Tp, class _Allocator>
 _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::swap(__split_buffer& __x)
-    _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<__alloc_rr>::value) {
+    _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__alloc_rr>) {
   std::swap(__first_, __x.__first_);
   std::swap(__begin_, __x.__begin_);
   std::swap(__end_, __x.__end_);
diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index 5a0d8f42a69ce..0b206b5980f77 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -1006,11 +1006,10 @@ public:
 
   _LIBCPP_HIDE_FROM_ABI void swap(__tree& __t)
 #if _LIBCPP_STD_VER <= 11
-      _NOEXCEPT_(__is_nothrow_swappable<value_compare>::value &&
-                 (!__node_traits::propagate_on_container_swap::value ||
-                  __is_nothrow_swappable<__node_allocator>::value));
+      _NOEXCEPT_(__is_nothrow_swappable_v<value_compare> &&
+                 (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>));
 #else
-      _NOEXCEPT_(__is_nothrow_swappable<value_compare>::value);
+      _NOEXCEPT_(__is_nothrow_swappable_v<value_compare>);
 #endif
 
   template <class _Key, class... _Args>
@@ -1549,10 +1548,10 @@ void __tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd) _NOEXCEPT {
 template <class _Tp, class _Compare, class _Allocator>
 void __tree<_Tp, _Compare, _Allocator>::swap(__tree& __t)
 #if _LIBCPP_STD_VER <= 11
-    _NOEXCEPT_(__is_nothrow_swappable<value_compare>::value &&
-               (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable<__node_allocator>::value))
+    _NOEXCEPT_(__is_nothrow_swappable_v<value_compare> &&
+               (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>))
 #else
-    _NOEXCEPT_(__is_nothrow_swappable<value_compare>::value)
+    _NOEXCEPT_(__is_nothrow_swappable_v<value_compare>)
 #endif
 {
   using std::swap;
diff --git a/libcxx/include/__type_traits/is_swappable.h b/libcxx/include/__type_traits/is_swappable.h
index 06b59e5c25d04..0b817e6509933 100644
--- a/libcxx/include/__type_traits/is_swappable.h
+++ b/libcxx/include/__type_traits/is_swappable.h
@@ -11,16 +11,12 @@
 
 #include <__config>
 #include <__type_traits/add_lvalue_reference.h>
-#include <__type_traits/conditional.h>
 #include <__type_traits/enable_if.h>
 #include <__type_traits/is_assignable.h>
 #include <__type_traits/is_constructible.h>
 #include <__type_traits/is_nothrow_assignable.h>
 #include <__type_traits/is_nothrow_constructible.h>
-#include <__type_traits/is_referenceable.h>
-#include <__type_traits/is_same.h>
-#include <__type_traits/is_void.h>
-#include <__type_traits/nat.h>
+#include <__type_traits/void_t.h>
 #include <__utility/declval.h>
 #include <cstddef>
 
@@ -30,10 +26,17 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+template <class _Tp, class _Up, class = void>
+inline const bool __is_swappable_with_v = false;
+
 template <class _Tp>
-struct __is_swappable;
+inline const bool __is_swappable_v = __is_swappable_with_v<_Tp&, _Tp&>;
+
+template <class _Tp, class _Up, bool = __is_swappable_with_v<_Tp, _Up> >
+inline const bool __is_nothrow_swappable_with_v = false;
+
 template <class _Tp>
-struct __is_nothrow_swappable;
+inline const bool __is_nothrow_swappable_v = __is_nothrow_swappable_with_v<_Tp&, _Tp&>;
 
 #ifndef _LIBCPP_CXX03_LANG
 template <class _Tp>
@@ -47,85 +50,52 @@ template <class _Tp>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __swap_result_t<_Tp> swap(_Tp& __x, _Tp& __y)
     _NOEXCEPT_(is_nothrow_move_constructible<_Tp>::value&& is_nothrow_move_assignable<_Tp>::value);
 
-template <class _Tp, size_t _Np, __enable_if_t<__is_swappable<_Tp>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(_Tp (&__a)[_Np], _Tp (&__b)[_Np])
-    _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value);
+template <class _Tp, size_t _Np, __enable_if_t<__is_swappable_v<_Tp>, int> = 0>
+inline _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(_Tp (&__a)[_Np], _Tp (&__b)[_Np]) _NOEXCEPT_(__is_nothrow_swappable_v<_Tp>);
 
-namespace __detail {
 // ALL generic swap overloads MUST already have a declaration available at this point.
 
-template <class _Tp, class _Up = _Tp, bool _NotVoid = !is_void<_Tp>::value && !is_void<_Up>::value>
-struct __swappable_with {
-  template <class _LHS, class _RHS>
-  static decltype(swap(std::declval<_LHS>(), std::declval<_RHS>())) __test_swap(int);
-  template <class, class>
-  static __nat __test_swap(long);
-
-  // Extra parens are needed for the C++03 definition of decltype.
-  typedef decltype((__test_swap<_Tp, _Up>(0))) __swap1;
-  typedef decltype((__test_swap<_Up, _Tp>(0))) __swap2;
-
-  static const bool value = _IsNotSame<__swap1, __nat>::value && _IsNotSame<__swap2, __nat>::value;
-};
+template <class _Tp, class _Up>
+inline const bool __is_swappable_with_v<_Tp,
+                                        _Up,
+                                        __void_t<decltype(swap(std::declval<_Tp>(), std::declval<_Up>())),
+                                                 decltype(swap(std::declval<_Up>(), std::declval<_Tp>()))> > = true;
 
+#ifndef _LIBCPP_CXX03_LANG // C++03 doesn't have noexcept, so things are never nothrow swappable
 template <class _Tp, class _Up>
-struct __swappable_with<_Tp, _Up, false> : false_type {};
-
-template <class _Tp, class _Up = _Tp, bool _Swappable = __swappable_with<_Tp, _Up>::value>
-struct __nothrow_swappable_with {
-  static const bool value =
-#ifndef _LIBCPP_HAS_NO_NOEXCEPT
-      noexcept(swap(std::declval<_Tp>(), std::declval<_Up>()))&& noexcept(
-          swap(std::declval<_Up>(), std::declval<_Tp>()));
-#else
-      false;
+inline const bool __is_nothrow_swappable_with_v<_Tp, _Up, true> =
+    noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())) &&
+    noexcept(swap(std::declval<_Up>(), std::declval<_Tp>()));
 #endif
-};
 
-template <class _Tp, class _Up>
-struct __nothrow_swappable_with<_Tp, _Up, false> : false_type {};
+#if _LIBCPP_STD_VER >= 17
 
-} // namespace __detail
+template <class _Tp, class _Up>
+inline constexpr bool is_swappable_with_v = __is_swappable_with_v<_Tp, _Up>;
 
-template <class _Tp>
-struct __is_swappable : public integral_constant<bool, __detail::__swappable_with<_Tp&>::value> {};
+template <class _Tp, class _Up>
+struct _LIBCPP_TEMPLATE_VIS is_swappable_with : bool_constant<is_swappable_with_v<_Tp, _Up>> {};
 
 template <class _Tp>
-struct __is_nothrow_swappable : public integral_constant<bool, __detail::__nothrow_swappable_with<_Tp&>::value> {};
-
-#if _LIBCPP_STD_VER >= 17
-
-template <class _Tp, class _Up>
-struct _LIBCPP_TEMPLATE_VIS is_swappable_with
-    : public integral_constant<bool, __detail::__swappable_with<_Tp, _Up>::value> {};
+inline constexpr bool is_swappable_v =
+    is_swappable_with_v<__add_lvalue_reference_t<_Tp>, __add_lvalue_reference_t<_Tp>>;
 
 template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS is_swappable
-    : public __conditional_t<__libcpp_is_referenceable<_Tp>::value,
-                             is_swappable_with<__add_lvalue_reference_t<_Tp>, __add_lvalue_reference_t<_Tp> >,
-                             false_type> {};
+struct _LIBCPP_TEMPLATE_VIS is_swappable : bool_constant<is_swappable_v<_Tp>> {};
 
 template <class _Tp, class _Up>
-struct _LIBCPP_TEMPLATE_VIS is_nothrow_swappable_with
-    : public integral_constant<bool, __detail::__nothrow_swappable_with<_Tp, _Up>::value> {};
-
-template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS is_nothrow_swappable
-    : public __conditional_t<__libcpp_is_referenceable<_Tp>::value,
-                             is_nothrow_swappable_with<__add_lvalue_reference_t<_Tp>, __add_lvalue_reference_t<_Tp> >,
-                             false_type> {};
+inline constexpr bool is_nothrow_swappable_with_v = __is_nothrow_swappable_with_v<_Tp, _Up>;
 
 template <class _Tp, class _Up>
-inline constexpr bool is_swappable_with_v = is_swappable_with<_Tp, _Up>::value;
+struct _LIBCPP_TEMPLATE_VIS is_nothrow_swappable_with : bool_constant<is_nothrow_swappable_with_v<_Tp, _Up>> {};
 
 template <class _Tp>
-inline constexpr bool is_swappable_v = is_swappable<_Tp>::value;
-
-template <class _Tp, class _Up>
-inline constexpr bool is_nothrow_swappable_with_v = is_nothrow_swappable_with<_Tp, _Up>::value;
+inline constexpr bool is_nothrow_swappable_v =
+    is_nothrow_swappable_with_v<__add_lvalue_reference_t<_Tp>, __add_lvalue_reference_t<_Tp>>;
 
 template <class _Tp>
-inline constexpr bool is_nothrow_swappable_v = is_nothrow_swappable<_Tp>::value;
+struct _LIBCPP_TEMPLATE_VIS is_nothrow_swappable : bool_constant<is_nothrow_swappable_v<_Tp>> {};
 
 #endif // _LIBCPP_STD_VER >= 17
 
diff --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h
index 3ffab2f7fe4f6..3b6e201852f07 100644
--- a/libcxx/include/__utility/pair.h
+++ b/libcxx/include/__utility/pair.h
@@ -409,7 +409,7 @@ struct _LIBCPP_TEMPLATE_VIS pair
 #endif   // _LIBCPP_CXX03_LANG
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(pair& __p)
-      _NOEXCEPT_(__is_nothrow_swappable<first_type>::value&& __is_nothrow_swappable<second_type>::value) {
+      _NOEXCEPT_(__is_nothrow_swappable_v<first_type>&& __is_nothrow_swappable_v<second_type>) {
     using std::swap;
     swap(first, __p.first);
     swap(second, __p.second);
@@ -417,7 +417,7 @@ struct _LIBCPP_TEMPLATE_VIS pair
 
 #if _LIBCPP_STD_VER >= 23
   _LIBCPP_HIDE_FROM_ABI constexpr void swap(const pair& __p) const
-      noexcept(__is_nothrow_swappable<const first_type>::value && __is_nothrow_swappable<const second_type>::value) {
+      noexcept(__is_nothrow_swappable_v<const first_type> && __is_nothrow_swappable_v<const second_type>) {
     using std::swap;
     swap(first, __p.first);
     swap(second, __p.second);
@@ -513,15 +513,15 @@ struct common_type<pair<_T1, _T2>, pair<_U1, _U2>> {
 };
 #endif // _LIBCPP_STD_VER >= 23
 
-template <class _T1, class _T2, __enable_if_t<__is_swappable<_T1>::value && __is_swappable<_T2>::value, int> = 0>
+template <class _T1, class _T2, __enable_if_t<__is_swappable_v<_T1> && __is_swappable_v<_T2>, int> = 0>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y)
-    _NOEXCEPT_(__is_nothrow_swappable<_T1>::value&& __is_nothrow_swappable<_T2>::value) {
+    _NOEXCEPT_(__is_nothrow_swappable_v<_T1>&& __is_nothrow_swappable_v<_T2>) {
   __x.swap(__y);
 }
 
 #if _LIBCPP_STD_VER >= 23
 template <class _T1, class _T2>
-  requires(__is_swappable<const _T1>::value && __is_swappable<const _T2>::value)
+  requires(__is_swappable_v<const _T1> && __is_swappable_v<const _T2>)
 _LIBCPP_HIDE_FROM_ABI constexpr void
 swap(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) noexcept(noexcept(__x.swap(__y))) {
   __x.swap(__y);
diff --git a/libcxx/include/__utility/swap.h b/libcxx/include/__utility/swap.h
index d678d2cba7dc9..ab88b8e0a0b53 100644
--- a/libcxx/include/__utility/swap.h
+++ b/libcxx/include/__utility/swap.h
@@ -44,9 +44,9 @@ inline _LIBCPP_HIDE_FROM_ABI __swap_result_t<_Tp> _LIBCPP_CONSTEXPR_SINCE_CXX20
   __y = std::move(__t);
 }
 
-template <class _Tp, size_t _Np, __enable_if_t<__is_swappable<_Tp>::value, int> >
+template <class _Tp, size_t _Np, __enable_if_t<__is_swappable_v<_Tp>, int> >
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(_Tp (&__a)[_Np], _Tp (&__b)[_Np])
-    _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value) {
+    _NOEXCEPT_(__is_nothrow_swappable_v<_Tp>) {
   for (size_t __i = 0; __i != _Np; ++__i) {
     swap(__a[__i], __b[__i]);
   }
diff --git a/libcxx/include/array b/libcxx/include/array
index 6ea094deec32d..7d03d4c458219 100644
--- a/libcxx/include/array
+++ b/libcxx/include/array
@@ -192,8 +192,7 @@ struct _LIBCPP_TEMPLATE_VIS array {
     std::fill_n(data(), _Size, __u);
   }
 
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(array& __a)
-      _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value) {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(array& __a) _NOEXCEPT_(__is_nothrow_swappable_v<_Tp>) {
     std::swap_ranges(data(), data() + _Size, __a.data());
   }
 
@@ -428,7 +427,7 @@ operator<=>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) {
 
 #endif // _LIBCPP_STD_VER <= 17
 
-template <class _Tp, size_t _Size, __enable_if_t<_Size == 0 || __is_swappable<_Tp>::value, int> = 0>
+template <class _Tp, size_t _Size, __enable_if_t<_Size == 0 || __is_swappable_v<_Tp>, int> = 0>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(array<_Tp, _Size>& __x, array<_Tp, _Size>& __y)
     _NOEXCEPT_(noexcept(__x.swap(__y))) {
   __x.swap(__y);
diff --git a/libcxx/include/deque b/libcxx/include/deque
index 555761aae6afd..d6173bedbcf5b 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -214,6 +214,7 @@ template <class T, class Allocator, class Predicate>
 #include <__type_traits/is_allocator.h>
 #include <__type_traits/is_convertible.h>
 #include <__type_traits/is_same.h>
+#include <__type_traits/is_swappable.h>
 #include <__type_traits/type_identity.h>
 #include <__utility/forward.h>
 #include <__utility/move.h>
@@ -794,7 +795,7 @@ public:
 #if _LIBCPP_STD_VER >= 14
       _NOEXCEPT;
 #else
-      _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<allocator_type>::value);
+      _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>);
 #endif
   _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT;
 
@@ -2452,7 +2453,7 @@ inline void deque<_Tp, _Allocator>::swap(deque& __c)
 #if _LIBCPP_STD_VER >= 14
     _NOEXCEPT
 #else
-    _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<allocator_type>::value)
+    _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>)
 #endif
 {
   __map_.swap(__c.__map_);
diff --git a/libcxx/include/experimental/propagate_const b/libcxx/include/experimental/propagate_const
index 43648015fe80e..a30bba9effb14 100644
--- a/libcxx/include/experimental/propagate_const
+++ b/libcxx/include/experimental/propagate_const
@@ -266,8 +266,7 @@ public:
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR element_type& operator*() { return *get(); }
 
- ...
[truncated]

Copy link
Member

@ldionne ldionne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code LGTM, but can you expand on the rationale for this change in the PR description? I assume this has to do with reduced compilation times?

Also, do you have a plan to make similar changes in many other type traits?

@philnik777
Copy link
Contributor Author

No, I don't plan to refactor any other traits currently. Most of them have builtins by now, which are used directly in the class and variable versions.

@philnik777 philnik777 merged commit cb41740 into llvm:main Jun 18, 2024
56 checks passed
@philnik777 philnik777 deleted the refactor_is_swappable branch June 18, 2024 09:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants