[libcxx-commits] [libcxx] [libc++] Refactor __tuple_like and __pair_like (PR #85206)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Sun Mar 17 12:07:43 PDT 2024


https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/85206

>From 04af17fe0e7002c59f80497cde7ca60a3436bb46 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Thu, 14 Mar 2024 12:10:03 +0100
Subject: [PATCH] [libc++] Refactor __tuple_like and __pair_like

---
 libcxx/include/CMakeLists.txt                 |  2 +-
 .../__memory/uses_allocator_construction.h    | 12 +---
 .../__memory_resource/polymorphic_allocator.h |  1 +
 libcxx/include/__ranges/subrange.h            |  8 +--
 libcxx/include/__tuple/pair_like.h            | 32 ----------
 libcxx/include/__tuple/tuple_like.h           | 33 +++-------
 .../include/__tuple/tuple_like_no_subrange.h  | 60 +++++++++++++++++++
 libcxx/include/__utility/pair.h               | 27 +++------
 libcxx/include/module.modulemap               | 27 ++++-----
 libcxx/include/variant                        |  1 +
 10 files changed, 101 insertions(+), 102 deletions(-)
 delete mode 100644 libcxx/include/__tuple/pair_like.h
 create mode 100644 libcxx/include/__tuple/tuple_like_no_subrange.h

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 63adc03fae2980..6a142ae0f69853 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -703,12 +703,12 @@ set(files
   __tree
   __tuple/find_index.h
   __tuple/make_tuple_types.h
-  __tuple/pair_like.h
   __tuple/sfinae_helpers.h
   __tuple/tuple_element.h
   __tuple/tuple_indices.h
   __tuple/tuple_like.h
   __tuple/tuple_like_ext.h
+  __tuple/tuple_like_no_subrange.h
   __tuple/tuple_size.h
   __tuple/tuple_types.h
   __type_traits/add_const.h
diff --git a/libcxx/include/__memory/uses_allocator_construction.h b/libcxx/include/__memory/uses_allocator_construction.h
index 71ae5bcd323315..9b7262bec5cf8b 100644
--- a/libcxx/include/__memory/uses_allocator_construction.h
+++ b/libcxx/include/__memory/uses_allocator_construction.h
@@ -12,7 +12,7 @@
 #include <__config>
 #include <__memory/construct_at.h>
 #include <__memory/uses_allocator.h>
-#include <__tuple/pair_like.h>
+#include <__tuple/tuple_like_no_subrange.h>
 #include <__type_traits/enable_if.h>
 #include <__type_traits/is_same.h>
 #include <__type_traits/remove_cv.h>
@@ -128,11 +128,7 @@ __uses_allocator_construction_args(const _Alloc& __alloc, const pair<_Up, _Vp>&&
       std::forward_as_tuple(std::get<1>(std::move(__pair))));
 }
 
-template < class _Pair,
-           class _Alloc,
-           __pair_like _PairLike,
-           __enable_if_t<__is_cv_std_pair<_Pair> && !__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value,
-                         int> = 0>
+template <class _Pair, class _Alloc, __pair_like_no_subrange _PairLike, __enable_if_t<__is_cv_std_pair<_Pair>, int> = 0>
 _LIBCPP_HIDE_FROM_ABI constexpr auto
 __uses_allocator_construction_args(const _Alloc& __alloc, _PairLike&& __p) noexcept {
   return std::__uses_allocator_construction_args<_Pair>(
@@ -161,9 +157,7 @@ inline constexpr bool __convertible_to_const_pair_ref =
 #  if _LIBCPP_STD_VER >= 23
 template <class _Tp, class _Up>
 inline constexpr bool __uses_allocator_constraints =
-    __is_cv_std_pair<_Tp> &&
-    (__is_specialization_of_subrange<remove_cvref_t<_Up>>::value ||
-     (!__pair_like<_Up> && !__convertible_to_const_pair_ref<_Up>));
+    __is_cv_std_pair<_Tp> && !__pair_like_no_subrange<_Up> && !__convertible_to_const_pair_ref<_Up>;
 #  else
 template <class _Tp, class _Up>
 inline constexpr bool __uses_allocator_constraints = __is_cv_std_pair<_Tp> && !__convertible_to_const_pair_ref<_Up>;
diff --git a/libcxx/include/__memory_resource/polymorphic_allocator.h b/libcxx/include/__memory_resource/polymorphic_allocator.h
index cfd07bc84fe8aa..823c1503c22b65 100644
--- a/libcxx/include/__memory_resource/polymorphic_allocator.h
+++ b/libcxx/include/__memory_resource/polymorphic_allocator.h
@@ -12,6 +12,7 @@
 #include <__assert>
 #include <__availability>
 #include <__config>
+#include <__fwd/pair.h>
 #include <__memory_resource/memory_resource.h>
 #include <__utility/exception_guard.h>
 #include <cstddef>
diff --git a/libcxx/include/__ranges/subrange.h b/libcxx/include/__ranges/subrange.h
index bb4411cf355497..f356f86ee0b4b5 100644
--- a/libcxx/include/__ranges/subrange.h
+++ b/libcxx/include/__ranges/subrange.h
@@ -28,8 +28,9 @@
 #include <__ranges/enable_borrowed_range.h>
 #include <__ranges/size.h>
 #include <__ranges/view_interface.h>
-#include <__tuple/pair_like.h>
 #include <__tuple/tuple_element.h>
+#include <__tuple/tuple_like.h>
+#include <__tuple/tuple_like_no_subrange.h>
 #include <__tuple/tuple_size.h>
 #include <__type_traits/conditional.h>
 #include <__type_traits/decay.h>
@@ -64,7 +65,7 @@ concept __convertible_to_non_slicing =
 
 template <class _Pair, class _Iter, class _Sent>
 concept __pair_like_convertible_from =
-    !range<_Pair> && __pair_like<_Pair> && constructible_from<_Pair, _Iter, _Sent> &&
+    !range<_Pair> && __pair_like_no_subrange<_Pair> && constructible_from<_Pair, _Iter, _Sent> &&
     __convertible_to_non_slicing<_Iter, tuple_element_t<0, _Pair>> && convertible_to<_Sent, tuple_element_t<1, _Pair>>;
 
 template <input_or_output_iterator _Iter,
@@ -125,8 +126,7 @@ class _LIBCPP_TEMPLATE_VIS subrange : public view_interface<subrange<_Iter, _Sen
                requires(_Kind == subrange_kind::sized)
       : subrange(ranges::begin(__range), ranges::end(__range), __n) {}
 
-  template <__different_from<subrange> _Pair>
-    requires __pair_like_convertible_from<_Pair, const _Iter&, const _Sent&>
+  template <__pair_like_convertible_from<const _Iter&, const _Sent&> _Pair>
   _LIBCPP_HIDE_FROM_ABI constexpr operator _Pair() const {
     return _Pair(__begin_, __end_);
   }
diff --git a/libcxx/include/__tuple/pair_like.h b/libcxx/include/__tuple/pair_like.h
deleted file mode 100644
index 192682dc7eb598..00000000000000
--- a/libcxx/include/__tuple/pair_like.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _LIBCPP___TUPLE_PAIR_LIKE_H
-#define _LIBCPP___TUPLE_PAIR_LIKE_H
-
-#include <__config>
-#include <__tuple/tuple_like.h>
-#include <__tuple/tuple_size.h>
-#include <__type_traits/remove_cvref.h>
-
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-#  pragma GCC system_header
-#endif
-
-_LIBCPP_BEGIN_NAMESPACE_STD
-
-#if _LIBCPP_STD_VER >= 20
-
-template <class _Tp>
-concept __pair_like = __tuple_like<_Tp> && tuple_size<remove_cvref_t<_Tp>>::value == 2;
-
-#endif // _LIBCPP_STD_VER >= 20
-
-_LIBCPP_END_NAMESPACE_STD
-
-#endif // _LIBCPP___TUPLE_PAIR_LIKE_H
diff --git a/libcxx/include/__tuple/tuple_like.h b/libcxx/include/__tuple/tuple_like.h
index 967e4a543c0318..cc5c0ce4ba4d20 100644
--- a/libcxx/include/__tuple/tuple_like.h
+++ b/libcxx/include/__tuple/tuple_like.h
@@ -10,12 +10,9 @@
 #define _LIBCPP___TUPLE_TUPLE_LIKE_H
 
 #include <__config>
-#include <__fwd/array.h>
-#include <__fwd/complex.h>
-#include <__fwd/pair.h>
 #include <__fwd/subrange.h>
-#include <__fwd/tuple.h>
-#include <__type_traits/integral_constant.h>
+#include <__tuple/tuple_like_no_subrange.h>
+#include <__tuple/tuple_size.h>
 #include <__type_traits/remove_cvref.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -26,30 +23,18 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 20
 
+#  if _LIBCPP_STD_VER >= 23
 template <class _Tp>
-struct __tuple_like_impl : false_type {};
-
-template <class... _Tp>
-struct __tuple_like_impl<tuple<_Tp...> > : true_type {};
-
-template <class _T1, class _T2>
-struct __tuple_like_impl<pair<_T1, _T2> > : true_type {};
-
-template <class _Tp, size_t _Size>
-struct __tuple_like_impl<array<_Tp, _Size> > : true_type {};
-
-template <class _Ip, class _Sp, ranges::subrange_kind _Kp>
-struct __tuple_like_impl<ranges::subrange<_Ip, _Sp, _Kp> > : true_type {};
-
-#  if _LIBCPP_STD_VER >= 26
-
-template <class _Tp>
-struct __tuple_like_impl<complex<_Tp>> : true_type {};
+inline constexpr bool __is_ranges_subrange_v = false;
 
+template <class _Iter, class _Sent, ranges::subrange_kind _Kind>
+inline constexpr bool __is_ranges_subrange_v<ranges::subrange<_Iter, _Sent, _Kind>> = true;
 #  endif
 
 template <class _Tp>
-concept __tuple_like = __tuple_like_impl<remove_cvref_t<_Tp>>::value;
+concept __tuple_like = __tuple_like_no_subrange<_Tp> || __is_ranges_subrange_v<remove_cvref_t<_Tp>>;
+
+// If the exposition-only type trait `pair-like` is required, you most likely want __pair_like_no_subrange.
 
 #endif // _LIBCPP_STD_VER >= 20
 
diff --git a/libcxx/include/__tuple/tuple_like_no_subrange.h b/libcxx/include/__tuple/tuple_like_no_subrange.h
new file mode 100644
index 00000000000000..d0f97f3a107705
--- /dev/null
+++ b/libcxx/include/__tuple/tuple_like_no_subrange.h
@@ -0,0 +1,60 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___TUPLE_TUPLE_LIKE_NO_SUBRANGE_H
+#define _LIBCPP___TUPLE_TUPLE_LIKE_NO_SUBRANGE_H
+
+#include <__config>
+#include <__fwd/array.h>
+#include <__fwd/complex.h>
+#include <__fwd/pair.h>
+#include <__fwd/tuple.h>
+#include <__tuple/tuple_size.h>
+#include <__type_traits/remove_cvref.h>
+#include <cstddef>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 20
+
+template <class _Tp>
+inline constexpr bool __tuple_like_no_subrange_impl = false;
+
+template <class... _Tp>
+inline constexpr bool __tuple_like_no_subrange_impl<tuple<_Tp...>> = true;
+
+template <class _T1, class _T2>
+inline constexpr bool __tuple_like_no_subrange_impl<pair<_T1, _T2>> = true;
+
+template <class _Tp, size_t _Size>
+inline constexpr bool __tuple_like_no_subrange_impl<array<_Tp, _Size>> = true;
+
+#  if _LIBCPP_STD_VER >= 26
+
+template <class _Tp>
+inline constexpr bool __tuple_like_no_subrange_impl<complex<_Tp>> = true;
+
+#  endif
+
+template <class _Tp>
+concept __tuple_like_no_subrange = __tuple_like_no_subrange_impl<remove_cvref_t<_Tp>>;
+
+// This is equivalent to the exposition-only type trait `pair-like`, except that it is false for specializations of
+// `ranges::subrange`. This is removed, because every use of `pair-like` excludes `ranges::subrange`.
+template <class _Tp>
+concept __pair_like_no_subrange = __tuple_like_no_subrange<_Tp> && tuple_size<remove_cvref_t<_Tp>>::value == 2;
+
+#endif // _LIBCPP_STD_VER >= 20
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___TUPLE_TUPLE_LIKE_NO_SUBRANGE_H
diff --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h
index b488a9829c3849..71b3f177460357 100644
--- a/libcxx/include/__utility/pair.h
+++ b/libcxx/include/__utility/pair.h
@@ -15,12 +15,11 @@
 #include <__config>
 #include <__fwd/array.h>
 #include <__fwd/pair.h>
-#include <__fwd/subrange.h>
 #include <__fwd/tuple.h>
-#include <__tuple/pair_like.h>
 #include <__tuple/sfinae_helpers.h>
 #include <__tuple/tuple_element.h>
 #include <__tuple/tuple_indices.h>
+#include <__tuple/tuple_like_no_subrange.h>
 #include <__tuple/tuple_size.h>
 #include <__type_traits/common_reference.h>
 #include <__type_traits/common_type.h>
@@ -67,14 +66,6 @@ struct __non_trivially_copyable_base {
   __non_trivially_copyable_base(__non_trivially_copyable_base const&) _NOEXCEPT {}
 };
 
-#if _LIBCPP_STD_VER >= 23
-template <class _Tp>
-struct __is_specialization_of_subrange : false_type {};
-
-template <class _Iter, class _Sent, ranges::subrange_kind _Kind>
-struct __is_specialization_of_subrange<ranges::subrange<_Iter, _Sent, _Kind>> : true_type {};
-#endif
-
 template <class _T1, class _T2>
 struct _LIBCPP_TEMPLATE_VIS pair
 #if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR)
@@ -208,19 +199,19 @@ struct _LIBCPP_TEMPLATE_VIS pair
 #  endif
 
 #  if _LIBCPP_STD_VER >= 23
+  // TODO: Remove this workaround in LLVM 20. The bug got fixed in Clang 18.
   // This is a workaround for http://llvm.org/PR60710. We should be able to remove it once Clang is fixed.
   template <class _PairLike>
   _LIBCPP_HIDE_FROM_ABI static constexpr bool __pair_like_explicit_wknd() {
-    if constexpr (__pair_like<_PairLike>) {
+    if constexpr (__pair_like_no_subrange<_PairLike>) {
       return !is_convertible_v<decltype(std::get<0>(std::declval<_PairLike&&>())), first_type> ||
              !is_convertible_v<decltype(std::get<1>(std::declval<_PairLike&&>())), second_type>;
     }
     return false;
   }
 
-  template <__pair_like _PairLike>
-    requires(!__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value &&
-             is_constructible_v<first_type, decltype(std::get<0>(std::declval<_PairLike &&>()))> &&
+  template <__pair_like_no_subrange _PairLike>
+    requires(is_constructible_v<first_type, decltype(std::get<0>(std::declval<_PairLike &&>()))> &&
              is_constructible_v<second_type, decltype(std::get<1>(std::declval<_PairLike &&>()))>)
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(__pair_like_explicit_wknd<_PairLike>()) pair(_PairLike&& __p)
       : first(std::get<0>(std::forward<_PairLike>(__p))), second(std::get<1>(std::forward<_PairLike>(__p))) {}
@@ -313,8 +304,8 @@ struct _LIBCPP_TEMPLATE_VIS pair
     return *this;
   }
 
-  template <__pair_like _PairLike>
-    requires(__different_from<_PairLike, pair> && !__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value &&
+  template <__pair_like_no_subrange _PairLike>
+    requires(__different_from<_PairLike, pair> &&
              is_assignable_v<first_type&, decltype(std::get<0>(std::declval<_PairLike>()))> &&
              is_assignable_v<second_type&, decltype(std::get<1>(std::declval<_PairLike>()))>)
   _LIBCPP_HIDE_FROM_ABI constexpr pair& operator=(_PairLike&& __p) {
@@ -323,8 +314,8 @@ struct _LIBCPP_TEMPLATE_VIS pair
     return *this;
   }
 
-  template <__pair_like _PairLike>
-    requires(__different_from<_PairLike, pair> && !__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value &&
+  template <__pair_like_no_subrange _PairLike>
+    requires(__different_from<_PairLike, pair> &&
              is_assignable_v<first_type const&, decltype(std::get<0>(std::declval<_PairLike>()))> &&
              is_assignable_v<second_type const&, decltype(std::get<1>(std::declval<_PairLike>()))>)
   _LIBCPP_HIDE_FROM_ABI constexpr pair const& operator=(_PairLike&& __p) const {
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 0bd2831b7f159c..431d3876723061 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -1799,20 +1799,19 @@ module std_private_thread_thread               [system] {
 }
 module std_private_thread_timed_backoff_policy [system] { header "__thread/timed_backoff_policy.h" }
 
-module std_private_tuple_find_index       [system] { header "__tuple/find_index.h" }
-module std_private_tuple_make_tuple_types [system] { header "__tuple/make_tuple_types.h" }
-module std_private_tuple_pair_like        [system] {
-  header "__tuple/pair_like.h"
-  export std_private_tuple_tuple_like
-}
-module std_private_tuple_sfinae_helpers   [system] { header "__tuple/sfinae_helpers.h" }
-module std_private_tuple_tuple_element    [system] { header "__tuple/tuple_element.h" }
-module std_private_tuple_tuple_fwd        [system] { header "__fwd/tuple.h" }
-module std_private_tuple_tuple_indices    [system] { header "__tuple/tuple_indices.h" }
-module std_private_tuple_tuple_like       [system] { header "__tuple/tuple_like.h" }
-module std_private_tuple_tuple_like_ext   [system] { header "__tuple/tuple_like_ext.h" }
-module std_private_tuple_tuple_size       [system] { header "__tuple/tuple_size.h" }
-module std_private_tuple_tuple_types      [system] { header "__tuple/tuple_types.h" }
+module std_private_tuple_find_index             [system] { header "__tuple/find_index.h" }
+module std_private_tuple_make_tuple_types       [system] { header "__tuple/make_tuple_types.h" }
+module std_private_tuple_tuple_like_no_subrange [system] {
+  header "__tuple/tuple_like_no_subrange.h"
+}
+module std_private_tuple_sfinae_helpers         [system] { header "__tuple/sfinae_helpers.h" }
+module std_private_tuple_tuple_element          [system] { header "__tuple/tuple_element.h" }
+module std_private_tuple_tuple_fwd              [system] { header "__fwd/tuple.h" }
+module std_private_tuple_tuple_indices          [system] { header "__tuple/tuple_indices.h" }
+module std_private_tuple_tuple_like             [system] { header "__tuple/tuple_like.h" }
+module std_private_tuple_tuple_like_ext         [system] { header "__tuple/tuple_like_ext.h" }
+module std_private_tuple_tuple_size             [system] { header "__tuple/tuple_size.h" }
+module std_private_tuple_tuple_types            [system] { header "__tuple/tuple_types.h" }
 
 module std_private_type_traits_add_const                                 [system] { header "__type_traits/add_const.h" }
 module std_private_type_traits_add_cv                                    [system] { header "__type_traits/add_cv.h" }
diff --git a/libcxx/include/variant b/libcxx/include/variant
index 25d47ec79defa7..5db66c1aa63208 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -242,6 +242,7 @@ namespace std {
 #include <__type_traits/is_trivially_move_constructible.h>
 #include <__type_traits/is_void.h>
 #include <__type_traits/remove_const.h>
+#include <__type_traits/remove_cvref.h>
 #include <__type_traits/type_identity.h>
 #include <__type_traits/void_t.h>
 #include <__utility/declval.h>



More information about the libcxx-commits mailing list