1 // { dg-do run { target c++17 } }
2 // { dg-require-effective-target std_allocator_new }
3 // { dg-xfail-run-if "AIX operator new" { powerpc-ibm-aix* } }
5 // Copyright (C) 2021-2025 Free Software Foundation, Inc.
7 // This file is part of the GNU ISO C++ Library. This library is free
8 // software; you can redistribute it and/or modify it under the
9 // terms of the GNU General Public License as published by the
10 // Free Software Foundation; either version 3, or (at your option)
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License along
19 // with this library; see the file COPYING3. If not see
20 // <http://www.gnu.org/licenses/>.
24 #include <string_view>
26 #include <unordered_map>
29 #include <testsuite_hooks.h>
30 #include <replacement_memory_operators.h>
32 static constexpr std::initializer_list
<std::pair
<const char*, const char*>> lst
=
33 { { "long_str_for_dynamic_allocation", "long_str_for_dynamic_allocation" } };
38 __gnu_test::counter::reset();
39 std::unordered_map
<std::string
, std::string
> um
;
40 um
.insert(lst
.begin(), lst
.end());
41 VERIFY( um
.size() == 1 );
43 VERIFY( __gnu_test::counter::count() == 4 );
44 VERIFY( __gnu_test::counter::get()._M_increments
== 4 );
46 um
.insert(lst
.begin(), lst
.end());
47 VERIFY( um
.size() == 1 );
49 VERIFY( __gnu_test::counter::count() == 4 );
50 // Allocated another node and a pair<const std::string, std::string>:
51 VERIFY( __gnu_test::counter::get()._M_increments
== 7 );
57 __gnu_test::counter::reset();
58 std::unordered_map
<std::string
, std::string
,
59 std::hash
<std::string_view
>,
60 std::equal_to
<std::string_view
>> um
;
61 um
.insert(lst
.begin(), lst
.end());
62 VERIFY( um
.size() == 1 );
64 VERIFY( __gnu_test::counter::count() == 4 );
65 VERIFY( __gnu_test::counter::get()._M_increments
== 4 );
67 um
.insert(lst
.begin(), lst
.end());
68 VERIFY( um
.size() == 1 );
70 VERIFY( __gnu_test::counter::count() == 4 );
71 // Allocated another node and a pair<const std::string, std::string>:
72 VERIFY( __gnu_test::counter::get()._M_increments
== 7 );
76 hash_string_f(const std::string
& str
) noexcept
78 std::hash
<std::string
> h
;
85 typedef std::size_t (*hash_string_t
)(const std::string
&) noexcept
;
86 __gnu_test::counter::reset();
87 hash_string_t hasher
= &hash_string_f
;
88 std::unordered_map
<std::string
, std::string
,
90 std::equal_to
<std::string
>> um(0, hasher
);
91 um
.insert(lst
.begin(), lst
.end());
92 VERIFY( um
.size() == 1 );
94 VERIFY( __gnu_test::counter::count() == 4 );
95 VERIFY( __gnu_test::counter::get()._M_increments
== 4 );
97 um
.insert(lst
.begin(), lst
.end());
98 VERIFY( um
.size() == 1 );
100 VERIFY( __gnu_test::counter::count() == 4 );
101 // Allocated another node and a pair<const std::string, std::string>:
102 VERIFY( __gnu_test::counter::get()._M_increments
== 7 );
106 hash_string_view_f(const std::string_view
& str
) noexcept
108 std::hash
<std::string_view
> h
;
115 typedef std::size_t (*hash_stringview_t
) (const std::string_view
&) noexcept
;
116 __gnu_test::counter::reset();
117 hash_stringview_t hasher
= &hash_string_view_f
;
118 std::unordered_map
<std::string
, std::string
, hash_stringview_t
,
119 std::equal_to
<std::string_view
>> um(0, hasher
);
120 um
.insert(lst
.begin(), lst
.end());
121 VERIFY( um
.size() == 1 );
123 VERIFY( __gnu_test::counter::count() == 4 );
124 VERIFY( __gnu_test::counter::get()._M_increments
== 4 );
126 um
.insert(lst
.begin(), lst
.end());
127 VERIFY( um
.size() == 1 );
129 VERIFY( __gnu_test::counter::count() == 4 );
130 // Allocated another node and a pair<const std::string, std::string>:
131 VERIFY( __gnu_test::counter::get()._M_increments
== 7 );
134 struct hash_string_functor
137 operator()(const std::string
& str
) const noexcept
139 std::hash
<std::string
> h
;
147 __gnu_test::counter::reset();
148 std::unordered_map
<std::string
, std::string
,
150 std::equal_to
<std::string
>> um
;
151 um
.insert(lst
.begin(), lst
.end());
152 VERIFY( um
.size() == 1 );
154 VERIFY( __gnu_test::counter::count() == 4 );
155 VERIFY( __gnu_test::counter::get()._M_increments
== 4 );
157 um
.insert(lst
.begin(), lst
.end());
158 VERIFY( um
.size() == 1 );
160 VERIFY( __gnu_test::counter::count() == 4 );
161 // Allocated another node and a pair<const std::string, std::string>:
162 VERIFY( __gnu_test::counter::get()._M_increments
== 7 );
165 struct hash_string_view_noexcept_functor
168 operator()(const std::string_view
& str
) const noexcept
170 std::hash
<std::string_view
> h
;
178 __gnu_test::counter::reset();
179 std::unordered_map
<std::string
, std::string
,
180 hash_string_view_noexcept_functor
,
181 std::equal_to
<std::string_view
>> um
;
182 um
.insert(lst
.begin(), lst
.end());
183 VERIFY( um
.size() == 1 );
185 VERIFY( __gnu_test::counter::count() == 4 );
186 VERIFY( __gnu_test::counter::get()._M_increments
== 4 );
188 um
.insert(lst
.begin(), lst
.end());
189 VERIFY( um
.size() == 1 );
191 VERIFY( __gnu_test::counter::count() == 4 );
192 // Allocated another node and a pair<const std::string, std::string>:
193 VERIFY( __gnu_test::counter::get()._M_increments
== 7 );
196 struct hash_string_view_functor
199 operator()(const std::string_view
& str
) const
201 std::hash
<std::string_view
> h
;
209 __gnu_test::counter::reset();
210 std::unordered_map
<std::string
, std::string
,
211 hash_string_view_functor
,
212 std::equal_to
<std::string_view
>> um
;
213 um
.insert(lst
.begin(), lst
.end());
214 VERIFY( um
.size() == 1 );
216 VERIFY( __gnu_test::counter::count() == 4 );
217 VERIFY( __gnu_test::counter::get()._M_increments
== 4 );
219 um
.insert(lst
.begin(), lst
.end());
220 VERIFY( um
.size() == 1 );
222 VERIFY( __gnu_test::counter::count() == 4 );
223 // Allocated another node and a pair<const std::string, std::string>:
224 VERIFY( __gnu_test::counter::get()._M_increments
== 7 );
230 std::vector
<std::pair
<std::string
, std::string
>> v
;
231 v
.insert(v
.end(), lst
.begin(), lst
.end());
233 const auto origin
= __gnu_test::counter::count();
236 __gnu_test::counter::reset();
237 std::unordered_map
<std::string
, std::string
,
238 std::hash
<std::string_view
>,
239 std::equal_to
<std::string_view
>> um
;
240 um
.insert(v
.begin(), v
.end());
241 VERIFY( um
.size() == 1 );
243 // Allocate array of buckets, a node, and the 2 std::string (unless COW).
244 constexpr std::size_t increments
= _GLIBCXX_USE_CXX11_ABI
? 4 : 2;
246 VERIFY( __gnu_test::counter::count() == origin
+ increments
);
247 VERIFY( __gnu_test::counter::get()._M_increments
== increments
);
249 um
.insert(v
.begin(), v
.end());
250 VERIFY( um
.size() == 1 );
252 VERIFY( __gnu_test::counter::count() == origin
+ increments
);
253 VERIFY( __gnu_test::counter::get()._M_increments
== increments
);
255 VERIFY( __gnu_test::counter::count() == origin
);
258 __gnu_test::counter::reset();
259 std::unordered_map
<std::string
, std::string
,
260 std::hash
<std::string_view
>,
261 std::equal_to
<std::string_view
>> um
;
262 um
.insert(std::make_move_iterator(v
.begin()),
263 std::make_move_iterator(v
.end()));
264 VERIFY( um
.size() == 1 );
266 // Allocate array of buckets and a node. String is moved.
267 constexpr std::size_t increments
= 2;
269 VERIFY( __gnu_test::counter::count() == origin
+ increments
);
270 VERIFY( __gnu_test::counter::get()._M_increments
== increments
);
277 __gnu_test::counter::scope s
;