[libcxx-commits] [libcxx] [libc++] Replace __is_primary_template with a concept (PR #197646)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Thu May 14 07:31:39 PDT 2026


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

>From fa2700c2308724910670d2f0fb16bac764ae49f5 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Thu, 14 May 2026 12:06:16 +0200
Subject: [PATCH] [libc++] Replace __is_primary_template with a concept

---
 libcxx/include/CMakeLists.txt                    |  2 +-
 .../primary_template.h}                          | 16 ++++++++--------
 libcxx/include/__iterator/concepts.h             | 15 +++++++--------
 libcxx/include/__iterator/incrementable_traits.h |  4 ++--
 libcxx/include/__iterator/iterator_traits.h      |  4 ++--
 libcxx/include/__iterator/readable_traits.h      |  2 +-
 libcxx/include/module.modulemap.in               |  5 +----
 7 files changed, 22 insertions(+), 26 deletions(-)
 rename libcxx/include/{__type_traits/is_primary_template.h => __concepts/primary_template.h} (66%)

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 5c2520de90dcc..499a33f304b12 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -323,6 +323,7 @@ set(files
   __concepts/invocable.h
   __concepts/movable.h
   __concepts/predicate.h
+  __concepts/primary_template.h
   __concepts/regular.h
   __concepts/relation.h
   __concepts/same_as.h
@@ -875,7 +876,6 @@ set(files
   __type_traits/is_pod.h
   __type_traits/is_pointer.h
   __type_traits/is_polymorphic.h
-  __type_traits/is_primary_template.h
   __type_traits/is_reference.h
   __type_traits/is_reference_wrapper.h
   __type_traits/is_referenceable.h
diff --git a/libcxx/include/__type_traits/is_primary_template.h b/libcxx/include/__concepts/primary_template.h
similarity index 66%
rename from libcxx/include/__type_traits/is_primary_template.h
rename to libcxx/include/__concepts/primary_template.h
index 5fe6820bc7f7a..2ee30ffc74ffb 100644
--- a/libcxx/include/__type_traits/is_primary_template.h
+++ b/libcxx/include/__concepts/primary_template.h
@@ -10,23 +10,23 @@
 #define _LIBCPP___TYPE_TRAITS_IS_PRIMARY_TEMPLATE_H
 
 #include <__config>
-#include <__type_traits/enable_if.h>
-#include <__type_traits/is_same.h>
-#include <__type_traits/is_valid_expansion.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>
-using __test_for_primary_template _LIBCPP_NODEBUG =
-    __enable_if_t<_IsSame<_Tp, typename _Tp::__primary_template>::value>;
+_LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Tp>
-using __is_primary_template _LIBCPP_NODEBUG = _IsValidExpansion<__test_for_primary_template, _Tp>;
+concept __primary_template = requires {
+  typename _Tp::__primary_template;
+  requires __is_same(typename _Tp::__primary_template, _Tp);
+};
 
 _LIBCPP_END_NAMESPACE_STD
 
+#endif // _LIBCPP_STD_VER >= 20
+
 #endif // _LIBCPP___TYPE_TRAITS_IS_PRIMARY_TEMPLATE_H
diff --git a/libcxx/include/__iterator/concepts.h b/libcxx/include/__iterator/concepts.h
index 3b43920443636..a3f07e8032888 100644
--- a/libcxx/include/__iterator/concepts.h
+++ b/libcxx/include/__iterator/concepts.h
@@ -20,6 +20,7 @@
 #include <__concepts/invocable.h>
 #include <__concepts/movable.h>
 #include <__concepts/predicate.h>
+#include <__concepts/primary_template.h>
 #include <__concepts/regular.h>
 #include <__concepts/relation.h>
 #include <__concepts/same_as.h>
@@ -38,10 +39,8 @@
 #include <__type_traits/integral_constant.h>
 #include <__type_traits/invoke.h>
 #include <__type_traits/is_pointer.h>
-#include <__type_traits/is_primary_template.h>
 #include <__type_traits/is_reference.h>
 #include <__type_traits/is_referenceable.h>
-#include <__type_traits/is_valid_expansion.h>
 #include <__type_traits/remove_cv.h>
 #include <__type_traits/remove_cvref.h>
 #include <__utility/forward.h>
@@ -80,7 +79,7 @@ template <class _Tp>
 concept __specialization_of_projected = requires {
   typename __projected_iterator_t<_Tp>;
   typename __projected_projection_t<_Tp>;
-} && __is_primary_template<_Tp>::value;
+} && __primary_template<_Tp>;
 
 template <class _Tp>
 struct __indirect_value_t_impl {
@@ -153,8 +152,7 @@ concept sized_sentinel_for =
 
 template <class _Iter>
 struct __iter_traits_cache {
-  using type _LIBCPP_NODEBUG =
-      _If<__is_primary_template<iterator_traits<_Iter> >::value, _Iter, iterator_traits<_Iter> >;
+  using type _LIBCPP_NODEBUG = _If<__primary_template<iterator_traits<_Iter> >, _Iter, iterator_traits<_Iter> >;
 };
 template <class _Iter>
 using _ITER_TRAITS _LIBCPP_NODEBUG = typename __iter_traits_cache<_Iter>::type;
@@ -169,12 +167,13 @@ struct __iter_concept_category_test {
 };
 struct __iter_concept_random_fallback {
   template <class _Iter>
-  using _Apply _LIBCPP_NODEBUG =
-      __enable_if_t<__is_primary_template<iterator_traits<_Iter> >::value, random_access_iterator_tag>;
+  using _Apply _LIBCPP_NODEBUG = __enable_if_t<__primary_template<iterator_traits<_Iter> >, random_access_iterator_tag>;
 };
 
 template <class _Iter, class _Tester>
-struct __test_iter_concept : _IsValidExpansion<_Tester::template _Apply, _Iter>, _Tester {};
+    struct __test_iter_concept : bool_constant < requires {
+  typename _Tester::template _Apply<_Iter>;
+} >, _Tester{};
 
 template <class _Iter>
 struct __iter_concept_cache {
diff --git a/libcxx/include/__iterator/incrementable_traits.h b/libcxx/include/__iterator/incrementable_traits.h
index 37c8daddf8a86..dc62b1abb397a 100644
--- a/libcxx/include/__iterator/incrementable_traits.h
+++ b/libcxx/include/__iterator/incrementable_traits.h
@@ -11,11 +11,11 @@
 #define _LIBCPP___ITERATOR_INCREMENTABLE_TRAITS_H
 
 #include <__concepts/arithmetic.h>
+#include <__concepts/primary_template.h>
 #include <__config>
 #include <__cstddef/ptrdiff_t.h>
 #include <__type_traits/conditional.h>
 #include <__type_traits/is_object.h>
-#include <__type_traits/is_primary_template.h>
 #include <__type_traits/make_signed.h>
 #include <__type_traits/remove_cvref.h>
 #include <__utility/declval.h>
@@ -68,7 +68,7 @@ struct iterator_traits;
 // generated from the primary template, and `iterator_traits<RI>::difference_type` otherwise.
 template <class _Ip>
 using iter_difference_t =
-    typename conditional_t<__is_primary_template<iterator_traits<remove_cvref_t<_Ip> > >::value,
+    typename conditional_t<__primary_template<iterator_traits<remove_cvref_t<_Ip> > >,
                            incrementable_traits<remove_cvref_t<_Ip> >,
                            iterator_traits<remove_cvref_t<_Ip> > >::difference_type;
 
diff --git a/libcxx/include/__iterator/iterator_traits.h b/libcxx/include/__iterator/iterator_traits.h
index ebf315a53b6b7..db7228297fc73 100644
--- a/libcxx/include/__iterator/iterator_traits.h
+++ b/libcxx/include/__iterator/iterator_traits.h
@@ -15,6 +15,7 @@
 #include <__concepts/convertible_to.h>
 #include <__concepts/copyable.h>
 #include <__concepts/equality_comparable.h>
+#include <__concepts/primary_template.h>
 #include <__concepts/same_as.h>
 #include <__concepts/totally_ordered.h>
 #include <__config>
@@ -30,7 +31,6 @@
 #include <__type_traits/integral_constant.h>
 #include <__type_traits/is_convertible.h>
 #include <__type_traits/is_object.h>
-#include <__type_traits/is_primary_template.h>
 #include <__type_traits/is_reference.h>
 #include <__type_traits/is_referenceable.h>
 #include <__type_traits/nat.h>
@@ -468,7 +468,7 @@ using __iterator_reference _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::re
 // This has to be in this file and not readable_traits.h to break the include cycle between the two.
 template <class _Ip>
 using iter_value_t =
-    typename conditional_t<__is_primary_template<iterator_traits<remove_cvref_t<_Ip> > >::value,
+    typename conditional_t<__primary_template<iterator_traits<remove_cvref_t<_Ip> > >,
                            indirectly_readable_traits<remove_cvref_t<_Ip> >,
                            iterator_traits<remove_cvref_t<_Ip> > >::value_type;
 
diff --git a/libcxx/include/__iterator/readable_traits.h b/libcxx/include/__iterator/readable_traits.h
index 25e74567fff11..05c24d828937c 100644
--- a/libcxx/include/__iterator/readable_traits.h
+++ b/libcxx/include/__iterator/readable_traits.h
@@ -10,12 +10,12 @@
 #ifndef _LIBCPP___ITERATOR_READABLE_TRAITS_H
 #define _LIBCPP___ITERATOR_READABLE_TRAITS_H
 
+#include <__concepts/primary_template.h>
 #include <__concepts/same_as.h>
 #include <__config>
 #include <__type_traits/conditional.h>
 #include <__type_traits/is_array.h>
 #include <__type_traits/is_object.h>
-#include <__type_traits/is_primary_template.h>
 #include <__type_traits/remove_cv.h>
 #include <__type_traits/remove_cvref.h>
 #include <__type_traits/remove_extent.h>
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index b5aa319d0aca2..02d54d27c64ca 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -255,10 +255,6 @@ module std_core [system] {
       header "__type_traits/is_polymorphic.h"
       export std_core.type_traits.integral_constant
     }
-    module is_primary_template {
-      header "__type_traits/is_primary_template.h"
-      export std_core.type_traits.integral_constant
-    }
     module is_reference_wrapper {
       header "__type_traits/is_reference_wrapper.h"
       export std_core.type_traits.integral_constant
@@ -1089,6 +1085,7 @@ module std [system] {
     module invocable                { header "__concepts/invocable.h" }
     module movable                  { header "__concepts/movable.h" }
     module predicate                { header "__concepts/predicate.h" }
+    module primary_template         { header "__concepts/primary_template.h" }
     module regular                  { header "__concepts/regular.h" }
     module relation                 { header "__concepts/relation.h" }
     module same_as                  { header "__concepts/same_as.h" }



More information about the libcxx-commits mailing list