[libcxx-commits] [libcxx] [libc++] Specialize allocator_traits for std::allocator (PR #160278)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jan 29 02:52:44 PST 2026


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

>From 56028a850ca60a39786800df09680bbcb5b2e56c Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Tue, 23 Sep 2025 13:17:41 +0200
Subject: [PATCH] [libc++] Specialize allocator_traits for std::allocator

---
 libcxx/include/__memory/allocator_traits.h | 62 +++++++++++++++++++++-
 1 file changed, 61 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/__memory/allocator_traits.h b/libcxx/include/__memory/allocator_traits.h
index b38d7293a3fd3..eebddcfbbfbf5 100644
--- a/libcxx/include/__memory/allocator_traits.h
+++ b/libcxx/include/__memory/allocator_traits.h
@@ -11,6 +11,7 @@
 #define _LIBCPP___MEMORY_ALLOCATOR_TRAITS_H
 
 #include <__config>
+#include <__cstddef/ptrdiff_t.h>
 #include <__cstddef/size_t.h>
 #include <__fwd/memory.h>
 #include <__memory/construct_at.h>
@@ -223,8 +224,13 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(allocation_result);
 
 #endif // _LIBCPP_STD_VER
 
+template <class>
+struct allocator_traits;
+
+// We have a base class that can be specialized for different allocators, since the metaprogramming to get the aliases
+// is quite expensive and the definition of these aliases is usually quite trivial in the end.
 template <class _Alloc>
-struct allocator_traits {
+struct __allocator_traits_base {
   using allocator_type                         = _Alloc;
   using value_type                             = typename allocator_type::value_type;
   using pointer                                = __pointer<value_type, allocator_type>;
@@ -253,6 +259,60 @@ struct allocator_traits {
     using other = allocator_traits<typename rebind_alloc<_Tp>::other>;
   };
 #endif // _LIBCPP_CXX03_LANG
+};
+
+template <class _Tp>
+struct __allocator_traits_base<allocator<_Tp> > {
+  using allocator_type                         = allocator<_Tp>;
+  using value_type                             = _Tp;
+  using pointer                                = _Tp*;
+  using const_pointer                          = const _Tp*;
+  using void_pointer                           = void*;
+  using const_void_pointer                     = const void*;
+  using difference_type                        = ptrdiff_t;
+  using size_type                              = size_t;
+  using propagate_on_container_copy_assignment = false_type;
+  using propagate_on_container_move_assignment = true_type;
+  using propagate_on_container_swap            = false_type;
+  using is_always_equal                        = true_type;
+
+#ifndef _LIBCPP_CXX03_LANG
+  template <class _Up>
+  using rebind_alloc = allocator<_Up>;
+  template <class _Up>
+  using rebind_traits = allocator_traits<allocator<_Up> >;
+#else
+  template <class _Up>
+  struct rebind_alloc {
+    using other = allocator<_Up>;
+  };
+  template <class _Up>
+  struct rebind_traits {
+    using other = allocator_traits<allocator<_Up> >;
+  };
+#endif
+};
+
+template <class _Alloc>
+struct allocator_traits : __allocator_traits_base<_Alloc> {
+  using __base = __allocator_traits_base<_Alloc>;
+
+  using allocator_type                         = typename __base::allocator_type;
+  using value_type                             = typename __base::value_type;
+  using pointer                                = typename __base::pointer;
+  using const_pointer                          = typename __base::const_pointer;
+  using void_pointer                           = typename __base::void_pointer;
+  using const_void_pointer                     = typename __base::const_void_pointer;
+  using difference_type                        = typename __base::difference_type;
+  using size_type                              = typename __base::size_type;
+  using propagate_on_container_copy_assignment = typename __base::propagate_on_container_copy_assignment;
+  using propagate_on_container_move_assignment = typename __base::propagate_on_container_move_assignment;
+  using is_always_equal                        = typename __base::is_always_equal;
+
+  template <class _Tp>
+  using rebind_alloc = typename __base::template rebind_alloc<_Tp>;
+  template <class _Tp>
+  using rebind_traits = typename __base::template rebind_traits<_Tp>;
 
   [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer
   allocate(allocator_type& __a, size_type __n) {



More information about the libcxx-commits mailing list