1 // { dg-do run { target c++17 } }
3 // PR libstdc++/114401 allocator destructor omitted when reinserting node_handle
5 #include <unordered_set>
7 #include <testsuite_hooks.h>
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
)) { }
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
); }
27 operator==(const Alloc
& a
, const Alloc
<U
>& a2
)
28 { return a
.id
== a2
.id
; }
32 operator!=(const Alloc
& a
, const Alloc
<U
>& a2
)
33 { return !(a
== a2
); }
35 std::shared_ptr
<int> id
;
39 = std::unordered_set
<int, std::hash
<int>, std::equal_to
<int>, Alloc
<int>>;
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() );
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() );
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 );
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 );
125 test_alloc_lifetime();