[libcxx-commits] [libcxx] [libc++] Optimize copy construction and assignment of __tree (PR #151304)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jul 31 06:38:44 PDT 2025


================
@@ -12,116 +12,93 @@
 
 // map(const map& m, const allocator_type& a);
 
-#include <map>
 #include <cassert>
+#include <map>
 
 #include "test_macros.h"
 #include "../../../test_compare.h"
 #include "test_allocator.h"
 #include "min_allocator.h"
 
-int main(int, char**) {
-  {
-    typedef std::pair<const int, double> V;
-    V ar[] = {
-        V(1, 1),
-        V(1, 1.5),
-        V(1, 2),
-        V(2, 1),
-        V(2, 1.5),
-        V(2, 2),
-        V(3, 1),
-        V(3, 1.5),
-        V(3, 2),
-    };
-    typedef test_less<int> C;
-    typedef test_allocator<V> A;
-    std::map<int, double, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(7));
-    std::map<int, double, C, A> m(mo, A(3));
-    assert(m.get_allocator() == A(3));
-    assert(m.key_comp() == C(5));
-    assert(m.size() == 3);
-    assert(std::distance(m.begin(), m.end()) == 3);
-    assert(*m.begin() == V(1, 1));
-    assert(*std::next(m.begin()) == V(2, 1));
-    assert(*std::next(m.begin(), 2) == V(3, 1));
-
-    assert(mo.get_allocator() == A(7));
-    assert(mo.key_comp() == C(5));
-    assert(mo.size() == 3);
-    assert(std::distance(mo.begin(), mo.end()) == 3);
-    assert(*mo.begin() == V(1, 1));
-    assert(*std::next(mo.begin()) == V(2, 1));
-    assert(*std::next(mo.begin(), 2) == V(3, 1));
+template <class Alloc>
+void test_alloc(const Alloc& new_alloc) {
+  { // Simple check
+    using V = std::pair<const int, int>;
+    V arr[] = {V(1, 1), V(2, 3), V(3, 6)};
+    std::map<int, int, std::less<int>, Alloc> orig(begin(arr), end(arr));
+    std::map<int, int, std::less<int>, Alloc> copy(orig, new_alloc);
+    assert(copy.size() == 3);
+    assert(*std::next(copy.begin(), 0) == V(1, 1));
+    assert(*std::next(copy.begin(), 1) == V(2, 3));
+    assert(*std::next(copy.begin(), 2) == V(3, 6));
+    assert(std::next(copy.begin(), 3) == copy.end());
+    assert(copy.get_allocator() == new_alloc);
+
+    // Check that orig is still what is expected
+    assert(orig.size() == 3);
+    assert(*std::next(orig.begin(), 0) == V(1, 1));
+    assert(*std::next(orig.begin(), 1) == V(2, 3));
+    assert(*std::next(orig.begin(), 2) == V(3, 6));
+    assert(std::next(orig.begin(), 3) == orig.end());
   }
-#if TEST_STD_VER >= 11
-  {
-    typedef std::pair<const int, double> V;
-    V ar[] = {
-        V(1, 1),
-        V(1, 1.5),
-        V(1, 2),
-        V(2, 1),
-        V(2, 1.5),
-        V(2, 2),
-        V(3, 1),
-        V(3, 1.5),
-        V(3, 2),
-    };
-    typedef test_less<int> C;
-    typedef min_allocator<V> A;
-    std::map<int, double, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A());
-    std::map<int, double, C, A> m(mo, A());
-    assert(m.get_allocator() == A());
-    assert(m.key_comp() == C(5));
-    assert(m.size() == 3);
-    assert(std::distance(m.begin(), m.end()) == 3);
-    assert(*m.begin() == V(1, 1));
-    assert(*std::next(m.begin()) == V(2, 1));
-    assert(*std::next(m.begin(), 2) == V(3, 1));
-
-    assert(mo.get_allocator() == A());
-    assert(mo.key_comp() == C(5));
-    assert(mo.size() == 3);
-    assert(std::distance(mo.begin(), mo.end()) == 3);
-    assert(*mo.begin() == V(1, 1));
-    assert(*std::next(mo.begin()) == V(2, 1));
-    assert(*std::next(mo.begin(), 2) == V(3, 1));
+
+  { // copy empty map
+    using V = std::pair<const int, int>;
+    std::map<int, int, std::less<int>, Alloc> orig;
+    std::map<int, int, std::less<int>, Alloc> copy = orig;
+    assert(copy.size() == 0);
+    assert(copy.begin() == copy.end());
+
+    // Check that orig is still what is expected
+    assert(orig.size() == 0);
+    assert(orig.begin() == orig.end());
+  }
+
+  { // only some leaf nodes exist
+    using V = std::pair<const int, int>;
+    V arr[] = {V(1, 1), V(2, 3), V(3, 6), V(4, 7), V(5, 0)};
+    std::map<int, int, std::less<int>, Alloc> orig(begin(arr), end(arr));
+    std::map<int, int, std::less<int>, Alloc> copy = orig;
+    assert(copy.size() == 5);
+    assert(*std::next(copy.begin(), 0) == V(1, 1));
+    assert(*std::next(copy.begin(), 1) == V(2, 3));
+    assert(*std::next(copy.begin(), 2) == V(3, 6));
+    assert(*std::next(copy.begin(), 3) == V(4, 7));
+    assert(*std::next(copy.begin(), 4) == V(5, 0));
+    assert(std::next(copy.begin(), 5) == copy.end());
+
+    // Check that orig is still what is expected
+    assert(orig.size() == 5);
+    assert(*std::next(orig.begin(), 0) == V(1, 1));
+    assert(*std::next(orig.begin(), 1) == V(2, 3));
+    assert(*std::next(orig.begin(), 2) == V(3, 6));
+    assert(*std::next(orig.begin(), 3) == V(4, 7));
+    assert(*std::next(orig.begin(), 4) == V(5, 0));
+    assert(std::next(orig.begin(), 5) == orig.end());
   }
-  {
-    typedef std::pair<const int, double> V;
-    V ar[] = {
-        V(1, 1),
-        V(1, 1.5),
-        V(1, 2),
-        V(2, 1),
-        V(2, 1.5),
-        V(2, 2),
-        V(3, 1),
-        V(3, 1.5),
-        V(3, 2),
-    };
-    typedef test_less<int> C;
-    typedef explicit_allocator<V> A;
-    std::map<int, double, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A{});
-    std::map<int, double, C, A> m(mo, A{});
-    assert(m.get_allocator() == A());
-    assert(m.key_comp() == C(5));
-    assert(m.size() == 3);
-    assert(std::distance(m.begin(), m.end()) == 3);
-    assert(*m.begin() == V(1, 1));
-    assert(*std::next(m.begin()) == V(2, 1));
-    assert(*std::next(m.begin(), 2) == V(3, 1));
-
-    assert(mo.get_allocator() == A());
-    assert(mo.key_comp() == C(5));
-    assert(mo.size() == 3);
-    assert(std::distance(mo.begin(), mo.end()) == 3);
-    assert(*mo.begin() == V(1, 1));
-    assert(*std::next(mo.begin()) == V(2, 1));
-    assert(*std::next(mo.begin(), 2) == V(3, 1));
+}
+
+void test() {
+  test_alloc(std::allocator<std::pair<const int, int>>());
+  test_alloc(test_allocator<std::pair<const int, int>>(25)); // Make sure that the new allocator is acutually used
----------------
ldionne wrote:

```suggestion
  test_alloc(test_allocator<std::pair<const int, int>>(25)); // Make sure that the new allocator is actually used
```

https://github.com/llvm/llvm-project/pull/151304


More information about the libcxx-commits mailing list