[libcxx-commits] [libcxx] Revert "[libc++] Optimize copy construction and assignment of __tree" (PR #152180)
Andrew Lazarev via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Aug 5 10:12:40 PDT 2025
https://github.com/alazarev created https://github.com/llvm/llvm-project/pull/152180
Reverts llvm/llvm-project#151304
Broke ubsan:
https://lab.llvm.org/buildbot/#/builders/25/builds/10410
>From 36c8b1e64ba4adfd5b0b33f32a29a3744e894fa8 Mon Sep 17 00:00:00 2001
From: Andrew Lazarev <alazarev at google.com>
Date: Tue, 5 Aug 2025 10:11:41 -0700
Subject: [PATCH] Revert "[libc++] Optimize copy construction and assignment of
__tree (#151304)"
This reverts commit 1cac2be874c5f1b1b70bdaea8891f5e5b76a84e2.
---
libcxx/docs/ReleaseNotes/22.rst | 3 -
libcxx/include/__tree | 135 +----
libcxx/include/map | 8 +-
libcxx/include/set | 8 +-
.../associative_container_benchmarks.h | 38 +-
.../containers/associative/map.bench.cpp | 1 -
.../containers/associative/multimap.bench.cpp | 1 -
.../containers/associative/multiset.bench.cpp | 1 -
.../containers/associative/set.bench.cpp | 1 -
.../libcxx/gdb/gdb_pretty_printer_test.sh.cpp | 5 -
.../associative/map/map.cons/copy.pass.cpp | 217 ++++----
.../map/map.cons/copy_alloc.pass.cpp | 184 ++++---
.../map/map.cons/copy_assign.pass.cpp | 496 +++++++++---------
.../multimap/multimap.cons/copy.pass.cpp | 185 +++----
.../multimap.cons/copy_alloc.pass.cpp | 155 +++---
.../multimap.cons/copy_assign.pass.cpp | 357 ++++---------
.../multiset/multiset.cons/copy.pass.cpp | 180 +++----
.../multiset.cons/copy_alloc.pass.cpp | 114 ++--
.../multiset.cons/copy_assign.pass.cpp | 339 +++---------
.../associative/set/set.cons/copy.pass.cpp | 160 ++----
.../set/set.cons/copy_alloc.pass.cpp | 107 +---
.../set/set.cons/copy_assign.pass.cpp | 318 +++--------
22 files changed, 1029 insertions(+), 1984 deletions(-)
diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst
index 8b8dce5083149..15bf46d44b07f 100644
--- a/libcxx/docs/ReleaseNotes/22.rst
+++ b/libcxx/docs/ReleaseNotes/22.rst
@@ -43,9 +43,6 @@ Implemented Papers
Improvements and New Features
-----------------------------
-- The performance of ``map::map(const map&)`` has been improved up to 2.3x
-- The performance of ``map::operator=(const map&)`` has been improved by up to 11x
-
Deprecations and Removals
-------------------------
diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index 1b1bb538029da..f8bb4f01b1e29 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -1213,104 +1213,6 @@ private:
__node_pointer __cache_root_;
__node_pointer __cache_elem_;
};
-
- class __tree_deleter {
- __node_allocator& __alloc_;
-
- public:
- using pointer = __node_pointer;
-
- _LIBCPP_HIDE_FROM_ABI __tree_deleter(__node_allocator& __alloc) : __alloc_(__alloc) {}
-
-#ifdef _LIBCPP_COMPILER_CLANG_BASED // FIXME: GCC complains about not being able to always_inline a recursive function
- _LIBCPP_HIDE_FROM_ABI
-#endif
- void
- operator()(__node_pointer __ptr) {
- if (!__ptr)
- return;
-
- (*this)(static_cast<__node_pointer>(__ptr->__left_));
-
- auto __right = __ptr->__right_;
-
- __node_traits::destroy(__alloc_, std::addressof(__ptr->__value_));
- __node_traits::deallocate(__alloc_, __ptr, 1);
-
- (*this)(static_cast<__node_pointer>(__right));
- }
- };
-
- // This copy construction will always produce a correct red-black-tree assuming the incoming tree is correct, since we
- // copy the exact structure 1:1. Since this is for copy construction _only_ we know that we get a correct tree. If we
- // didn't get a correct tree, the invariants of __tree are broken and we have a much bigger problem than an improperly
- // balanced tree.
-#ifdef _LIBCPP_COMPILER_CLANG_BASED // FIXME: GCC complains about not being able to always_inline a recursive function
- _LIBCPP_HIDE_FROM_ABI
-#endif
- __node_pointer
- __copy_construct_tree(__node_pointer __src) {
- if (!__src)
- return nullptr;
-
- __node_holder __new_node = __construct_node(__src->__value_);
-
- unique_ptr<__node, __tree_deleter> __left(
- __copy_construct_tree(static_cast<__node_pointer>(__src->__left_)), __node_alloc_);
- __node_pointer __right = __copy_construct_tree(static_cast<__node_pointer>(__src->__right_));
-
- __node_pointer __new_node_ptr = __new_node.release();
-
- __new_node_ptr->__is_black_ = __src->__is_black_;
- __new_node_ptr->__left_ = static_cast<__node_base_pointer>(__left.release());
- __new_node_ptr->__right_ = static_cast<__node_base_pointer>(__right);
- if (__new_node_ptr->__left_)
- __new_node_ptr->__left_->__parent_ = static_cast<__end_node_pointer>(__new_node_ptr);
- if (__new_node_ptr->__right_)
- __new_node_ptr->__right_->__parent_ = static_cast<__end_node_pointer>(__new_node_ptr);
- return __new_node_ptr;
- }
-
- // This copy assignment will always produce a correct red-black-tree assuming the incoming tree is correct, since our
- // own tree is a red-black-tree and the incoming tree is a red-black-tree. The invariants of a red-black-tree are
- // temporarily not met until all of the incoming red-black tree is copied.
-#ifdef _LIBCPP_COMPILER_CLANG_BASED // FIXME: GCC complains about not being able to always_inline a recursive function
- _LIBCPP_HIDE_FROM_ABI
-#endif
- __node_pointer
- __copy_assign_tree(__node_pointer __dest, __node_pointer __src) {
- if (!__src) {
- destroy(__dest);
- return nullptr;
- }
-
- __assign_value(__dest->__value_, __src->__value_);
- __dest->__is_black_ = __src->__is_black_;
-
- // If we already have a left node in the destination tree, reuse it and copy-assign recursively
- if (__dest->__left_) {
- __dest->__left_ = static_cast<__node_base_pointer>(__copy_assign_tree(
- static_cast<__node_pointer>(__dest->__left_), static_cast<__node_pointer>(__src->__left_)));
-
- // Otherwise, we must create new nodes; copy-construct from here on
- } else if (__src->__left_) {
- auto __new_left = __copy_construct_tree(static_cast<__node_pointer>(__src->__left_));
- __dest->__left_ = static_cast<__node_base_pointer>(__new_left);
- __new_left->__parent_ = static_cast<__end_node_pointer>(__dest);
- }
-
- // Identical to the left case above, just for the right nodes
- if (__dest->__right_) {
- __dest->__right_ = static_cast<__node_base_pointer>(__copy_assign_tree(
- static_cast<__node_pointer>(__dest->__right_), static_cast<__node_pointer>(__src->__right_)));
- } else if (__src->__right_) {
- auto __new_right = __copy_construct_tree(static_cast<__node_pointer>(__src->__right_));
- __dest->__right_ = static_cast<__node_base_pointer>(__new_right);
- __new_right->__parent_ = static_cast<__end_node_pointer>(__dest);
- }
-
- return __dest;
- }
};
template <class _Tp, class _Compare, class _Allocator>
@@ -1375,22 +1277,11 @@ __tree<_Tp, _Compare, _Allocator>::_DetachedTreeCache::__detach_next(__node_poin
template <class _Tp, class _Compare, class _Allocator>
__tree<_Tp, _Compare, _Allocator>& __tree<_Tp, _Compare, _Allocator>::operator=(const __tree& __t) {
- if (this == std::addressof(__t))
- return *this;
-
- value_comp() = __t.value_comp();
- __copy_assign_alloc(__t);
-
- if (__size_ != 0) {
- *__root_ptr() = static_cast<__node_base_pointer>(__copy_assign_tree(__root(), __t.__root()));
- } else {
- *__root_ptr() = static_cast<__node_base_pointer>(__copy_construct_tree(__t.__root()));
- if (__root())
- __root()->__parent_ = __end_node();
+ if (this != std::addressof(__t)) {
+ value_comp() = __t.value_comp();
+ __copy_assign_alloc(__t);
+ __assign_multi(__t.begin(), __t.end());
}
- __begin_node_ = static_cast<__end_node_pointer>(std::__tree_min(static_cast<__node_base_pointer>(__end_node())));
- __size_ = __t.size();
-
return *this;
}
@@ -1436,17 +1327,11 @@ void __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _
template <class _Tp, class _Compare, class _Allocator>
__tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t)
- : __begin_node_(__end_node()),
+ : __begin_node_(),
__node_alloc_(__node_traits::select_on_container_copy_construction(__t.__node_alloc())),
__size_(0),
__value_comp_(__t.value_comp()) {
- if (__t.size() == 0)
- return;
-
- *__root_ptr() = static_cast<__node_base_pointer>(__copy_construct_tree(__t.__root()));
- __root()->__parent_ = __end_node();
- __begin_node_ = static_cast<__end_node_pointer>(std::__tree_min(static_cast<__node_base_pointer>(__end_node())));
- __size_ = __t.size();
+ __begin_node_ = __end_node();
}
template <class _Tp, class _Compare, class _Allocator>
@@ -1545,7 +1430,13 @@ __tree<_Tp, _Compare, _Allocator>::~__tree() {
template <class _Tp, class _Compare, class _Allocator>
void __tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd) _NOEXCEPT {
- (__tree_deleter(__node_alloc_))(__nd);
+ if (__nd != nullptr) {
+ destroy(static_cast<__node_pointer>(__nd->__left_));
+ destroy(static_cast<__node_pointer>(__nd->__right_));
+ __node_allocator& __na = __node_alloc();
+ __node_traits::destroy(__na, std::addressof(__nd->__value_));
+ __node_traits::deallocate(__na, __nd, 1);
+ }
}
template <class _Tp, class _Compare, class _Allocator>
diff --git a/libcxx/include/map b/libcxx/include/map
index 0a43bd09a0b16..2251565801470 100644
--- a/libcxx/include/map
+++ b/libcxx/include/map
@@ -970,7 +970,7 @@ public:
: map(from_range, std::forward<_Range>(__range), key_compare(), __a) {}
# endif
- _LIBCPP_HIDE_FROM_ABI map(const map& __m) = default;
+ _LIBCPP_HIDE_FROM_ABI map(const map& __m) : __tree_(__m.__tree_) { insert(__m.begin(), __m.end()); }
_LIBCPP_HIDE_FROM_ABI map& operator=(const map& __m) = default;
@@ -1637,7 +1637,11 @@ public:
: multimap(from_range, std::forward<_Range>(__range), key_compare(), __a) {}
# endif
- _LIBCPP_HIDE_FROM_ABI multimap(const multimap& __m) = default;
+ _LIBCPP_HIDE_FROM_ABI multimap(const multimap& __m)
+ : __tree_(__m.__tree_.value_comp(),
+ __alloc_traits::select_on_container_copy_construction(__m.__tree_.__alloc())) {
+ insert(__m.begin(), __m.end());
+ }
_LIBCPP_HIDE_FROM_ABI multimap& operator=(const multimap& __m) = default;
diff --git a/libcxx/include/set b/libcxx/include/set
index 342a5294c814f..1f2fd7fc91bbb 100644
--- a/libcxx/include/set
+++ b/libcxx/include/set
@@ -660,7 +660,7 @@ public:
: set(from_range, std::forward<_Range>(__range), key_compare(), __a) {}
# endif
- _LIBCPP_HIDE_FROM_ABI set(const set& __s) = default;
+ _LIBCPP_HIDE_FROM_ABI set(const set& __s) : __tree_(__s.__tree_) { insert(__s.begin(), __s.end()); }
_LIBCPP_HIDE_FROM_ABI set& operator=(const set& __s) = default;
@@ -1119,7 +1119,11 @@ public:
: multiset(from_range, std::forward<_Range>(__range), key_compare(), __a) {}
# endif
- _LIBCPP_HIDE_FROM_ABI multiset(const multiset& __s) = default;
+ _LIBCPP_HIDE_FROM_ABI multiset(const multiset& __s)
+ : __tree_(__s.__tree_.value_comp(),
+ __alloc_traits::select_on_container_copy_construction(__s.__tree_.__alloc())) {
+ insert(__s.begin(), __s.end());
+ }
_LIBCPP_HIDE_FROM_ABI multiset& operator=(const multiset& __s) = default;
diff --git a/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h b/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h
index 535a52f0a08ab..0ff7f15164d8a 100644
--- a/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h
+++ b/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h
@@ -151,7 +151,7 @@ void associative_container_benchmarks(std::string container) {
/////////////////////////
// Assignment
/////////////////////////
- bench("operator=(const&) (into cleared Container)", [=](auto& st) {
+ bench("operator=(const&)", [=](auto& st) {
const std::size_t size = st.range(0);
std::vector<Value> in = make_value_types(generate_unique_keys(size));
Container src(in.begin(), in.end());
@@ -172,42 +172,6 @@ void associative_container_benchmarks(std::string container) {
}
});
- bench("operator=(const&) (into partially populated Container)", [=](auto& st) {
- const std::size_t size = st.range(0);
- std::vector<Value> in = make_value_types(generate_unique_keys(size));
- Container src(in.begin(), in.end());
- Container c[BatchSize];
-
- while (st.KeepRunningBatch(BatchSize)) {
- for (std::size_t i = 0; i != BatchSize; ++i) {
- c[i] = src;
- benchmark::DoNotOptimize(c[i]);
- benchmark::ClobberMemory();
- }
-
- st.PauseTiming();
- for (std::size_t i = 0; i != BatchSize; ++i) {
- c[i].clear();
- }
- st.ResumeTiming();
- }
- });
-
- bench("operator=(const&) (into populated Container)", [=](auto& st) {
- const std::size_t size = st.range(0);
- std::vector<Value> in = make_value_types(generate_unique_keys(size));
- Container src(in.begin(), in.end());
- Container c[BatchSize];
-
- while (st.KeepRunningBatch(BatchSize)) {
- for (std::size_t i = 0; i != BatchSize; ++i) {
- c[i] = src;
- benchmark::DoNotOptimize(c[i]);
- benchmark::ClobberMemory();
- }
- }
- });
-
/////////////////////////
// Insertion
/////////////////////////
diff --git a/libcxx/test/benchmarks/containers/associative/map.bench.cpp b/libcxx/test/benchmarks/containers/associative/map.bench.cpp
index bd664dbb56ee7..cee669ae0a667 100644
--- a/libcxx/test/benchmarks/containers/associative/map.bench.cpp
+++ b/libcxx/test/benchmarks/containers/associative/map.bench.cpp
@@ -29,7 +29,6 @@ struct support::adapt_operations<std::map<K, V>> {
int main(int argc, char** argv) {
support::associative_container_benchmarks<std::map<int, int>>("std::map<int, int>");
- support::associative_container_benchmarks<std::map<std::string, int>>("std::map<std::string, int>");
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/containers/associative/multimap.bench.cpp b/libcxx/test/benchmarks/containers/associative/multimap.bench.cpp
index 15a0b573081bb..6ae93f06aa363 100644
--- a/libcxx/test/benchmarks/containers/associative/multimap.bench.cpp
+++ b/libcxx/test/benchmarks/containers/associative/multimap.bench.cpp
@@ -28,7 +28,6 @@ struct support::adapt_operations<std::multimap<K, V>> {
int main(int argc, char** argv) {
support::associative_container_benchmarks<std::multimap<int, int>>("std::multimap<int, int>");
- support::associative_container_benchmarks<std::multimap<std::string, int>>("std::multimap<std::string, int>");
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/containers/associative/multiset.bench.cpp b/libcxx/test/benchmarks/containers/associative/multiset.bench.cpp
index c205e0a4f793f..894f159a52e4a 100644
--- a/libcxx/test/benchmarks/containers/associative/multiset.bench.cpp
+++ b/libcxx/test/benchmarks/containers/associative/multiset.bench.cpp
@@ -26,7 +26,6 @@ struct support::adapt_operations<std::multiset<K>> {
int main(int argc, char** argv) {
support::associative_container_benchmarks<std::multiset<int>>("std::multiset<int>");
- support::associative_container_benchmarks<std::multiset<std::string>>("std::multiset<std::string>");
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/containers/associative/set.bench.cpp b/libcxx/test/benchmarks/containers/associative/set.bench.cpp
index 50ee142b6e8b3..6b7b142c792ba 100644
--- a/libcxx/test/benchmarks/containers/associative/set.bench.cpp
+++ b/libcxx/test/benchmarks/containers/associative/set.bench.cpp
@@ -27,7 +27,6 @@ struct support::adapt_operations<std::set<K>> {
int main(int argc, char** argv) {
support::associative_container_benchmarks<std::set<int>>("std::set<int>");
- support::associative_container_benchmarks<std::set<std::string>>("std::set<std::string>");
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp b/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp
index f5a878582666b..f125cc9adc491 100644
--- a/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp
+++ b/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp
@@ -324,11 +324,6 @@ void deque_test() {
void map_test() {
std::map<int, int> i_am_empty{};
-
- // Make __tree_itertor available in the debug info
- // FIXME: Is there any way to avoid this requirement?
- (void)i_am_empty.begin();
-
ComparePrettyPrintToChars(i_am_empty, "std::map is empty");
std::map<int, std::string> one_two_three;
diff --git a/libcxx/test/std/containers/associative/map/map.cons/copy.pass.cpp b/libcxx/test/std/containers/associative/map/map.cons/copy.pass.cpp
index f1696b003c131..e7a69aff0b036 100644
--- a/libcxx/test/std/containers/associative/map/map.cons/copy.pass.cpp
+++ b/libcxx/test/std/containers/associative/map/map.cons/copy.pass.cpp
@@ -12,129 +12,116 @@
// map(const map& m);
-#include <cassert>
#include <map>
+#include <cassert>
-#include "min_allocator.h"
+#include "test_macros.h"
#include "../../../test_compare.h"
#include "test_allocator.h"
+#include "min_allocator.h"
-template <template <class> class Alloc>
-void test_alloc() {
- { // Simple check
- using V = std::pair<const int, int>;
- using Map = std::map<int, int, std::less<int>, Alloc<V> >;
-
- V arr[] = {V(1, 1), V(2, 3), V(3, 6)};
- const Map orig(begin(arr), end(arr));
- Map copy = orig;
- 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());
-
- // 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());
- }
-
- { // copy empty map
- using V = std::pair<const int, int>;
- using Map = std::map<int, int, std::less<int>, Alloc<V> >;
-
- const Map orig;
- Map 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>;
- using Map = std::map<int, int, std::less<int>, Alloc<V> >;
-
- V arr[] = {V(1, 1), V(2, 3), V(3, 6), V(4, 7), V(5, 0)};
- const Map orig(begin(arr), end(arr));
- Map 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());
- }
-}
-
-void test() {
- test_alloc<std::allocator>();
- test_alloc<min_allocator>(); // Make sure that fancy pointers work
-
- { // Ensure that the comparator is copied
- using V = std::pair<const int, int>;
- using Map = std::map<int, int, test_less<int> >;
-
- V arr[] = {V(1, 1), V(2, 3), V(3, 6)};
- const Map orig(begin(arr), end(arr), test_less<int>(3));
- Map copy = orig;
- assert(copy.size() == 3);
- assert(copy.key_comp() == test_less<int>(3));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.key_comp() == test_less<int>(3));
+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;
+ assert(m.get_allocator() == A(7));
+ 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));
}
-
- { // Ensure that the allocator is copied
- using V = std::pair<const int, int>;
- using Map = std::map<int, int, std::less<int>, test_allocator<V> >;
-
- V arr[] = {V(1, 1), V(2, 3), V(3, 6)};
- const Map orig(begin(arr), end(arr), std::less<int>(), test_allocator<V>(10));
- Map copy = orig;
- assert(copy.size() == 3);
- assert(copy.get_allocator() == test_allocator<V>(10));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.get_allocator() == test_allocator<V>(10));
- assert(orig.get_allocator().get_id() != test_alloc_base::moved_value);
+#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 other_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;
+ assert(m.get_allocator() == A(-2));
+ 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));
}
-
- { // Ensure that soccc is handled properly
- using V = std::pair<const int, int>;
- using Map = std::map<int, int, std::less<int>, other_allocator<V> >;
-
- V arr[] = {V(1, 1), V(2, 3), V(3, 6)};
- const Map orig(begin(arr), end(arr), std::less<int>(), other_allocator<V>(10));
- Map copy = orig;
- assert(copy.size() == 3);
- assert(copy.get_allocator() == other_allocator<V>(-2));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.get_allocator() == other_allocator<V>(10));
+ {
+ 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;
+ 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));
}
-}
-
-int main(int, char**) {
- test();
+#endif
return 0;
}
diff --git a/libcxx/test/std/containers/associative/map/map.cons/copy_alloc.pass.cpp b/libcxx/test/std/containers/associative/map/map.cons/copy_alloc.pass.cpp
index caa3490d44faf..aaf1be867b748 100644
--- a/libcxx/test/std/containers/associative/map/map.cons/copy_alloc.pass.cpp
+++ b/libcxx/test/std/containers/associative/map/map.cons/copy_alloc.pass.cpp
@@ -12,100 +12,116 @@
// map(const map& m, const allocator_type& a);
-#include <cassert>
#include <map>
+#include <cassert>
#include "test_macros.h"
#include "../../../test_compare.h"
#include "test_allocator.h"
#include "min_allocator.h"
-template <class Alloc>
-void test_alloc(const Alloc& new_alloc) {
- { // Simple check
- using V = std::pair<const int, int>;
- using Map = std::map<int, int, std::less<int>, Alloc>;
-
- V arr[] = {V(1, 1), V(2, 3), V(3, 6)};
- const Map orig(begin(arr), end(arr));
- Map 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());
- }
-
- { // copy empty map
- using Map = std::map<int, int, std::less<int>, Alloc>;
-
- const Map orig;
- Map 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());
+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));
}
-
- { // only some leaf nodes exist
- using V = std::pair<const int, int>;
- using Map = std::map<int, int, std::less<int>, Alloc>;
-
- V arr[] = {V(1, 1), V(2, 3), V(3, 6), V(4, 7), V(5, 0)};
- const Map orig(begin(arr), end(arr));
- Map 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());
+#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));
}
-}
-
-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 actually used
- test_alloc(min_allocator<std::pair<const int, int> >()); // Make sure that fancy pointers work
-
- { // Ensure that the comparator is copied
- using V = std::pair<const int, int>;
- using Map = std::map<int, int, test_less<int> >;
-
- V arr[] = {V(1, 1), V(2, 3), V(3, 6)};
- const Map orig(begin(arr), end(arr), test_less<int>(3));
- Map copy(orig, std::allocator<V>());
- assert(copy.size() == 3);
- assert(copy.key_comp() == test_less<int>(3));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.key_comp() == test_less<int>(3));
+ {
+ 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));
}
-}
-
-int main(int, char**) {
- test();
+#endif
return 0;
}
diff --git a/libcxx/test/std/containers/associative/map/map.cons/copy_assign.pass.cpp b/libcxx/test/std/containers/associative/map/map.cons/copy_assign.pass.cpp
index e01a10b679ac6..07c8bab2f201d 100644
--- a/libcxx/test/std/containers/associative/map/map.cons/copy_assign.pass.cpp
+++ b/libcxx/test/std/containers/associative/map/map.cons/copy_assign.pass.cpp
@@ -12,11 +12,11 @@
// map& operator=(const map& m);
+#include <map>
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <iterator>
-#include <map>
#include <vector>
#include "test_macros.h"
@@ -24,286 +24,274 @@
#include "test_allocator.h"
#include "min_allocator.h"
-template <class T>
-class tracking_allocator {
- std::vector<void*>* allocs_;
-
- template <class U>
- friend class tracking_allocator;
+#if TEST_STD_VER >= 11
+std::vector<int> ca_allocs;
+std::vector<int> ca_deallocs;
+template <class T>
+class counting_allocatorT {
public:
- using value_type = T;
- using propagate_on_container_copy_assignment = std::true_type;
-
- tracking_allocator(std::vector<void*>& allocs) : allocs_(&allocs) {}
+ typedef T value_type;
+ int foo{0};
+ counting_allocatorT(int f) noexcept : foo(f) {}
+ using propagate_on_container_copy_assignment = std::true_type;
template <class U>
- tracking_allocator(const tracking_allocator<U>& other) : allocs_(other.allocs_) {}
-
- T* allocate(std::size_t n) {
- T* allocation = std::allocator<T>().allocate(n);
- allocs_->push_back(allocation);
- return allocation;
+ counting_allocatorT(const counting_allocatorT<U>& other) noexcept {
+ foo = other.foo;
}
-
- void deallocate(T* ptr, std::size_t n) TEST_NOEXCEPT {
- auto res = std::remove(allocs_->begin(), allocs_->end(), ptr);
- assert(res != allocs_->end() && "Trying to deallocate memory from different allocator?");
- allocs_->erase(res);
- std::allocator<T>().deallocate(ptr, n);
+ template <class U>
+ bool operator==(const counting_allocatorT<U>& other) const noexcept {
+ return foo == other.foo;
}
-
- friend bool operator==(const tracking_allocator& lhs, const tracking_allocator& rhs) {
- return lhs.allocs_ == rhs.allocs_;
+ template <class U>
+ bool operator!=(const counting_allocatorT<U>& other) const noexcept {
+ return foo != other.foo;
}
- friend bool operator!=(const tracking_allocator& lhs, const tracking_allocator& rhs) {
- return lhs.allocs_ != rhs.allocs_;
+ T* allocate(std::size_t n) const {
+ ca_allocs.push_back(foo);
+ void* const pv = ::malloc(n * sizeof(T));
+ return static_cast<T*>(pv);
+ }
+ void deallocate(T* p, std::size_t) const noexcept {
+ ca_deallocs.push_back(foo);
+ free(p);
}
};
-struct NoOp {
- void operator()() {}
-};
-
-template <class Alloc, class AllocatorInvariant = NoOp>
-void test_alloc(const Alloc& lhs_alloc = Alloc(),
- const Alloc& rhs_alloc = Alloc(),
- AllocatorInvariant check_alloc_invariant = NoOp()) {
- { // Test empty/non-empy map combinations
- { // assign from a non-empty container into an empty one
- using V = std::pair<const int, int>;
- using Map = std::map<int, int, std::less<int>, Alloc>;
-
- V arr[] = {V(1, 1), V(2, 3), V(3, 6)};
- const Map orig(begin(arr), end(arr), std::less<int>(), rhs_alloc);
- Map copy(lhs_alloc);
- copy = orig;
- 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());
-
- // 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());
- }
- check_alloc_invariant();
- { // assign from an empty container into an empty one
- using Map = std::map<int, int, std::less<int>, Alloc>;
-
- const Map orig(rhs_alloc);
- Map copy(lhs_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());
- }
- check_alloc_invariant();
- { // assign from an empty container into a non-empty one
- using V = std::pair<const int, int>;
- using Map = std::map<int, int, std::less<int>, Alloc>;
-
- V arr[] = {V(1, 1), V(2, 3), V(3, 6)};
- const Map orig(rhs_alloc);
- Map copy(begin(arr), end(arr), std::less<int>(), rhs_alloc);
- copy = orig;
- assert(copy.size() == 0);
- assert(copy.begin() == copy.end());
+template <class T>
+class counting_allocatorF {
+public:
+ typedef T value_type;
+ int foo{0};
+ counting_allocatorF(int f) noexcept : foo(f) {}
- // Check that orig is still what is expected
- assert(orig.size() == 0);
- assert(orig.begin() == orig.end());
- }
+ using propagate_on_container_copy_assignment = std::false_type;
+ template <class U>
+ counting_allocatorF(const counting_allocatorF<U>& other) noexcept {
+ foo = other.foo;
}
-
- { // Ensure that self-assignment works correctly
- { // with a non-empty map
- using V = std::pair<const int, int>;
- using Map = std::map<int, int, std::less<int>, Alloc>;
-
- V arr[] = {V(1, 1), V(2, 3), V(3, 6)};
- Map orig(begin(arr), end(arr), std::less<int>(), rhs_alloc);
- orig = static_cast<const Map&>(orig);
-
- 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());
- }
- { // with an empty map
- using Map = std::map<int, int, std::less<int>, Alloc>;
-
- Map orig(rhs_alloc);
- orig = static_cast<const Map&>(orig);
-
- assert(orig.size() == 0);
- assert(orig.begin() == orig.end());
- }
+ template <class U>
+ bool operator==(const counting_allocatorF<U>& other) const noexcept {
+ return foo == other.foo;
}
-
- { // check assignment into a non-empty map
- check_alloc_invariant();
- { // LHS already contains elements, but fewer than the RHS
- using V = std::pair<const int, int>;
- using Map = std::map<int, int, std::less<int>, Alloc>;
-
- V lhs_arr[] = {V(1, 1), V(2, 3), V(3, 6)};
- const Map orig(begin(lhs_arr), end(lhs_arr), std::less<int>(), rhs_alloc);
-
- V rhs_arr[] = {V(4, 2), V(5, 1)};
- Map copy(begin(rhs_arr), end(rhs_arr), std::less<int>(), lhs_alloc);
- copy = orig;
- 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());
-
- // 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());
- }
- check_alloc_invariant();
- { // LHS contains the same number of elements as the RHS
- using V = std::pair<const int, int>;
- using Map = std::map<int, int, std::less<int>, Alloc>;
-
- V lhs_arr[] = {V(1, 1), V(2, 3), V(3, 6)};
- const Map orig(begin(lhs_arr), end(lhs_arr), std::less<int>(), rhs_alloc);
-
- V rhs_arr[] = {V(4, 2), V(5, 1), V(6, 0)};
- Map copy(begin(rhs_arr), end(rhs_arr), std::less<int>(), lhs_alloc);
- copy = orig;
- 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());
-
- // 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());
- }
- check_alloc_invariant();
- { // LHS already contains more elements than the RHS
- using V = std::pair<const int, int>;
- using Map = std::map<int, int, std::less<int>, Alloc>;
-
- V lhs_arr[] = {V(1, 1), V(2, 3), V(3, 6)};
- const Map orig(begin(lhs_arr), end(lhs_arr), std::less<int>(), rhs_alloc);
-
- V rhs_arr[] = {V(4, 2), V(5, 1), V(6, 0), V(7, 9)};
- Map copy(begin(rhs_arr), end(rhs_arr), std::less<int>(), lhs_alloc);
- copy = orig;
- 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());
-
- // 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());
- }
- check_alloc_invariant();
+ template <class U>
+ bool operator!=(const counting_allocatorF<U>& other) const noexcept {
+ return foo != other.foo;
}
- { // Make a somewhat larget set to exercise the algorithm a bit
- using V = std::pair<const int, int>;
- using Map = std::map<int, int, std::less<int>, Alloc>;
-
- Map orig(rhs_alloc);
- for (int i = 0; i != 50; ++i)
- orig[i] = i + 3;
- Map copy(lhs_alloc);
- copy = orig;
- int i = 0;
- for (auto v : copy) {
- assert(v == V(i, i + 3));
- ++i;
- }
+ T* allocate(std::size_t n) const {
+ ca_allocs.push_back(foo);
+ void* const pv = ::malloc(n * sizeof(T));
+ return static_cast<T*>(pv);
}
- check_alloc_invariant();
-}
+ void deallocate(T* p, std::size_t) const noexcept {
+ ca_deallocs.push_back(foo);
+ free(p);
+ }
+};
-void test() {
- test_alloc<std::allocator<std::pair<const int, int> > >();
-#if TEST_STD_VER >= 11
- test_alloc<min_allocator<std::pair<const int, int> > >();
+bool balanced_allocs() {
+ std::vector<int> temp1, temp2;
+
+ std::printf("Allocations = %zu, deallocations = %zu\n", ca_allocs.size(), ca_deallocs.size());
+ if (ca_allocs.size() != ca_deallocs.size())
+ return false;
+
+ temp1 = ca_allocs;
+ std::sort(temp1.begin(), temp1.end());
+ temp2.clear();
+ std::unique_copy(temp1.begin(), temp1.end(), std::back_inserter<std::vector<int>>(temp2));
+ std::printf("There were %zu different allocators\n", temp2.size());
+
+ for (std::vector<int>::const_iterator it = temp2.begin(); it != temp2.end(); ++it) {
+ std::ptrdiff_t const allocs = std::count(ca_allocs.begin(), ca_allocs.end(), *it);
+ std::ptrdiff_t const deallocs = std::count(ca_deallocs.begin(), ca_deallocs.end(), *it);
+ std::printf("%d: %td vs %td\n", *it, allocs, deallocs);
+ if (allocs != deallocs)
+ return false;
+ }
- { // Make sure we're allocating/deallocating nodes with the correct allocator
- // See https://llvm.org/PR29001
- class AssertEmpty {
- std::vector<void*>* lhs_allocs_;
- std::vector<void*>* rhs_allocs_;
+ temp1 = ca_allocs;
+ std::sort(temp1.begin(), temp1.end());
+ temp2.clear();
+ std::unique_copy(temp1.begin(), temp1.end(), std::back_inserter<std::vector<int>>(temp2));
+ std::printf("There were %zu different (de)allocators\n", temp2.size());
+
+ for (std::vector<int>::const_iterator it = ca_deallocs.begin(); it != ca_deallocs.end(); ++it) {
+ std::ptrdiff_t const allocs = std::count(ca_allocs.begin(), ca_allocs.end(), *it);
+ std::ptrdiff_t const deallocs = std::count(ca_deallocs.begin(), ca_deallocs.end(), *it);
+ std::printf("%d: %td vs %td\n", *it, allocs, deallocs);
+ if (allocs != deallocs)
+ return false;
+ }
- public:
- AssertEmpty(std::vector<void*>& lhs_allocs, std::vector<void*>& rhs_allocs)
- : lhs_allocs_(&lhs_allocs), rhs_allocs_(&rhs_allocs) {}
+ return true;
+}
+#endif
- void operator()() {
- assert(lhs_allocs_->empty());
- assert(rhs_allocs_->empty());
- }
+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(2));
+ std::map<int, double, C, A> m(ar, ar + sizeof(ar) / sizeof(ar[0]) / 2, C(3), A(7));
+ m = mo;
+ assert(m.get_allocator() == A(7));
+ 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(2));
+ 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));
+ }
+ {
+ typedef std::pair<const int, double> V;
+ const V ar[] = {
+ V(1, 1),
+ V(2, 1),
+ V(3, 1),
};
+ std::map<int, double> m(ar, ar + sizeof(ar) / sizeof(ar[0]));
+ std::map<int, double>* p = &m;
+ m = *p;
- std::vector<void*> lhs_allocs;
- std::vector<void*> rhs_allocs;
- test_alloc<tracking_allocator<std::pair<const int, int> > >(
- lhs_allocs, rhs_allocs, AssertEmpty(lhs_allocs, rhs_allocs));
+ assert(m.size() == 3);
+ assert(std::equal(m.begin(), m.end(), ar));
}
-#endif
-
- { // Ensure that the comparator is copied
- using V = std::pair<const int, int>;
- using Map = std::map<int, int, test_less<int> >;
-
- V arr[] = {V(1, 1), V(2, 3), V(3, 6)};
- const Map orig(begin(arr), end(arr), test_less<int>(3));
- Map copy;
- copy = orig;
- assert(copy.size() == 3);
- assert(copy.key_comp() == test_less<int>(3));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.key_comp() == test_less<int>(3));
+ {
+ 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 other_allocator<V> A;
+ std::map<int, double, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(2));
+ std::map<int, double, C, A> m(ar, ar + sizeof(ar) / sizeof(ar[0]) / 2, C(3), A(7));
+ m = mo;
+ assert(m.get_allocator() == A(2));
+ 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(2));
+ 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));
}
-
- { // Make sure the color is copied as well
- std::map<int, int> in;
-
- for (int i = 0; i != 32; ++i)
- in[i] = i;
-
- std::map<int, int> out = in;
-
- out.erase(std::next(out.begin(), 10), out.end());
- out = in;
- out.erase(std::next(out.begin(), 17), out.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(ar, ar + sizeof(ar) / sizeof(ar[0]) / 2, C(3), A());
+ m = mo;
+ 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));
+ }
+ {
+ 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(ar, ar + sizeof(ar) / sizeof(ar[0]) / 2, C(3), A());
+ m = mo;
+ 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));
}
-}
-int main(int, char**) {
- test();
+ assert(balanced_allocs());
+ {
+ 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 counting_allocatorT<V> A;
+ std::map<int, double, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(1));
+ std::map<int, double, C, A> m(ar, ar + sizeof(ar) / sizeof(ar[0]) / 2, C(3), A(2));
+ m = mo;
+ 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.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));
+ }
+ assert(balanced_allocs());
+ {
+ 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 counting_allocatorF<V> A;
+ std::map<int, double, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(100));
+ std::map<int, double, C, A> m(ar, ar + sizeof(ar) / sizeof(ar[0]) / 2, C(3), A(200));
+ m = mo;
+ 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.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));
+ }
+ assert(balanced_allocs());
+#endif
return 0;
}
diff --git a/libcxx/test/std/containers/associative/multimap/multimap.cons/copy.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.cons/copy.pass.cpp
index 724755d1ef655..9cffbf8c17850 100644
--- a/libcxx/test/std/containers/associative/multimap/multimap.cons/copy.pass.cpp
+++ b/libcxx/test/std/containers/associative/multimap/multimap.cons/copy.pass.cpp
@@ -20,122 +20,81 @@
#include "test_allocator.h"
#include "min_allocator.h"
-template <template <class> class Alloc>
-void test_alloc() {
- { // Simple check
- using V = std::pair<const int, int>;
- using Map = std::multimap<int, int, std::less<int>, Alloc<V> >;
-
- V arr[] = {V(1, 1), V(2, 3), V(2, 6)};
- const Map orig(begin(arr), end(arr));
- Map copy = orig;
- 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(2, 6));
- assert(std::next(copy.begin(), 3) == copy.end());
-
- // 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(2, 6));
- assert(std::next(orig.begin(), 3) == orig.end());
- }
-
- { // copy empty map
- using V = std::pair<const int, int>;
- using Map = std::multimap<int, int, std::less<int>, Alloc<V> >;
-
- const Map orig;
- Map 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>;
- using Map = std::multimap<int, int, std::less<int>, Alloc<V> >;
-
- V arr[] = {V(1, 1), V(2, 3), V(2, 6), V(4, 7), V(5, 0)};
- const Map orig(begin(arr), end(arr));
- Map 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(2, 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(2, 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());
- }
-}
-
-void test() {
- test_alloc<std::allocator>();
- test_alloc<min_allocator>(); // Make sure that fancy pointers work
-
- { // Ensure that the comparator is copied
- using V = std::pair<const int, int>;
- using Map = std::multimap<int, int, test_less<int> >;
-
- V arr[] = {V(1, 1), V(2, 3), V(2, 6)};
- const Map orig(begin(arr), end(arr), test_less<int>(3));
- Map copy = orig;
- assert(copy.size() == 3);
- assert(copy.key_comp() == test_less<int>(3));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.key_comp() == test_less<int>(3));
+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::multimap<int, double, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(7));
+ std::multimap<int, double, C, A> m = mo;
+ assert(m == mo);
+ assert(m.get_allocator() == A(7));
+ assert(m.key_comp() == C(5));
+
+ assert(mo.get_allocator() == A(7));
+ assert(mo.key_comp() == C(5));
}
-
- { // Ensure that the allocator is copied
- using V = std::pair<const int, int>;
- using Map = std::multimap<int, int, std::less<int>, test_allocator<V> >;
-
- V arr[] = {V(1, 1), V(2, 3), V(2, 6)};
- const Map orig(begin(arr), end(arr), std::less<int>(), test_allocator<V>(10));
- Map copy = orig;
- assert(copy.size() == 3);
- assert(copy.get_allocator() == test_allocator<V>(10));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.get_allocator() == test_allocator<V>(10));
- assert(orig.get_allocator().get_id() != test_alloc_base::moved_value);
+#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 other_allocator<V> A;
+ std::multimap<int, double, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(7));
+ std::multimap<int, double, C, A> m = mo;
+ assert(m == mo);
+ assert(m.get_allocator() == A(-2));
+ assert(m.key_comp() == C(5));
+
+ assert(mo.get_allocator() == A(7));
+ assert(mo.key_comp() == C(5));
}
-
- { // Ensure that soccc is handled properly
- using V = std::pair<const int, int>;
- using Map = std::multimap<int, int, std::less<int>, other_allocator<V> >;
-
- V arr[] = {V(1, 1), V(2, 3), V(2, 6)};
- const Map orig(begin(arr), end(arr), std::less<int>(), other_allocator<V>(10));
- Map copy = orig;
- assert(copy.size() == 3);
- assert(copy.get_allocator() == other_allocator<V>(-2));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.get_allocator() == other_allocator<V>(10));
+ {
+ 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::multimap<int, double, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A());
+ std::multimap<int, double, C, A> m = mo;
+ assert(m == mo);
+ assert(m.get_allocator() == A());
+ assert(m.key_comp() == C(5));
+
+ assert(mo.get_allocator() == A());
+ assert(mo.key_comp() == C(5));
}
-}
-
-int main(int, char**) {
- test();
+#endif
return 0;
}
diff --git a/libcxx/test/std/containers/associative/multimap/multimap.cons/copy_alloc.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.cons/copy_alloc.pass.cpp
index 055efaecfca54..89e6c40aa108d 100644
--- a/libcxx/test/std/containers/associative/multimap/multimap.cons/copy_alloc.pass.cpp
+++ b/libcxx/test/std/containers/associative/multimap/multimap.cons/copy_alloc.pass.cpp
@@ -20,92 +20,81 @@
#include "test_allocator.h"
#include "min_allocator.h"
-template <class Alloc>
-void test_alloc(const Alloc& new_alloc) {
- { // Simple check
- using V = std::pair<const int, int>;
- using Map = std::multimap<int, int, std::less<int>, Alloc>;
-
- V arr[] = {V(1, 1), V(2, 3), V(2, 6)};
- const Map orig(begin(arr), end(arr));
- Map 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(2, 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(2, 6));
- assert(std::next(orig.begin(), 3) == orig.end());
- }
-
- { // copy empty map
- using Map = std::multimap<int, int, std::less<int>, Alloc>;
-
- const Map orig;
- Map 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());
+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::multimap<int, double, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(7));
+ std::multimap<int, double, C, A> m(mo, A(3));
+ assert(m == mo);
+ assert(m.get_allocator() == A(3));
+ assert(m.key_comp() == C(5));
+
+ assert(mo.get_allocator() == A(7));
+ assert(mo.key_comp() == C(5));
}
-
- { // only some leaf nodes exist
- using V = std::pair<const int, int>;
- using Map = std::multimap<int, int, std::less<int>, Alloc>;
-
- V arr[] = {V(1, 1), V(2, 3), V(2, 6), V(4, 7), V(5, 0)};
- const Map orig(begin(arr), end(arr));
- Map 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(2, 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(2, 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());
+#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::multimap<int, double, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A());
+ std::multimap<int, double, C, A> m(mo, A());
+ assert(m == mo);
+ assert(m.get_allocator() == A());
+ assert(m.key_comp() == C(5));
+
+ assert(mo.get_allocator() == A());
+ assert(mo.key_comp() == C(5));
}
-}
-
-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 actually used
- test_alloc(min_allocator<std::pair<const int, int> >()); // Make sure that fancy pointers work
-
- { // Ensure that the comparator is copied
- using V = std::pair<const int, int>;
- using Map = std::multimap<int, int, test_less<int> >;
-
- V arr[] = {V(1, 1), V(2, 3), V(2, 6)};
- const Map orig(begin(arr), end(arr), test_less<int>(3));
- Map copy(orig, std::allocator<V>());
- assert(copy.size() == 3);
- assert(copy.key_comp() == test_less<int>(3));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.key_comp() == test_less<int>(3));
+ {
+ 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::multimap<int, double, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A{});
+ std::multimap<int, double, C, A> m(mo, A{});
+ assert(m == mo);
+ assert(m.get_allocator() == A{});
+ assert(m.key_comp() == C(5));
+
+ assert(mo.get_allocator() == A{});
+ assert(mo.key_comp() == C(5));
}
-}
-
-int main(int, char**) {
- test();
+#endif
return 0;
}
diff --git a/libcxx/test/std/containers/associative/multimap/multimap.cons/copy_assign.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.cons/copy_assign.pass.cpp
index 5830283e9b0c5..463403a412aaa 100644
--- a/libcxx/test/std/containers/associative/multimap/multimap.cons/copy_assign.pass.cpp
+++ b/libcxx/test/std/containers/associative/multimap/multimap.cons/copy_assign.pass.cpp
@@ -12,286 +12,111 @@
// multimap& operator=(const multimap& m);
-#include <algorithm>
-#include <cassert>
#include <map>
-#include <vector>
+#include <cassert>
#include "test_macros.h"
#include "../../../test_compare.h"
#include "test_allocator.h"
#include "min_allocator.h"
-template <class T>
-class tracking_allocator {
- std::vector<void*>* allocs_;
-
- template <class U>
- friend class tracking_allocator;
-
-public:
- using value_type = T;
- using propagate_on_container_copy_assignment = std::true_type;
-
- tracking_allocator(std::vector<void*>& allocs) : allocs_(&allocs) {}
-
- template <class U>
- tracking_allocator(const tracking_allocator<U>& other) : allocs_(other.allocs_) {}
-
- T* allocate(std::size_t n) {
- T* allocation = std::allocator<T>().allocate(n);
- allocs_->push_back(allocation);
- return allocation;
- }
-
- void deallocate(T* ptr, std::size_t n) TEST_NOEXCEPT {
- auto res = std::remove(allocs_->begin(), allocs_->end(), ptr);
- assert(res != allocs_->end() && "Trying to deallocate memory from different allocator?");
- allocs_->erase(res);
- std::allocator<T>().deallocate(ptr, n);
- }
-
- friend bool operator==(const tracking_allocator& lhs, const tracking_allocator& rhs) {
- return lhs.allocs_ == rhs.allocs_;
- }
-
- friend bool operator!=(const tracking_allocator& lhs, const tracking_allocator& rhs) {
- return lhs.allocs_ != rhs.allocs_;
- }
-};
-
-struct NoOp {
- void operator()() {}
-};
-
-template <class Alloc, class AllocatorInvariant = NoOp>
-void test_alloc(const Alloc& lhs_alloc = Alloc(),
- const Alloc& rhs_alloc = Alloc(),
- AllocatorInvariant check_alloc_invariant = NoOp()) {
- { // Test empty/non-empy multimap combinations
- { // assign from a non-empty container into an empty one
- using V = std::pair<const int, int>;
- using Map = std::multimap<int, int, std::less<int>, Alloc>;
-
- V arr[] = {V(1, 1), V(2, 3), V(2, 6)};
- const Map orig(begin(arr), end(arr), std::less<int>(), rhs_alloc);
- Map copy(lhs_alloc);
- copy = orig;
- 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(2, 6));
- assert(std::next(copy.begin(), 3) == copy.end());
-
- // 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(2, 6));
- assert(std::next(orig.begin(), 3) == orig.end());
- }
- check_alloc_invariant();
- { // assign from an empty container into an empty one
- using Map = std::multimap<int, int, std::less<int>, Alloc>;
-
- const Map orig(rhs_alloc);
- Map copy(lhs_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());
- }
- check_alloc_invariant();
- { // assign from an empty container into a non-empty one
- using V = std::pair<const int, int>;
- using Map = std::multimap<int, int, std::less<int>, Alloc>;
-
- V arr[] = {V(1, 1), V(2, 3), V(2, 6)};
- const Map orig(rhs_alloc);
- Map copy(begin(arr), end(arr), std::less<int>(), rhs_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());
- }
- }
-
- { // Ensure that self-assignment works correctly
- { // with a non-empty multimap
- using V = std::pair<const int, int>;
- using Map = std::multimap<int, int, std::less<int>, Alloc>;
-
- V arr[] = {V(1, 1), V(2, 3), V(2, 6)};
- Map orig(begin(arr), end(arr), std::less<int>(), rhs_alloc);
- orig = static_cast<const Map&>(orig);
-
- 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(2, 6));
- assert(std::next(orig.begin(), 3) == orig.end());
- }
- { // with an empty multimap
- using Map = std::multimap<int, int, std::less<int>, Alloc>;
-
- Map orig(rhs_alloc);
- orig = static_cast<const Map&>(orig);
-
- assert(orig.size() == 0);
- assert(orig.begin() == orig.end());
- }
+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::multimap<int, double, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(2));
+ std::multimap<int, double, C, A> m(ar, ar + sizeof(ar) / sizeof(ar[0]) / 2, C(3), A(7));
+ m = mo;
+ assert(m == mo);
+ assert(m.get_allocator() == A(7));
+ assert(m.key_comp() == C(5));
+
+ assert(mo.get_allocator() == A(2));
+ assert(mo.key_comp() == C(5));
}
-
- { // check assignment into a non-empty multimap
- check_alloc_invariant();
- { // LHS already contains elements, but fewer than the RHS
- using V = std::pair<const int, int>;
- using Map = std::multimap<int, int, std::less<int>, Alloc>;
-
- V lhs_arr[] = {V(1, 1), V(2, 3), V(2, 6)};
- const Map orig(begin(lhs_arr), end(lhs_arr), std::less<int>(), rhs_alloc);
-
- V rhs_arr[] = {V(4, 2), V(5, 1)};
- Map copy(begin(rhs_arr), end(rhs_arr), std::less<int>(), lhs_alloc);
- copy = orig;
- 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(2, 6));
- assert(std::next(copy.begin(), 3) == copy.end());
-
- // 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(2, 6));
- assert(std::next(orig.begin(), 3) == orig.end());
- }
- check_alloc_invariant();
- { // LHS contains the same number of elements as the RHS
- using V = std::pair<const int, int>;
- using Map = std::multimap<int, int, std::less<int>, Alloc>;
-
- V lhs_arr[] = {V(1, 1), V(2, 3), V(2, 6)};
- const Map orig(begin(lhs_arr), end(lhs_arr), std::less<int>(), rhs_alloc);
-
- V rhs_arr[] = {V(4, 2), V(5, 1), V(6, 0)};
- Map copy(begin(rhs_arr), end(rhs_arr), std::less<int>(), lhs_alloc);
- copy = orig;
- 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(2, 6));
- assert(std::next(copy.begin(), 3) == copy.end());
-
- // 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(2, 6));
- assert(std::next(orig.begin(), 3) == orig.end());
- }
- check_alloc_invariant();
- { // LHS already contains more elements than the RHS
- using V = std::pair<const int, int>;
- using Map = std::multimap<int, int, std::less<int>, Alloc>;
-
- V lhs_arr[] = {V(1, 1), V(2, 3), V(2, 6)};
- const Map orig(begin(lhs_arr), end(lhs_arr), std::less<int>(), rhs_alloc);
-
- V rhs_arr[] = {V(4, 2), V(5, 1), V(6, 0), V(7, 9)};
- Map copy(begin(rhs_arr), end(rhs_arr), std::less<int>(), lhs_alloc);
- copy = orig;
- 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(2, 6));
- assert(std::next(copy.begin(), 3) == copy.end());
-
- // 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(2, 6));
- assert(std::next(orig.begin(), 3) == orig.end());
- }
- check_alloc_invariant();
+ {
+ typedef std::pair<const int, double> V;
+ const 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),
+ };
+ std::multimap<int, double> m(ar, ar + sizeof(ar) / sizeof(ar[0]));
+ std::multimap<int, double>* p = &m;
+ m = *p;
+ assert(m.size() == sizeof(ar) / sizeof(ar[0]));
+ assert(std::equal(m.begin(), m.end(), ar));
}
- { // Make a somewhat larget set to exercise the algorithm a bit
- using V = std::pair<const int, int>;
- using Map = std::multimap<int, int, std::less<int>, Alloc>;
-
- Map orig(rhs_alloc);
- for (int i = 0; i != 50; ++i) {
- orig.insert(V(i, i + 3));
- orig.insert(V(i, i + 5));
- }
-
- Map copy(lhs_alloc);
- copy = orig;
- int i = 0;
- for (auto iter = copy.begin(); iter != copy.end();) {
- assert(*iter++ == V(i, i + 3));
- assert(*iter++ == V(i, i + 5));
- ++i;
- }
+ {
+ 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 other_allocator<V> A;
+ std::multimap<int, double, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(2));
+ std::multimap<int, double, C, A> m(ar, ar + sizeof(ar) / sizeof(ar[0]) / 2, C(3), A(7));
+ m = mo;
+ assert(m == mo);
+ assert(m.get_allocator() == A(2));
+ assert(m.key_comp() == C(5));
+
+ assert(mo.get_allocator() == A(2));
+ assert(mo.key_comp() == C(5));
}
- check_alloc_invariant();
-}
-
-void test() {
- test_alloc<std::allocator<std::pair<const int, int> > >();
#if TEST_STD_VER >= 11
- test_alloc<min_allocator<std::pair<const int, int> > >();
-
- { // Make sure we're allocating/deallocating nodes with the correct allocator
- // See https://llvm.org/PR29001
- class AssertEmpty {
- std::vector<void*>* lhs_allocs_;
- std::vector<void*>* rhs_allocs_;
-
- public:
- AssertEmpty(std::vector<void*>& lhs_allocs, std::vector<void*>& rhs_allocs)
- : lhs_allocs_(&lhs_allocs), rhs_allocs_(&rhs_allocs) {}
-
- void operator()() {
- assert(lhs_allocs_->empty());
- assert(rhs_allocs_->empty());
- }
+ {
+ 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),
};
-
- std::vector<void*> lhs_allocs;
- std::vector<void*> rhs_allocs;
- test_alloc<tracking_allocator<std::pair<const int, int> > >(
- lhs_allocs, rhs_allocs, AssertEmpty(lhs_allocs, rhs_allocs));
+ typedef test_less<int> C;
+ typedef min_allocator<V> A;
+ std::multimap<int, double, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A());
+ std::multimap<int, double, C, A> m(ar, ar + sizeof(ar) / sizeof(ar[0]) / 2, C(3), A());
+ m = mo;
+ assert(m == mo);
+ assert(m.get_allocator() == A());
+ assert(m.key_comp() == C(5));
+
+ assert(mo.get_allocator() == A());
+ assert(mo.key_comp() == C(5));
}
#endif
- { // Ensure that the comparator is copied
- using V = std::pair<const int, int>;
- using Map = std::multimap<int, int, test_less<int> >;
-
- V arr[] = {V(1, 1), V(2, 3), V(2, 6)};
- const Map orig(begin(arr), end(arr), test_less<int>(3));
- Map copy;
- copy = orig;
- assert(copy.size() == 3);
- assert(copy.key_comp() == test_less<int>(3));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.key_comp() == test_less<int>(3));
- }
-}
-
-int main(int, char**) {
- test();
-
return 0;
}
diff --git a/libcxx/test/std/containers/associative/multiset/multiset.cons/copy.pass.cpp b/libcxx/test/std/containers/associative/multiset/multiset.cons/copy.pass.cpp
index c747828aa01cc..8138227128e8a 100644
--- a/libcxx/test/std/containers/associative/multiset/multiset.cons/copy.pass.cpp
+++ b/libcxx/test/std/containers/associative/multiset/multiset.cons/copy.pass.cpp
@@ -16,121 +16,83 @@
#include <cassert>
#include <iterator>
-#include "min_allocator.h"
#include "test_macros.h"
#include "../../../test_compare.h"
#include "test_allocator.h"
-template <template <class> class Alloc>
-void test_alloc() {
- { // Simple check
- using Set = std::multiset<int, std::less<int>, Alloc<int> >;
-
- int arr[] = {1, 2, 2};
- const Set orig(std::begin(arr), std::end(arr));
- Set copy = orig;
- assert(copy.size() == 3);
- assert(*std::next(copy.begin(), 0) == 1);
- assert(*std::next(copy.begin(), 1) == 2);
- assert(*std::next(copy.begin(), 2) == 2);
- assert(std::next(copy.begin(), 3) == copy.end());
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(*std::next(orig.begin(), 0) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 2);
- assert(std::next(orig.begin(), 3) == orig.end());
- }
-
- { // copy empty set
- using Set = std::multiset<int, std::less<int>, Alloc<int> >;
-
- const Set orig;
- Set 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 Set = std::multiset<int, std::less<int>, Alloc<int> >;
-
- int arr[] = {1, 2, 3, 3, 5};
- const Set orig(std::begin(arr), std::end(arr));
- Set copy = orig;
- assert(copy.size() == 5);
- assert(*std::next(copy.begin(), 0) == 1);
- assert(*std::next(copy.begin(), 1) == 2);
- assert(*std::next(copy.begin(), 2) == 3);
- assert(*std::next(copy.begin(), 3) == 3);
- assert(*std::next(copy.begin(), 4) == 5);
- 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) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 3);
- assert(*std::next(orig.begin(), 3) == 3);
- assert(*std::next(orig.begin(), 4) == 5);
- assert(std::next(orig.begin(), 5) == orig.end());
- }
-}
-
-void test() {
- test_alloc<std::allocator>();
- test_alloc<min_allocator>(); // Make sure that fancy pointers work
-
- { // Ensure that the comparator is copied
- using Set = std::multiset<int, test_less<int> >;
-
- int arr[] = {1, 2, 2};
- const Set orig(std::begin(arr), std::end(arr), test_less<int>(3));
- Set copy = orig;
- assert(copy.size() == 3);
- assert(copy.key_comp() == test_less<int>(3));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.key_comp() == test_less<int>(3));
+int main(int, char**) {
+ {
+ typedef int V;
+ V ar[] = {1, 1, 1, 2, 2, 2, 3, 3, 3};
+ typedef test_less<int> C;
+ typedef test_allocator<V> A;
+ std::multiset<int, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(7));
+ std::multiset<int, C, A> m = mo;
+ assert(m.get_allocator() == A(7));
+ assert(m.key_comp() == C(5));
+ assert(m.size() == 9);
+ assert(std::distance(m.begin(), m.end()) == 9);
+ assert(*std::next(m.begin(), 0) == 1);
+ assert(*std::next(m.begin(), 1) == 1);
+ assert(*std::next(m.begin(), 2) == 1);
+ assert(*std::next(m.begin(), 3) == 2);
+ assert(*std::next(m.begin(), 4) == 2);
+ assert(*std::next(m.begin(), 5) == 2);
+ assert(*std::next(m.begin(), 6) == 3);
+ assert(*std::next(m.begin(), 7) == 3);
+ assert(*std::next(m.begin(), 8) == 3);
+
+ assert(mo.get_allocator() == A(7));
+ assert(mo.key_comp() == C(5));
+ assert(mo.size() == 9);
+ assert(std::distance(mo.begin(), mo.end()) == 9);
+ assert(*std::next(mo.begin(), 0) == 1);
+ assert(*std::next(mo.begin(), 1) == 1);
+ assert(*std::next(mo.begin(), 2) == 1);
+ assert(*std::next(mo.begin(), 3) == 2);
+ assert(*std::next(mo.begin(), 4) == 2);
+ assert(*std::next(mo.begin(), 5) == 2);
+ assert(*std::next(mo.begin(), 6) == 3);
+ assert(*std::next(mo.begin(), 7) == 3);
+ assert(*std::next(mo.begin(), 8) == 3);
}
-
- { // Ensure that the allocator is copied
- using Set = std::multiset<int, std::less<int>, test_allocator<int> >;
-
- int arr[] = {1, 2, 2};
- const Set orig(std::begin(arr), std::end(arr), std::less<int>(), test_allocator<int>(10));
- Set copy = orig;
- assert(copy.size() == 3);
- assert(copy.get_allocator() == test_allocator<int>(10));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.get_allocator() == test_allocator<int>(10));
- assert(orig.get_allocator().get_id() != test_alloc_base::moved_value);
+#if TEST_STD_VER >= 11
+ {
+ typedef int V;
+ V ar[] = {1, 1, 1, 2, 2, 2, 3, 3, 3};
+ typedef test_less<int> C;
+ typedef other_allocator<V> A;
+ std::multiset<int, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(7));
+ std::multiset<int, C, A> m = mo;
+ assert(m.get_allocator() == A(-2));
+ assert(m.key_comp() == C(5));
+ assert(m.size() == 9);
+ assert(std::distance(m.begin(), m.end()) == 9);
+ assert(*std::next(m.begin(), 0) == 1);
+ assert(*std::next(m.begin(), 1) == 1);
+ assert(*std::next(m.begin(), 2) == 1);
+ assert(*std::next(m.begin(), 3) == 2);
+ assert(*std::next(m.begin(), 4) == 2);
+ assert(*std::next(m.begin(), 5) == 2);
+ assert(*std::next(m.begin(), 6) == 3);
+ assert(*std::next(m.begin(), 7) == 3);
+ assert(*std::next(m.begin(), 8) == 3);
+
+ assert(mo.get_allocator() == A(7));
+ assert(mo.key_comp() == C(5));
+ assert(mo.size() == 9);
+ assert(std::distance(mo.begin(), mo.end()) == 9);
+ assert(*std::next(mo.begin(), 0) == 1);
+ assert(*std::next(mo.begin(), 1) == 1);
+ assert(*std::next(mo.begin(), 2) == 1);
+ assert(*std::next(mo.begin(), 3) == 2);
+ assert(*std::next(mo.begin(), 4) == 2);
+ assert(*std::next(mo.begin(), 5) == 2);
+ assert(*std::next(mo.begin(), 6) == 3);
+ assert(*std::next(mo.begin(), 7) == 3);
+ assert(*std::next(mo.begin(), 8) == 3);
}
-
- { // Ensure that soccc is handled properly
- using Set = std::multiset<int, std::less<int>, other_allocator<int> >;
-
- int arr[] = {1, 2, 2};
- const Set orig(std::begin(arr), std::end(arr), std::less<int>(), other_allocator<int>(10));
- Set copy = orig;
- assert(copy.size() == 3);
- assert(copy.get_allocator() == other_allocator<int>(-2));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.get_allocator() == other_allocator<int>(10));
- }
-}
-
-int main(int, char**) {
- test();
+#endif
return 0;
}
diff --git a/libcxx/test/std/containers/associative/multiset/multiset.cons/copy_alloc.pass.cpp b/libcxx/test/std/containers/associative/multiset/multiset.cons/copy_alloc.pass.cpp
index 868072ef15288..7570673066829 100644
--- a/libcxx/test/std/containers/associative/multiset/multiset.cons/copy_alloc.pass.cpp
+++ b/libcxx/test/std/containers/associative/multiset/multiset.cons/copy_alloc.pass.cpp
@@ -16,92 +16,44 @@
#include <cassert>
#include <iterator>
-#include "min_allocator.h"
#include "test_macros.h"
#include "../../../test_compare.h"
#include "test_allocator.h"
-template <class Alloc>
-void test_alloc(const Alloc& new_alloc) {
- { // Simple check
- using Set = std::multiset<int, std::less<int>, Alloc>;
-
- int arr[] = {1, 2, 2};
- const Set orig(std::begin(arr), std::end(arr));
- Set copy(orig, new_alloc);
- assert(copy.size() == 3);
- assert(*std::next(copy.begin(), 0) == 1);
- assert(*std::next(copy.begin(), 1) == 2);
- assert(*std::next(copy.begin(), 2) == 2);
- 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) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 2);
- assert(std::next(orig.begin(), 3) == orig.end());
- }
-
- { // copy empty set
- using Set = std::multiset<int, std::less<int>, Alloc>;
-
- const Set orig;
- Set 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 Set = std::multiset<int, std::less<int>, Alloc>;
-
- int arr[] = {1, 2, 3, 3, 5};
- const Set orig(std::begin(arr), std::end(arr));
- Set copy = orig;
- assert(copy.size() == 5);
- assert(*std::next(copy.begin(), 0) == 1);
- assert(*std::next(copy.begin(), 1) == 2);
- assert(*std::next(copy.begin(), 2) == 3);
- assert(*std::next(copy.begin(), 3) == 3);
- assert(*std::next(copy.begin(), 4) == 5);
- 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) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 3);
- assert(*std::next(orig.begin(), 3) == 3);
- assert(*std::next(orig.begin(), 4) == 5);
- assert(std::next(orig.begin(), 5) == orig.end());
- }
-}
-
-void test() {
- test_alloc(std::allocator<int>());
- test_alloc(test_allocator<int>(25)); // Make sure that the new allocator is actually used
- test_alloc(min_allocator<int>()); // Make sure that fancy pointers work
-
- { // Ensure that the comparator is copied
- int arr[] = {1, 2, 2};
- const std::multiset<int, test_less<int> > orig(std::begin(arr), std::end(arr), test_less<int>(3));
- std::multiset<int, test_less<int> > copy(orig, std::allocator<int>());
- assert(copy.size() == 3);
- assert(copy.key_comp() == test_less<int>(3));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.key_comp() == test_less<int>(3));
- }
-}
-
int main(int, char**) {
- test();
+ typedef int V;
+ V ar[] = {1, 1, 1, 2, 2, 2, 3, 3, 3};
+ typedef test_less<int> C;
+ typedef test_allocator<V> A;
+ std::multiset<int, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(7));
+ std::multiset<int, C, A> m(mo, A(3));
+ assert(m.get_allocator() == A(3));
+ assert(m.key_comp() == C(5));
+ assert(m.size() == 9);
+ assert(std::distance(m.begin(), m.end()) == 9);
+ assert(*std::next(m.begin(), 0) == 1);
+ assert(*std::next(m.begin(), 1) == 1);
+ assert(*std::next(m.begin(), 2) == 1);
+ assert(*std::next(m.begin(), 3) == 2);
+ assert(*std::next(m.begin(), 4) == 2);
+ assert(*std::next(m.begin(), 5) == 2);
+ assert(*std::next(m.begin(), 6) == 3);
+ assert(*std::next(m.begin(), 7) == 3);
+ assert(*std::next(m.begin(), 8) == 3);
+
+ assert(mo.get_allocator() == A(7));
+ assert(mo.key_comp() == C(5));
+ assert(mo.size() == 9);
+ assert(std::distance(mo.begin(), mo.end()) == 9);
+ assert(*std::next(mo.begin(), 0) == 1);
+ assert(*std::next(mo.begin(), 1) == 1);
+ assert(*std::next(mo.begin(), 2) == 1);
+ assert(*std::next(mo.begin(), 3) == 2);
+ assert(*std::next(mo.begin(), 4) == 2);
+ assert(*std::next(mo.begin(), 5) == 2);
+ assert(*std::next(mo.begin(), 6) == 3);
+ assert(*std::next(mo.begin(), 7) == 3);
+ assert(*std::next(mo.begin(), 8) == 3);
return 0;
}
diff --git a/libcxx/test/std/containers/associative/multiset/multiset.cons/copy_assign.pass.cpp b/libcxx/test/std/containers/associative/multiset/multiset.cons/copy_assign.pass.cpp
index 8511f05ab57e4..d6b394ff66698 100644
--- a/libcxx/test/std/containers/associative/multiset/multiset.cons/copy_assign.pass.cpp
+++ b/libcxx/test/std/containers/associative/multiset/multiset.cons/copy_assign.pass.cpp
@@ -12,271 +12,96 @@
// multiset& operator=(const multiset& s);
-#include <algorithm>
+#include <set>
#include <cassert>
#include <iterator>
-#include <set>
-#include <vector>
-#include "../../../test_compare.h"
-#include "min_allocator.h"
#include "test_macros.h"
+#include "../../../test_compare.h"
+#include "test_allocator.h"
-template <class T>
-class tracking_allocator {
- std::vector<void*>* allocs_;
-
- template <class U>
- friend class tracking_allocator;
-
-public:
- using value_type = T;
- using propagate_on_container_copy_assignment = std::true_type;
-
- tracking_allocator(std::vector<void*>& allocs) : allocs_(&allocs) {}
-
- template <class U>
- tracking_allocator(const tracking_allocator<U>& other) : allocs_(other.allocs_) {}
-
- T* allocate(std::size_t n) {
- T* allocation = std::allocator<T>().allocate(n);
- allocs_->push_back(allocation);
- return allocation;
- }
-
- void deallocate(T* ptr, std::size_t n) TEST_NOEXCEPT {
- auto res = std::remove(allocs_->begin(), allocs_->end(), ptr);
- assert(res != allocs_->end() && "Trying to deallocate memory from different allocator?");
- allocs_->erase(res);
- std::allocator<T>().deallocate(ptr, n);
- }
-
- friend bool operator==(const tracking_allocator& lhs, const tracking_allocator& rhs) {
- return lhs.allocs_ == rhs.allocs_;
- }
-
- friend bool operator!=(const tracking_allocator& lhs, const tracking_allocator& rhs) {
- return lhs.allocs_ != rhs.allocs_;
- }
-};
-
-struct NoOp {
- void operator()() {}
-};
-
-template <class Alloc, class AllocatorInvariant = NoOp>
-void test_alloc(const Alloc& lhs_alloc = Alloc(),
- const Alloc& rhs_alloc = Alloc(),
- AllocatorInvariant check_alloc_invariant = NoOp()) {
- { // Test empty/non-empy multiset combinations
- { // assign from a non-empty container into an empty one
- using Set = std::multiset<int, std::less<int>, Alloc>;
-
- int arr[] = {1, 2, 2};
- const Set orig(std::begin(arr), std::end(arr), std::less<int>(), rhs_alloc);
- Set copy(lhs_alloc);
- copy = orig;
- assert(copy.size() == 3);
- assert(*std::next(copy.begin(), 0) == 1);
- assert(*std::next(copy.begin(), 1) == 2);
- assert(*std::next(copy.begin(), 2) == 2);
- assert(std::next(copy.begin(), 3) == copy.end());
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(*std::next(orig.begin(), 0) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 2);
- assert(std::next(orig.begin(), 3) == orig.end());
- }
- check_alloc_invariant();
- { // assign from an empty container into an empty one
- using Set = std::multiset<int, std::less<int>, Alloc>;
-
- const Set orig(rhs_alloc);
- Set copy(lhs_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());
- }
- check_alloc_invariant();
- { // assign from an empty container into a non-empty one
- using Set = std::multiset<int, std::less<int>, Alloc>;
-
- int arr[] = {1, 2, 2};
- const Set orig(rhs_alloc);
- Set copy(std::begin(arr), std::end(arr), std::less<int>(), rhs_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());
- }
- }
-
- { // Ensure that self-assignment works correctly
- { // with a non-empty multiset
- using Set = std::multiset<int, std::less<int>, Alloc>;
-
- int arr[] = {1, 2, 2};
- Set orig(std::begin(arr), std::end(arr), std::less<int>(), rhs_alloc);
- orig = static_cast<const Set&>(orig);
-
- assert(orig.size() == 3);
- assert(*std::next(orig.begin(), 0) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 2);
- assert(std::next(orig.begin(), 3) == orig.end());
- }
- { // with an empty multiset
- using Set = std::multiset<int, std::less<int>, Alloc>;
-
- Set orig(rhs_alloc);
- orig = static_cast<const Set&>(orig);
-
- assert(orig.size() == 0);
- assert(orig.begin() == orig.end());
- }
- }
-
- { // check assignment into a non-empty multiset
- check_alloc_invariant();
- { // LHS already contains elements, but fewer than the RHS
- using Set = std::multiset<int, std::less<int>, Alloc>;
-
- int lhs_arr[] = {1, 2, 2};
- const Set orig(std::begin(lhs_arr), std::end(lhs_arr), std::less<int>(), rhs_alloc);
-
- int rhs_arr[] = {4, 5};
- Set copy(std::begin(rhs_arr), std::end(rhs_arr), std::less<int>(), lhs_alloc);
- copy = orig;
- assert(copy.size() == 3);
- assert(*std::next(copy.begin(), 0) == 1);
- assert(*std::next(copy.begin(), 1) == 2);
- assert(*std::next(copy.begin(), 2) == 2);
- assert(std::next(copy.begin(), 3) == copy.end());
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(*std::next(orig.begin(), 0) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 2);
- assert(std::next(orig.begin(), 3) == orig.end());
- }
- check_alloc_invariant();
- { // LHS contains the same number of elements as the RHS
- using Set = std::multiset<int, std::less<int>, Alloc>;
-
- int lhs_arr[] = {1, 2, 2};
- const Set orig(std::begin(lhs_arr), std::end(lhs_arr), std::less<int>(), rhs_alloc);
-
- int rhs_arr[] = {4, 5, 6};
- Set copy(std::begin(rhs_arr), std::end(rhs_arr), std::less<int>(), lhs_alloc);
- copy = orig;
- assert(copy.size() == 3);
- assert(*std::next(copy.begin(), 0) == 1);
- assert(*std::next(copy.begin(), 1) == 2);
- assert(*std::next(copy.begin(), 2) == 2);
- assert(std::next(copy.begin(), 3) == copy.end());
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(*std::next(orig.begin(), 0) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 2);
- assert(std::next(orig.begin(), 3) == orig.end());
- }
- check_alloc_invariant();
- { // LHS already contains more elements than the RHS
- using Set = std::multiset<int, std::less<int>, Alloc>;
-
- int lhs_arr[] = {1, 2, 2};
- const Set orig(std::begin(lhs_arr), std::end(lhs_arr), std::less<int>(), rhs_alloc);
-
- int rhs_arr[] = {4, 5, 6};
- Set copy(std::begin(rhs_arr), std::end(rhs_arr), std::less<int>(), lhs_alloc);
- copy = orig;
- assert(copy.size() == 3);
- assert(*std::next(copy.begin(), 0) == 1);
- assert(*std::next(copy.begin(), 1) == 2);
- assert(*std::next(copy.begin(), 2) == 2);
- assert(std::next(copy.begin(), 3) == copy.end());
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(*std::next(orig.begin(), 0) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 2);
- assert(std::next(orig.begin(), 3) == orig.end());
- }
- check_alloc_invariant();
- { // Make a somewhat larget multiset to exercise the algorithm a bit
- using Set = std::multiset<int, std::less<int>, Alloc>;
-
- Set orig(rhs_alloc);
- for (int i = 0; i != 50; ++i)
- orig.insert(i);
-
- Set copy(lhs_alloc);
- copy = orig;
- int i = 0;
- for (auto v : copy) {
- assert(v == i++);
- }
- }
- check_alloc_invariant();
+int main(int, char**) {
+ {
+ typedef int V;
+ V ar[] = {1, 1, 1, 2, 2, 2, 3, 3, 3};
+ typedef test_less<int> C;
+ typedef test_allocator<V> A;
+ std::multiset<int, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(2));
+ std::multiset<int, C, A> m(ar, ar + sizeof(ar) / sizeof(ar[0]) / 2, C(3), A(7));
+ m = mo;
+ assert(m.get_allocator() == A(7));
+ assert(m.key_comp() == C(5));
+ assert(m.size() == 9);
+ assert(std::distance(m.begin(), m.end()) == 9);
+ assert(*std::next(m.begin(), 0) == 1);
+ assert(*std::next(m.begin(), 1) == 1);
+ assert(*std::next(m.begin(), 2) == 1);
+ assert(*std::next(m.begin(), 3) == 2);
+ assert(*std::next(m.begin(), 4) == 2);
+ assert(*std::next(m.begin(), 5) == 2);
+ assert(*std::next(m.begin(), 6) == 3);
+ assert(*std::next(m.begin(), 7) == 3);
+ assert(*std::next(m.begin(), 8) == 3);
+
+ assert(mo.get_allocator() == A(2));
+ assert(mo.key_comp() == C(5));
+ assert(mo.size() == 9);
+ assert(std::distance(mo.begin(), mo.end()) == 9);
+ assert(*std::next(mo.begin(), 0) == 1);
+ assert(*std::next(mo.begin(), 1) == 1);
+ assert(*std::next(mo.begin(), 2) == 1);
+ assert(*std::next(mo.begin(), 3) == 2);
+ assert(*std::next(mo.begin(), 4) == 2);
+ assert(*std::next(mo.begin(), 5) == 2);
+ assert(*std::next(mo.begin(), 6) == 3);
+ assert(*std::next(mo.begin(), 7) == 3);
+ assert(*std::next(mo.begin(), 8) == 3);
}
-}
-
-void test() {
- test_alloc<std::allocator<int> >();
-#if TEST_STD_VER >= 11
- test_alloc<min_allocator<int> >();
-
- { // Make sure we're allocating/deallocating nodes with the correct allocator
- // See https://llvm.org/PR29001
- class AssertEmpty {
- std::vector<void*>* lhs_allocs_;
- std::vector<void*>* rhs_allocs_;
-
- public:
- AssertEmpty(std::vector<void*>& lhs_allocs, std::vector<void*>& rhs_allocs)
- : lhs_allocs_(&lhs_allocs), rhs_allocs_(&rhs_allocs) {}
-
- void operator()() {
- assert(lhs_allocs_->empty());
- assert(rhs_allocs_->empty());
- }
- };
-
- std::vector<void*> lhs_allocs;
- std::vector<void*> rhs_allocs;
- test_alloc<tracking_allocator<int> >(lhs_allocs, rhs_allocs, AssertEmpty(lhs_allocs, rhs_allocs));
+ {
+ typedef int V;
+ const V ar[] = {1, 1, 1, 2, 2, 2, 3, 3, 3};
+ std::multiset<int> m(ar, ar + sizeof(ar) / sizeof(ar[0]));
+ std::multiset<int>* p = &m;
+ m = *p;
+ assert(m.size() == 9);
+ assert(std::equal(m.begin(), m.end(), ar));
}
-#endif
-
- { // Ensure that the comparator is copied
- int arr[] = {1, 2, 2};
- const std::multiset<int, test_less<int> > orig(std::begin(arr), std::end(arr), test_less<int>(3));
- std::multiset<int, test_less<int> > copy;
- copy = orig;
- assert(copy.size() == 3);
- assert(copy.key_comp() == test_less<int>(3));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.key_comp() == test_less<int>(3));
+ {
+ typedef int V;
+ V ar[] = {1, 1, 1, 2, 2, 2, 3, 3, 3};
+ typedef test_less<int> C;
+ typedef other_allocator<V> A;
+ std::multiset<int, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(2));
+ std::multiset<int, C, A> m(ar, ar + sizeof(ar) / sizeof(ar[0]) / 2, C(3), A(7));
+ m = mo;
+ assert(m.get_allocator() == A(2));
+ assert(m.key_comp() == C(5));
+ assert(m.size() == 9);
+ assert(std::distance(m.begin(), m.end()) == 9);
+ assert(*std::next(m.begin(), 0) == 1);
+ assert(*std::next(m.begin(), 1) == 1);
+ assert(*std::next(m.begin(), 2) == 1);
+ assert(*std::next(m.begin(), 3) == 2);
+ assert(*std::next(m.begin(), 4) == 2);
+ assert(*std::next(m.begin(), 5) == 2);
+ assert(*std::next(m.begin(), 6) == 3);
+ assert(*std::next(m.begin(), 7) == 3);
+ assert(*std::next(m.begin(), 8) == 3);
+
+ assert(mo.get_allocator() == A(2));
+ assert(mo.key_comp() == C(5));
+ assert(mo.size() == 9);
+ assert(std::distance(mo.begin(), mo.end()) == 9);
+ assert(*std::next(mo.begin(), 0) == 1);
+ assert(*std::next(mo.begin(), 1) == 1);
+ assert(*std::next(mo.begin(), 2) == 1);
+ assert(*std::next(mo.begin(), 3) == 2);
+ assert(*std::next(mo.begin(), 4) == 2);
+ assert(*std::next(mo.begin(), 5) == 2);
+ assert(*std::next(mo.begin(), 6) == 3);
+ assert(*std::next(mo.begin(), 7) == 3);
+ assert(*std::next(mo.begin(), 8) == 3);
}
-}
-
-int main(int, char**) {
- test();
return 0;
}
diff --git a/libcxx/test/std/containers/associative/set/set.cons/copy.pass.cpp b/libcxx/test/std/containers/associative/set/set.cons/copy.pass.cpp
index 8fac335175c80..01a1b6ab59af0 100644
--- a/libcxx/test/std/containers/associative/set/set.cons/copy.pass.cpp
+++ b/libcxx/test/std/containers/associative/set/set.cons/copy.pass.cpp
@@ -12,123 +12,63 @@
// set(const set& m);
-#include <cassert>
#include <set>
+#include <cassert>
+#include <iterator>
-#include "min_allocator.h"
+#include "test_macros.h"
#include "../../../test_compare.h"
#include "test_allocator.h"
-template <template <class> class Alloc>
-void test_alloc() {
- { // Simple check
- using Set = std::set<int, std::less<int>, Alloc<int> >;
-
- int arr[] = {1, 2, 3};
- const Set orig(std::begin(arr), std::end(arr));
- Set copy = orig;
- assert(copy.size() == 3);
- assert(*std::next(copy.begin(), 0) == 1);
- assert(*std::next(copy.begin(), 1) == 2);
- assert(*std::next(copy.begin(), 2) == 3);
- assert(std::next(copy.begin(), 3) == copy.end());
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(*std::next(orig.begin(), 0) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 3);
- assert(std::next(orig.begin(), 3) == orig.end());
- }
-
- { // copy empty set
- using Set = std::set<int, std::less<int>, Alloc<int> >;
-
- const Set orig;
- Set 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 Set = std::set<int, std::less<int>, Alloc<int> >;
-
- int arr[] = {1, 2, 3, 4, 5};
- const Set orig(std::begin(arr), std::end(arr));
- Set copy = orig;
- assert(copy.size() == 5);
- assert(*std::next(copy.begin(), 0) == 1);
- assert(*std::next(copy.begin(), 1) == 2);
- assert(*std::next(copy.begin(), 2) == 3);
- assert(*std::next(copy.begin(), 3) == 4);
- assert(*std::next(copy.begin(), 4) == 5);
- 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) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 3);
- assert(*std::next(orig.begin(), 3) == 4);
- assert(*std::next(orig.begin(), 4) == 5);
- assert(std::next(orig.begin(), 5) == orig.end());
- }
-}
-
-void test() {
- test_alloc<std::allocator>();
- test_alloc<min_allocator>(); // Make sure that fancy pointers work
-
- { // Ensure that the comparator is copied
- using Set = std::set<int, test_less<int> >;
-
- int arr[] = {1, 2, 3};
- const Set orig(std::begin(arr), std::end(arr), test_less<int>(3));
- Set copy = orig;
- assert(copy.size() == 3);
- assert(copy.key_comp() == test_less<int>(3));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.key_comp() == test_less<int>(3));
- }
-
- { // Ensure that the allocator is copied
- using Set = std::set<int, std::less<int>, test_allocator<int> >;
-
- int arr[] = {1, 2, 3};
- const Set orig(std::begin(arr), std::end(arr), std::less<int>(), test_allocator<int>(10));
- Set copy = orig;
- assert(copy.size() == 3);
- assert(copy.get_allocator() == test_allocator<int>(10));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.get_allocator() == test_allocator<int>(10));
- assert(orig.get_allocator().get_id() != test_alloc_base::moved_value);
+int main(int, char**) {
+ {
+ typedef int V;
+ V ar[] = {1, 1, 1, 2, 2, 2, 3, 3, 3};
+ typedef test_less<int> C;
+ typedef test_allocator<V> A;
+ std::set<int, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(7));
+ std::set<int, C, A> m = mo;
+ assert(m.get_allocator() == A(7));
+ assert(m.key_comp() == C(5));
+ assert(m.size() == 3);
+ assert(std::distance(m.begin(), m.end()) == 3);
+ assert(*m.begin() == 1);
+ assert(*std::next(m.begin()) == 2);
+ assert(*std::next(m.begin(), 2) == 3);
+
+ 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() == 1);
+ assert(*std::next(mo.begin()) == 2);
+ assert(*std::next(mo.begin(), 2) == 3);
}
-
- { // Ensure that soccc is handled properly
- using Set = std::set<int, std::less<int>, other_allocator<int> >;
-
- int arr[] = {1, 2, 3};
- const Set orig(std::begin(arr), std::end(arr), std::less<int>(), other_allocator<int>(10));
- Set copy = orig;
- assert(copy.size() == 3);
- assert(copy.get_allocator() == other_allocator<int>(-2));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.get_allocator() == other_allocator<int>(10));
+#if TEST_STD_VER >= 11
+ {
+ typedef int V;
+ V ar[] = {1, 1, 1, 2, 2, 2, 3, 3, 3};
+ typedef test_less<int> C;
+ typedef other_allocator<V> A;
+ std::set<int, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(7));
+ std::set<int, C, A> m = mo;
+ assert(m.get_allocator() == A(-2));
+ assert(m.key_comp() == C(5));
+ assert(m.size() == 3);
+ assert(std::distance(m.begin(), m.end()) == 3);
+ assert(*m.begin() == 1);
+ assert(*std::next(m.begin()) == 2);
+ assert(*std::next(m.begin(), 2) == 3);
+
+ 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() == 1);
+ assert(*std::next(mo.begin()) == 2);
+ assert(*std::next(mo.begin(), 2) == 3);
}
-}
-
-int main(int, char**) {
- test();
+#endif
return 0;
}
diff --git a/libcxx/test/std/containers/associative/set/set.cons/copy_alloc.pass.cpp b/libcxx/test/std/containers/associative/set/set.cons/copy_alloc.pass.cpp
index 2784af65b0a0f..8f9dd769329c0 100644
--- a/libcxx/test/std/containers/associative/set/set.cons/copy_alloc.pass.cpp
+++ b/libcxx/test/std/containers/associative/set/set.cons/copy_alloc.pass.cpp
@@ -12,95 +12,36 @@
// set(const set& m, const allocator_type& a);
-#include <cassert>
#include <set>
+#include <cassert>
+#include <iterator>
-#include "../../../test_compare.h"
-#include "min_allocator.h"
#include "test_macros.h"
+#include "../../../test_compare.h"
#include "test_allocator.h"
-template <class Alloc>
-void test_alloc(const Alloc& new_alloc) {
- { // Simple check
- using Set = std::set<int, std::less<int>, Alloc>;
-
- int arr[] = {1, 2, 3};
- const Set orig(std::begin(arr), std::end(arr));
- Set copy(orig, new_alloc);
- assert(copy.size() == 3);
- assert(*std::next(copy.begin(), 0) == 1);
- assert(*std::next(copy.begin(), 1) == 2);
- assert(*std::next(copy.begin(), 2) == 3);
- 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) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 3);
- assert(std::next(orig.begin(), 3) == orig.end());
- }
-
- { // copy empty set
- using Set = std::set<int, std::less<int>, Alloc>;
-
- const Set orig;
- Set 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 Set = std::set<int, std::less<int>, Alloc>;
-
- int arr[] = {1, 2, 3, 4, 5};
- const Set orig(std::begin(arr), std::end(arr));
- Set copy = orig;
- assert(copy.size() == 5);
- assert(*std::next(copy.begin(), 0) == 1);
- assert(*std::next(copy.begin(), 1) == 2);
- assert(*std::next(copy.begin(), 2) == 3);
- assert(*std::next(copy.begin(), 3) == 4);
- assert(*std::next(copy.begin(), 4) == 5);
- 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) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 3);
- assert(*std::next(orig.begin(), 3) == 4);
- assert(*std::next(orig.begin(), 4) == 5);
- assert(std::next(orig.begin(), 5) == orig.end());
- }
-}
-
-void test() {
- test_alloc(std::allocator<int>());
- test_alloc(test_allocator<int>(25)); // Make sure that the new allocator is actually used
- test_alloc(min_allocator<int>()); // Make sure that fancy pointers work
-
- { // Ensure that the comparator is copied
- int arr[] = {1, 2, 3};
- const std::set<int, test_less<int> > orig(std::begin(arr), std::end(arr), test_less<int>(3));
- std::set<int, test_less<int> > copy(orig, std::allocator<int>());
- assert(copy.size() == 3);
- assert(copy.key_comp() == test_less<int>(3));
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.key_comp() == test_less<int>(3));
- }
-}
-
int main(int, char**) {
- test();
+ typedef int V;
+ V ar[] = {1, 1, 1, 2, 2, 2, 3, 3, 3};
+ typedef test_less<int> C;
+ typedef test_allocator<V> A;
+ std::set<int, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(7));
+ std::set<int, 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() == 1);
+ assert(*std::next(m.begin()) == 2);
+ assert(*std::next(m.begin(), 2) == 3);
+
+ 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() == 1);
+ assert(*std::next(mo.begin()) == 2);
+ assert(*std::next(mo.begin(), 2) == 3);
return 0;
}
diff --git a/libcxx/test/std/containers/associative/set/set.cons/copy_assign.pass.cpp b/libcxx/test/std/containers/associative/set/set.cons/copy_assign.pass.cpp
index 85bc4e761f2c3..f154f5d8b994c 100644
--- a/libcxx/test/std/containers/associative/set/set.cons/copy_assign.pass.cpp
+++ b/libcxx/test/std/containers/associative/set/set.cons/copy_assign.pass.cpp
@@ -12,273 +12,83 @@
// set& operator=(const set& s);
-#include <algorithm>
+#include <set>
#include <cassert>
-#include <cstdio>
#include <iterator>
-#include <set>
-#include <vector>
#include "test_macros.h"
#include "../../../test_compare.h"
#include "test_allocator.h"
-#include "min_allocator.h"
-
-template <class T>
-class tracking_allocator {
- std::vector<void*>* allocs_;
-
- template <class U>
- friend class tracking_allocator;
-
-public:
- using value_type = T;
- using propagate_on_container_copy_assignment = std::true_type;
-
- tracking_allocator(std::vector<void*>& allocs) : allocs_(&allocs) {}
-
- template <class U>
- tracking_allocator(const tracking_allocator<U>& other) : allocs_(other.allocs_) {}
-
- T* allocate(std::size_t n) {
- T* allocation = std::allocator<T>().allocate(n);
- allocs_->push_back(allocation);
- return allocation;
- }
-
- void deallocate(T* ptr, std::size_t n) TEST_NOEXCEPT {
- auto res = std::remove(allocs_->begin(), allocs_->end(), ptr);
- assert(res != allocs_->end() && "Trying to deallocate memory from different allocator?");
- allocs_->erase(res);
- std::allocator<T>().deallocate(ptr, n);
- }
-
- friend bool operator==(const tracking_allocator& lhs, const tracking_allocator& rhs) {
- return lhs.allocs_ == rhs.allocs_;
- }
-
- friend bool operator!=(const tracking_allocator& lhs, const tracking_allocator& rhs) {
- return lhs.allocs_ != rhs.allocs_;
- }
-};
-
-struct NoOp {
- void operator()() {}
-};
-
-template <class Alloc, class AllocatorInvariant = NoOp>
-void test_alloc(const Alloc& lhs_alloc = Alloc(),
- const Alloc& rhs_alloc = Alloc(),
- AllocatorInvariant check_alloc_invariant = NoOp()) {
- { // Test empty/non-empy set combinations
- { // assign from a non-empty container into an empty one
- using Set = std::set<int, std::less<int>, Alloc>;
-
- int arr[] = {1, 2, 3};
- const Set orig(std::begin(arr), std::end(arr), std::less<int>(), rhs_alloc);
- Set copy(lhs_alloc);
- copy = orig;
- assert(copy.size() == 3);
- assert(*std::next(copy.begin(), 0) == 1);
- assert(*std::next(copy.begin(), 1) == 2);
- assert(*std::next(copy.begin(), 2) == 3);
- assert(std::next(copy.begin(), 3) == copy.end());
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(*std::next(orig.begin(), 0) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 3);
- assert(std::next(orig.begin(), 3) == orig.end());
- }
- check_alloc_invariant();
- { // assign from an empty container into an empty one
- using Set = std::set<int, std::less<int>, Alloc>;
-
- const Set orig(rhs_alloc);
- Set copy(lhs_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());
- }
- check_alloc_invariant();
- { // assign from an empty container into a non-empty one
- using Set = std::set<int, std::less<int>, Alloc>;
-
- int arr[] = {1, 2, 3};
- const Set orig(rhs_alloc);
- Set copy(std::begin(arr), std::end(arr), std::less<int>(), rhs_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());
- }
- }
-
- { // Ensure that self-assignment works correctly
- { // with a non-empty set
- using Set = std::set<int, std::less<int>, Alloc>;
- int arr[] = {1, 2, 3};
- Set orig(std::begin(arr), std::end(arr), std::less<int>(), rhs_alloc);
- orig = static_cast<const Set&>(orig);
-
- assert(orig.size() == 3);
- assert(*std::next(orig.begin(), 0) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 3);
- assert(std::next(orig.begin(), 3) == orig.end());
- }
- { // with an empty set
- using Set = std::set<int, std::less<int>, Alloc>;
-
- Set orig(rhs_alloc);
- orig = static_cast<const Set&>(orig);
-
- assert(orig.size() == 0);
- assert(orig.begin() == orig.end());
- }
+int main(int, char**) {
+ {
+ typedef int V;
+ V ar[] = {1, 1, 1, 2, 2, 2, 3, 3, 3};
+ typedef test_less<int> C;
+ typedef test_allocator<V> A;
+ std::set<int, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(2));
+ std::set<int, C, A> m(ar, ar + sizeof(ar) / sizeof(ar[0]) / 2, C(3), A(7));
+ m = mo;
+ assert(m.get_allocator() == A(7));
+ assert(m.key_comp() == C(5));
+ assert(m.size() == 3);
+ assert(std::distance(m.begin(), m.end()) == 3);
+ assert(*m.begin() == 1);
+ assert(*std::next(m.begin()) == 2);
+ assert(*std::next(m.begin(), 2) == 3);
+
+ assert(mo.get_allocator() == A(2));
+ assert(mo.key_comp() == C(5));
+ assert(mo.size() == 3);
+ assert(std::distance(mo.begin(), mo.end()) == 3);
+ assert(*mo.begin() == 1);
+ assert(*std::next(mo.begin()) == 2);
+ assert(*std::next(mo.begin(), 2) == 3);
}
-
- { // check assignment into a non-empty set
- check_alloc_invariant();
- { // LHS already contains elements, but fewer than the RHS
- using Set = std::set<int, std::less<int>, Alloc>;
-
- int lhs_arr[] = {1, 2, 3};
- const Set orig(std::begin(lhs_arr), std::end(lhs_arr), std::less<int>(), rhs_alloc);
-
- int rhs_arr[] = {4, 5};
- Set copy(std::begin(rhs_arr), std::end(rhs_arr), std::less<int>(), lhs_alloc);
- copy = orig;
- assert(copy.size() == 3);
- assert(*std::next(copy.begin(), 0) == 1);
- assert(*std::next(copy.begin(), 1) == 2);
- assert(*std::next(copy.begin(), 2) == 3);
- assert(std::next(copy.begin(), 3) == copy.end());
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(*std::next(orig.begin(), 0) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 3);
- assert(std::next(orig.begin(), 3) == orig.end());
- }
- check_alloc_invariant();
- { // LHS contains the same number of elements as the RHS
- using Set = std::set<int, std::less<int>, Alloc>;
-
- int lhs_arr[] = {1, 2, 3};
- const Set orig(std::begin(lhs_arr), std::end(lhs_arr), std::less<int>(), rhs_alloc);
-
- int rhs_arr[] = {4, 5, 6};
- Set copy(std::begin(rhs_arr), std::end(rhs_arr), std::less<int>(), lhs_alloc);
- copy = orig;
- assert(copy.size() == 3);
- assert(*std::next(copy.begin(), 0) == 1);
- assert(*std::next(copy.begin(), 1) == 2);
- assert(*std::next(copy.begin(), 2) == 3);
- assert(std::next(copy.begin(), 3) == copy.end());
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(*std::next(orig.begin(), 0) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 3);
- assert(std::next(orig.begin(), 3) == orig.end());
- }
- check_alloc_invariant();
- { // LHS already contains more elements than the RHS
- using Set = std::set<int, std::less<int>, Alloc>;
-
- int lhs_arr[] = {1, 2, 3};
- const Set orig(std::begin(lhs_arr), std::end(lhs_arr), std::less<int>(), rhs_alloc);
-
- int rhs_arr[] = {4, 5, 6};
- Set copy(std::begin(rhs_arr), std::end(rhs_arr), std::less<int>(), lhs_alloc);
- copy = orig;
- assert(copy.size() == 3);
- assert(*std::next(copy.begin(), 0) == 1);
- assert(*std::next(copy.begin(), 1) == 2);
- assert(*std::next(copy.begin(), 2) == 3);
- assert(std::next(copy.begin(), 3) == copy.end());
-
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(*std::next(orig.begin(), 0) == 1);
- assert(*std::next(orig.begin(), 1) == 2);
- assert(*std::next(orig.begin(), 2) == 3);
- assert(std::next(orig.begin(), 3) == orig.end());
- }
- check_alloc_invariant();
- { // Make a somewhat larget set to exercise the algorithm a bit
- using Set = std::set<int, std::less<int>, Alloc>;
-
- Set orig(rhs_alloc);
- for (int i = 0; i != 50; ++i)
- orig.insert(i);
-
- Set copy(lhs_alloc);
- copy = orig;
- int i = 0;
- for (auto v : copy) {
- assert(v == i++);
- }
- }
- check_alloc_invariant();
+ {
+ typedef int V;
+ const V ar[] = {1, 2, 3};
+ std::set<int> m(ar, ar + sizeof(ar) / sizeof(ar[0]));
+ std::set<int>* p = &m;
+ m = *p;
+
+ assert(m.size() == 3);
+ assert(std::equal(m.begin(), m.end(), ar));
}
-}
-
-void test() {
- test_alloc<std::allocator<int> >();
-#if TEST_STD_VER >= 11
- test_alloc<min_allocator<int> >();
-
- { // Make sure we're allocating/deallocating nodes with the correct allocator
- // See https://llvm.org/PR29001
- class AssertEmpty {
- std::vector<void*>* lhs_allocs_;
- std::vector<void*>* rhs_allocs_;
-
- public:
- AssertEmpty(std::vector<void*>& lhs_allocs, std::vector<void*>& rhs_allocs)
- : lhs_allocs_(&lhs_allocs), rhs_allocs_(&rhs_allocs) {}
-
- void operator()() {
- assert(lhs_allocs_->empty());
- assert(rhs_allocs_->empty());
- }
- };
-
- std::vector<void*> lhs_allocs;
- std::vector<void*> rhs_allocs;
- test_alloc<tracking_allocator<int> >(lhs_allocs, rhs_allocs, AssertEmpty(lhs_allocs, rhs_allocs));
+ {
+ typedef int V;
+ V ar[] = {1, 1, 1, 2, 2, 2, 3, 3, 3};
+ typedef test_less<int> C;
+ typedef other_allocator<V> A;
+ std::set<int, C, A> mo(ar, ar + sizeof(ar) / sizeof(ar[0]), C(5), A(2));
+ std::set<int, C, A> m(ar, ar + sizeof(ar) / sizeof(ar[0]) / 2, C(3), A(7));
+ m = mo;
+ assert(m.get_allocator() == A(2));
+ assert(m.key_comp() == C(5));
+ assert(m.size() == 3);
+ assert(std::distance(m.begin(), m.end()) == 3);
+ assert(*m.begin() == 1);
+ assert(*std::next(m.begin()) == 2);
+ assert(*std::next(m.begin(), 2) == 3);
+
+ assert(mo.get_allocator() == A(2));
+ assert(mo.key_comp() == C(5));
+ assert(mo.size() == 3);
+ assert(std::distance(mo.begin(), mo.end()) == 3);
+ assert(*mo.begin() == 1);
+ assert(*std::next(mo.begin()) == 2);
+ assert(*std::next(mo.begin(), 2) == 3);
}
-#endif
- { // Ensure that the comparator is copied
- int arr[] = {1, 2, 3};
- const std::set<int, test_less<int> > orig(std::begin(arr), std::end(arr), test_less<int>(3));
- std::set<int, test_less<int> > copy;
- copy = orig;
- assert(copy.size() == 3);
- assert(copy.key_comp() == test_less<int>(3));
+ { // Test with std::pair, since we have some special handling for pairs inside __tree
+ std::pair<int, int> arr[] = {
+ std::make_pair(1, 2), std::make_pair(2, 3), std::make_pair(3, 4), std::make_pair(4, 5)};
+ std::set<std::pair<int, int> > a(arr, arr + 4);
+ std::set<std::pair<int, int> > b;
- // Check that orig is still what is expected
- assert(orig.size() == 3);
- assert(orig.key_comp() == test_less<int>(3));
+ b = a;
+ assert(a == b);
}
-}
-
-int main(int, char**) {
- test();
return 0;
}
More information about the libcxx-commits
mailing list