[libcxx-commits] [libcxx] [libc++] Move allocator assertion into allocator_traits (PR #94750)

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jun 17 11:33:11 PDT 2024


https://github.com/huixie90 updated https://github.com/llvm/llvm-project/pull/94750

>From 9503536d565903c27c6f5417cb54a8d4ad19a9ab Mon Sep 17 00:00:00 2001
From: Hui <hui.xie0621 at gmail.com>
Date: Fri, 7 Jun 2024 20:02:07 +0100
Subject: [PATCH] [libc++] reuse allocator validitity check logic and message

---
 libcxx/include/__memory/allocator_traits.h | 9 +++++++++
 libcxx/include/deque                       | 9 +++------
 libcxx/include/forward_list                | 6 ++----
 libcxx/include/list                        | 5 +----
 libcxx/include/map                         | 9 ++-------
 libcxx/include/set                         | 8 ++------
 libcxx/include/string                      | 5 +----
 libcxx/include/unordered_map               | 9 ++-------
 libcxx/include/unordered_set               | 5 +----
 libcxx/include/vector                      | 5 +----
 10 files changed, 24 insertions(+), 46 deletions(-)

diff --git a/libcxx/include/__memory/allocator_traits.h b/libcxx/include/__memory/allocator_traits.h
index 47fe132d15cb1..ac564f0e6fa0c 100644
--- a/libcxx/include/__memory/allocator_traits.h
+++ b/libcxx/include/__memory/allocator_traits.h
@@ -16,6 +16,7 @@
 #include <__type_traits/enable_if.h>
 #include <__type_traits/is_constructible.h>
 #include <__type_traits/is_empty.h>
+#include <__type_traits/is_same.h>
 #include <__type_traits/make_unsigned.h>
 #include <__type_traits/remove_reference.h>
 #include <__type_traits/void_t.h>
@@ -372,6 +373,14 @@ template <class _Traits, class _Tp>
 using __rebind_alloc = typename _Traits::template rebind_alloc<_Tp>::other;
 #endif
 
+template <class _Alloc>
+struct __check_valid_allocator : true_type {
+  using _Traits = std::allocator_traits<_Alloc>;
+  static_assert(is_same<_Alloc, __rebind_alloc<_Traits, typename _Traits::value_type> >::value,
+                "[allocator.requirements] states that rebinding an allocator to the same type should result in the "
+                "original allocator");
+};
+
 // __is_default_allocator
 template <class _Tp>
 struct __is_default_allocator : false_type {};
diff --git a/libcxx/include/deque b/libcxx/include/deque
index 051bb6551212e..005fc516f88bf 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -448,11 +448,11 @@ public:
 
   using value_type = _Tp;
 
-  static_assert((is_same<typename _Allocator::value_type, value_type>::value),
-                "Allocator::value_type must be same type as value_type");
-
   using allocator_type = _Allocator;
   using __alloc_traits = allocator_traits<allocator_type>;
+  static_assert(__check_valid_allocator<allocator_type>::value, "");
+  static_assert((is_same<typename allocator_type::value_type, value_type>::value),
+                "Allocator::value_type must be same type as value_type");
 
   using size_type       = typename __alloc_traits::size_type;
   using difference_type = typename __alloc_traits::difference_type;
@@ -487,9 +487,6 @@ public:
       deque,
       void>;
 
-  static_assert(is_same<allocator_type, __rebind_alloc<__alloc_traits, value_type> >::value,
-                "[allocator.requirements] states that rebinding an allocator to the same type should result in the "
-                "original allocator");
   static_assert(is_nothrow_default_constructible<allocator_type>::value ==
                     is_nothrow_default_constructible<__pointer_allocator>::value,
                 "rebinding an allocator should not change exception guarantees");
diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list
index 363931e3f2388..8806cf3d00ffa 100644
--- a/libcxx/include/forward_list
+++ b/libcxx/include/forward_list
@@ -650,13 +650,11 @@ public:
   typedef _Tp value_type;
   typedef _Alloc allocator_type;
 
+  static_assert(__check_valid_allocator<allocator_type>::value, "");
+
   static_assert(is_same<value_type, typename allocator_type::value_type>::value,
                 "Allocator::value_type must be same type as value_type");
 
-  static_assert(is_same<allocator_type, __rebind_alloc<allocator_traits<allocator_type>, value_type> >::value,
-                "[allocator.requirements] states that rebinding an allocator to the same type should result in the "
-                "original allocator");
-
   static_assert((!is_same<allocator_type, __node_allocator>::value),
                 "internal allocator type must differ from user-specified "
                 "type; otherwise overload resolution breaks");
diff --git a/libcxx/include/list b/libcxx/include/list
index 87f15e144ac8f..7419419ff6585 100644
--- a/libcxx/include/list
+++ b/libcxx/include/list
@@ -674,6 +674,7 @@ class _LIBCPP_TEMPLATE_VIS list : private __list_imp<_Tp, _Alloc> {
 public:
   typedef _Tp value_type;
   typedef _Alloc allocator_type;
+  static_assert(__check_valid_allocator<allocator_type>::value);
   static_assert((is_same<value_type, typename allocator_type::value_type>::value),
                 "Allocator::value_type must be same type as value_type");
   typedef value_type& reference;
@@ -692,10 +693,6 @@ public:
   typedef void __remove_return_type;
 #endif
 
-  static_assert(is_same<allocator_type, __rebind_alloc<allocator_traits<allocator_type>, value_type> >::value,
-                "[allocator.requirements] states that rebinding an allocator to the same type should result in the "
-                "original allocator");
-
   _LIBCPP_HIDE_FROM_ABI list() _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value) {}
   _LIBCPP_HIDE_FROM_ABI explicit list(const allocator_type& __a) : base(__a) {}
   _LIBCPP_HIDE_FROM_ABI explicit list(size_type __n);
diff --git a/libcxx/include/map b/libcxx/include/map
index 7efa715e84aa7..06d25cf15ed7a 100644
--- a/libcxx/include/map
+++ b/libcxx/include/map
@@ -999,9 +999,7 @@ private:
   typedef typename __base::__node_traits __node_traits;
   typedef allocator_traits<allocator_type> __alloc_traits;
 
-  static_assert(is_same<allocator_type, __rebind_alloc<__alloc_traits, value_type> >::value,
-                "[allocator.requirements] states that rebinding an allocator to the same type should result in the "
-                "original allocator");
+  static_assert(__check_valid_allocator<allocator_type>::value, "");
 
   __base __tree_;
 
@@ -1659,6 +1657,7 @@ public:
   typedef value_type& reference;
   typedef const value_type& const_reference;
 
+  static_assert(__check_valid_allocator<allocator_type>::value, "");
   static_assert((is_same<typename allocator_type::value_type, value_type>::value),
                 "Allocator::value_type must be same type as value_type");
 
@@ -1684,10 +1683,6 @@ private:
   typedef typename __base::__node_traits __node_traits;
   typedef allocator_traits<allocator_type> __alloc_traits;
 
-  static_assert(is_same<allocator_type, __rebind_alloc<__alloc_traits, value_type> >::value,
-                "[allocator.requirements] states that rebinding an allocator to the same type should result in the "
-                "original allocator");
-
   __base __tree_;
 
 public:
diff --git a/libcxx/include/set b/libcxx/include/set
index ab3a4363499af..83d6e47eb11b4 100644
--- a/libcxx/include/set
+++ b/libcxx/include/set
@@ -578,9 +578,7 @@ private:
   typedef __tree<value_type, value_compare, allocator_type> __base;
   typedef allocator_traits<allocator_type> __alloc_traits;
 
-  static_assert(is_same<allocator_type, __rebind_alloc<__alloc_traits, value_type> >::value,
-                "[allocator.requirements] states that rebinding an allocator to the same type should result in the "
-                "original allocator");
+  static_assert(__check_valid_allocator<allocator_type>::value, "");
 
   __base __tree_;
 
@@ -1035,9 +1033,7 @@ private:
   typedef __tree<value_type, value_compare, allocator_type> __base;
   typedef allocator_traits<allocator_type> __alloc_traits;
 
-  static_assert(is_same<allocator_type, __rebind_alloc<__alloc_traits, value_type> >::value,
-                "[allocator.requirements] states that rebinding an allocator to the same type should result in the "
-                "original allocator");
+  static_assert(__check_valid_allocator<allocator_type>::value, "");
 
   __base __tree_;
 
diff --git a/libcxx/include/string b/libcxx/include/string
index 751af8f1476d0..01f34fd3411bf 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -781,10 +781,7 @@ public:
                 "traits_type::char_type must be the same type as CharT");
   static_assert((is_same<typename allocator_type::value_type, value_type>::value),
                 "Allocator::value_type must be same type as value_type");
-
-  static_assert(is_same<allocator_type, __rebind_alloc<__alloc_traits, value_type> >::value,
-                "[allocator.requirements] states that rebinding an allocator to the same type should result in the "
-                "original allocator");
+  static_assert(__check_valid_allocator<allocator_type>::value, "");
 
   // TODO: Implement iterator bounds checking without requiring the global database.
   typedef __wrap_iter<pointer> iterator;
diff --git a/libcxx/include/unordered_map b/libcxx/include/unordered_map
index 2e25b0f050695..a9e15a3518ca6 100644
--- a/libcxx/include/unordered_map
+++ b/libcxx/include/unordered_map
@@ -1059,9 +1059,7 @@ private:
   typedef unique_ptr<__node, _Dp> __node_holder;
   typedef allocator_traits<allocator_type> __alloc_traits;
 
-  static_assert(is_same<allocator_type, __rebind_alloc<__alloc_traits, value_type> >::value,
-                "[allocator.requirements] states that rebinding an allocator to the same type should result in the "
-                "original allocator");
+  static_assert(__check_valid_allocator<allocator_type>::value, "");
 
   static_assert((is_same<typename __table::__container_value_type, value_type>::value), "");
   static_assert((is_same<typename __table::__node_value_type, __value_type>::value), "");
@@ -1843,6 +1841,7 @@ public:
   typedef pair<const key_type, mapped_type> value_type;
   typedef value_type& reference;
   typedef const value_type& const_reference;
+  static_assert(__check_valid_allocator<allocator_type>::value, "");
   static_assert((is_same<value_type, typename allocator_type::value_type>::value),
                 "Allocator::value_type must be same type as value_type");
 
@@ -1866,10 +1865,6 @@ private:
   static_assert((is_same<typename __node_traits::size_type, typename __alloc_traits::size_type>::value),
                 "Allocator uses different size_type for different types");
 
-  static_assert(is_same<allocator_type, __rebind_alloc<__alloc_traits, value_type> >::value,
-                "[allocator.requirements] states that rebinding an allocator to the same type should result in the "
-                "original allocator");
-
 public:
   typedef typename __alloc_traits::pointer pointer;
   typedef typename __alloc_traits::const_pointer const_pointer;
diff --git a/libcxx/include/unordered_set b/libcxx/include/unordered_set
index c966cc8eb4df1..89bbc455d0b5d 100644
--- a/libcxx/include/unordered_set
+++ b/libcxx/include/unordered_set
@@ -588,13 +588,10 @@ public:
   typedef __type_identity_t<_Alloc> allocator_type;
   typedef value_type& reference;
   typedef const value_type& const_reference;
+  static_assert(__check_valid_allocator<allocator_type>::value, "");
   static_assert((is_same<value_type, typename allocator_type::value_type>::value),
                 "Allocator::value_type must be same type as value_type");
 
-  static_assert(is_same<allocator_type, __rebind_alloc<allocator_traits<allocator_type>, value_type> >::value,
-                "[allocator.requirements] states that rebinding an allocator to the same type should result in the "
-                "original allocator");
-
 private:
   typedef __hash_table<value_type, hasher, key_equal, allocator_type> __table;
 
diff --git a/libcxx/include/vector b/libcxx/include/vector
index ecefc6f6f5bcc..5b6deae96823c 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -415,13 +415,10 @@ public:
       vector,
       void>;
 
+  static_assert(__check_valid_allocator<allocator_type>::value, "");
   static_assert((is_same<typename allocator_type::value_type, value_type>::value),
                 "Allocator::value_type must be same type as value_type");
 
-  static_assert(is_same<allocator_type, __rebind_alloc<__alloc_traits, value_type> >::value,
-                "[allocator.requirements] states that rebinding an allocator to the same type should result in the "
-                "original allocator");
-
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector()
       _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) {}
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(const allocator_type& __a)



More information about the libcxx-commits mailing list