match.pd: Fix indefinite recursion during exp-log transformations [PR118490]
[gcc.git] / libstdc++-v3 / testsuite / 23_containers / unordered_set / modifiers / 114401.cc
blob3ae2f2d5b5c33b86fa4f64b1c42c97d83817016e
1 // { dg-do run { target c++17 } }
3 // PR libstdc++/114401 allocator destructor omitted when reinserting node_handle
5 #include <unordered_set>
6 #include <memory>
7 #include <testsuite_hooks.h>
9 template<typename T>
10 struct Alloc
12 using value_type = T;
13 using propagate_on_container_copy_assignment = std::true_type;
14 using propagate_on_container_move_assignment = std::true_type;
15 using propagate_on_container_swap = std::true_type;
17 Alloc(int identity) : id(std::make_shared<int>(identity)) { }
19 template<typename U>
20 Alloc(const Alloc<U> a) : id(a.id) { }
22 T* allocate(std::size_t n) { return std::allocator<T>().allocate(n); }
23 void deallocate(T* p, std::size_t n) { std::allocator<T>().deallocate(p, n); }
25 template<typename U>
26 friend bool
27 operator==(const Alloc& a, const Alloc<U>& a2)
28 { return a.id == a2.id; }
30 template<typename U>
31 friend bool
32 operator!=(const Alloc& a, const Alloc<U>& a2)
33 { return !(a == a2); }
35 std::shared_ptr<int> id;
38 using test_type
39 = std::unordered_set<int, std::hash<int>, std::equal_to<int>, Alloc<int>>;
41 void
42 test_node_ops()
44 test_type s1({1,3,5}, 3, Alloc<int>(1));
45 test_type s2({2,4,6,8}, 4, Alloc<int>(2));
46 VERIFY( s1.get_allocator() != s2.get_allocator() );
48 auto node_a = s1.extract(1);
49 VERIFY( ! node_a.empty() );
50 VERIFY( node_a.get_allocator() == s1.get_allocator() );
52 node_a = std::move(node_a); // self-move
53 VERIFY( node_a.empty() );
55 swap(node_a, node_a); // self-swap
56 VERIFY( node_a.empty() );
58 auto node_b = s2.extract(2);
59 VERIFY( node_b.get_allocator() == s2.get_allocator() );
61 node_a = std::move(node_b); // empty = !empty
62 VERIFY( node_a.get_allocator() == s2.get_allocator() );
63 VERIFY( node_b.empty() );
65 swap(node_a, node_b); // swap(!empty, empty)
66 VERIFY( node_a.empty() );
67 VERIFY( node_b.get_allocator() == s2.get_allocator() );
69 swap(node_a, node_b); // swap(empty, !empty)
70 VERIFY( node_a.get_allocator() == s2.get_allocator() );
71 VERIFY( node_b.empty() );
73 node_a = s1.extract(3); // !empty = !empty
74 VERIFY( node_a.get_allocator() == s1.get_allocator() );
75 node_b = s2.extract(0); // empty = empty
76 VERIFY( node_b.empty() );
77 node_b = s2.extract(6); // empty = !empty
78 VERIFY( node_b.get_allocator() == s2.get_allocator() );
80 swap(node_a, node_b); // swap(!empty, !empty)
81 VERIFY( node_a.get_allocator() == s2.get_allocator() );
82 VERIFY( node_b.get_allocator() == s1.get_allocator() );
84 node_a = {};
85 node_b = std::move(node_a); // !empty = empty
86 VERIFY( node_a.empty() );
87 VERIFY( node_b.empty() );
89 swap(node_a, node_b); // swap(empty, empty)
90 VERIFY( node_a.empty() );
91 VERIFY( node_b.empty() );
94 void
95 test_alloc_lifetime()
97 Alloc<int> a(1);
98 test_type s({1,2,3}, 3, a);
99 VERIFY( a.id.use_count() == 2 ); // a and the copy in s
101 s.insert(s.extract(1));
102 VERIFY( a.id.use_count() == 2 );
104 s.insert(s.begin(), s.extract(2));
105 VERIFY( a.id.use_count() == 2 );
107 auto node = s.extract(1);
108 VERIFY( a.id.use_count() == 3 );
109 node = s.extract(0);
110 VERIFY( a.id.use_count() == 2 );
112 s.insert(std::move(node));
113 VERIFY( a.id.use_count() == 2 );
115 s.merge(test_type(s));
116 VERIFY( a.id.use_count() == 2 );
118 s.merge(test_type({4,5,6}, 3, a));
119 VERIFY( a.id.use_count() == 2 );
122 int main()
124 test_node_ops();
125 test_alloc_lifetime();