]>
Commit | Line | Data |
---|---|---|
e63637ea BK |
1 | // Debugging unordered_map/unordered_multimap implementation -*- C++ -*- |
2 | ||
6441eb6d | 3 | // Copyright (C) 2003-2025 Free Software Foundation, Inc. |
e63637ea BK |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
748086b7 | 8 | // Free Software Foundation; either version 3, or (at your option) |
e63637ea BK |
9 | // any later version. |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
748086b7 JJ |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | // You should have received a copy of the GNU General Public License and | |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
e63637ea BK |
24 | |
25 | /** @file debug/unordered_map | |
26 | * This file is a GNU debug extension to the Standard C++ Library. | |
27 | */ | |
28 | ||
29 | #ifndef _GLIBCXX_DEBUG_UNORDERED_MAP | |
30 | #define _GLIBCXX_DEBUG_UNORDERED_MAP 1 | |
31 | ||
63a598de | 32 | #ifdef _GLIBCXX_SYSHDR |
541a9b10 | 33 | #pragma GCC system_header |
63a598de | 34 | #endif |
541a9b10 | 35 | |
734f5023 | 36 | #if __cplusplus < 201103L |
ab65a4c7 | 37 | # include <bits/c++0x_warning.h> |
c878d6ba | 38 | #else |
9ca2ac69 JW |
39 | # include <bits/c++config.h> |
40 | namespace std _GLIBCXX_VISIBILITY(default) { namespace __debug { | |
41 | template<typename _Key, typename _Tp, typename _Hash, typename _Pred, | |
42 | typename _Allocator> | |
43 | class unordered_map; | |
44 | template<typename _Key, typename _Tp, typename _Hash, typename _Pred, | |
45 | typename _Allocator> | |
46 | class unordered_multimap; | |
47 | } } // namespace std::__debug | |
48 | ||
c878d6ba | 49 | # include <unordered_map> |
e63637ea | 50 | |
364c862b | 51 | #include <debug/safe_unordered_container.h> |
15ee1a77 | 52 | #include <debug/safe_container.h> |
ced3cb9f | 53 | #include <debug/safe_iterator.h> |
77e0bf4e | 54 | #include <debug/safe_local_iterator.h> |
e63637ea | 55 | |
12ffa228 | 56 | namespace std _GLIBCXX_VISIBILITY(default) |
e63637ea BK |
57 | { |
58 | namespace __debug | |
59 | { | |
1ceb9e06 | 60 | /// Class std::unordered_map with safety/checking/debug instrumentation. |
e63637ea | 61 | template<typename _Key, typename _Tp, |
ced3cb9f | 62 | typename _Hash = std::hash<_Key>, |
e63637ea | 63 | typename _Pred = std::equal_to<_Key>, |
03d7aff6 | 64 | typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > > |
e63637ea | 65 | class unordered_map |
15ee1a77 FD |
66 | : public __gnu_debug::_Safe_container< |
67 | unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc, | |
68 | __gnu_debug::_Safe_unordered_container>, | |
69 | public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc> | |
e63637ea | 70 | { |
12ffa228 | 71 | typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, |
15ee1a77 FD |
72 | _Pred, _Alloc> _Base; |
73 | typedef __gnu_debug::_Safe_container<unordered_map, | |
74 | _Alloc, __gnu_debug::_Safe_unordered_container> _Safe; | |
75 | typedef typename _Base::const_iterator _Base_const_iterator; | |
76 | typedef typename _Base::iterator _Base_iterator; | |
77 | typedef typename _Base::const_local_iterator | |
78 | _Base_const_local_iterator; | |
79 | typedef typename _Base::local_iterator _Base_local_iterator; | |
0462b6aa | 80 | |
e9afbed0 FD |
81 | template<typename _ItT, typename _SeqT, typename _CatT> |
82 | friend class ::__gnu_debug::_Safe_iterator; | |
83 | template<typename _ItT, typename _SeqT> | |
84 | friend class ::__gnu_debug::_Safe_local_iterator; | |
85 | ||
eca833b8 JW |
86 | // Reference wrapper for base class. See PR libstdc++/90102. |
87 | struct _Base_ref | |
88 | { | |
89 | _Base_ref(const _Base& __r) : _M_ref(__r) { } | |
90 | ||
91 | const _Base& _M_ref; | |
92 | }; | |
93 | ||
e63637ea | 94 | public: |
15ee1a77 FD |
95 | typedef typename _Base::size_type size_type; |
96 | typedef typename _Base::hasher hasher; | |
97 | typedef typename _Base::key_equal key_equal; | |
98 | typedef typename _Base::allocator_type allocator_type; | |
99 | ||
100 | typedef typename _Base::key_type key_type; | |
101 | typedef typename _Base::value_type value_type; | |
f4b4ce15 | 102 | typedef typename _Base::mapped_type mapped_type; |
15ee1a77 | 103 | |
f4b4ce15 FD |
104 | typedef typename _Base::pointer pointer; |
105 | typedef typename _Base::const_pointer const_pointer; | |
106 | typedef typename _Base::reference reference; | |
107 | typedef typename _Base::const_reference const_reference; | |
15ee1a77 FD |
108 | typedef __gnu_debug::_Safe_iterator< |
109 | _Base_iterator, unordered_map> iterator; | |
110 | typedef __gnu_debug::_Safe_iterator< | |
111 | _Base_const_iterator, unordered_map> const_iterator; | |
112 | typedef __gnu_debug::_Safe_local_iterator< | |
113 | _Base_local_iterator, unordered_map> local_iterator; | |
114 | typedef __gnu_debug::_Safe_local_iterator< | |
115 | _Base_const_local_iterator, unordered_map> const_local_iterator; | |
f4b4ce15 | 116 | typedef typename _Base::difference_type difference_type; |
e63637ea | 117 | |
da27f556 FD |
118 | unordered_map() = default; |
119 | ||
e63637ea | 120 | explicit |
da27f556 | 121 | unordered_map(size_type __n, |
e63637ea BK |
122 | const hasher& __hf = hasher(), |
123 | const key_equal& __eql = key_equal(), | |
124 | const allocator_type& __a = allocator_type()) | |
ced3cb9f | 125 | : _Base(__n, __hf, __eql, __a) { } |
e63637ea BK |
126 | |
127 | template<typename _InputIterator> | |
15ee1a77 | 128 | unordered_map(_InputIterator __first, _InputIterator __last, |
417e896e | 129 | size_type __n = 0, |
15ee1a77 FD |
130 | const hasher& __hf = hasher(), |
131 | const key_equal& __eql = key_equal(), | |
e63637ea | 132 | const allocator_type& __a = allocator_type()) |
90aabc7e FD |
133 | : _Base(__gnu_debug::__base( |
134 | __glibcxx_check_valid_constructor_range(__first, __last)), | |
1f5ca1a1 | 135 | __gnu_debug::__base(__last), __n, |
4c2d93db | 136 | __hf, __eql, __a) { } |
e63637ea | 137 | |
0462b6aa | 138 | unordered_map(const unordered_map&) = default; |
e63637ea | 139 | |
eca833b8 JW |
140 | unordered_map(_Base_ref __x) |
141 | : _Base(__x._M_ref) { } | |
ced3cb9f | 142 | |
0462b6aa FD |
143 | unordered_map(unordered_map&&) = default; |
144 | ||
145 | explicit | |
146 | unordered_map(const allocator_type& __a) | |
15ee1a77 | 147 | : _Base(__a) { } |
0462b6aa FD |
148 | |
149 | unordered_map(const unordered_map& __umap, | |
150 | const allocator_type& __a) | |
15ee1a77 | 151 | : _Base(__umap, __a) { } |
0462b6aa FD |
152 | |
153 | unordered_map(unordered_map&& __umap, | |
154 | const allocator_type& __a) | |
e9a53a4f FD |
155 | noexcept( noexcept(_Base(std::move(__umap), __a)) ) |
156 | : _Safe(std::move(__umap), __a), | |
157 | _Base(std::move(__umap), __a) { } | |
69b3331e | 158 | |
988499f4 | 159 | unordered_map(initializer_list<value_type> __l, |
417e896e | 160 | size_type __n = 0, |
988499f4 JM |
161 | const hasher& __hf = hasher(), |
162 | const key_equal& __eql = key_equal(), | |
163 | const allocator_type& __a = allocator_type()) | |
4c2d93db | 164 | : _Base(__l, __n, __hf, __eql, __a) { } |
ced3cb9f | 165 | |
e55b80f5 FD |
166 | unordered_map(size_type __n, const allocator_type& __a) |
167 | : unordered_map(__n, hasher(), key_equal(), __a) | |
168 | { } | |
169 | ||
170 | unordered_map(size_type __n, | |
171 | const hasher& __hf, | |
172 | const allocator_type& __a) | |
173 | : unordered_map(__n, __hf, key_equal(), __a) | |
174 | { } | |
175 | ||
1ecd95ea TK |
176 | template<typename _InputIterator> |
177 | unordered_map(_InputIterator __first, _InputIterator __last, | |
178 | const allocator_type& __a) | |
179 | : unordered_map(__first, __last, 0, hasher(), key_equal(), __a) | |
180 | { } | |
181 | ||
e55b80f5 FD |
182 | template<typename _InputIterator> |
183 | unordered_map(_InputIterator __first, _InputIterator __last, | |
184 | size_type __n, | |
185 | const allocator_type& __a) | |
12324b9a | 186 | : unordered_map(__first, __last, __n, hasher(), key_equal(), __a) |
e55b80f5 FD |
187 | { } |
188 | ||
189 | template<typename _InputIterator> | |
190 | unordered_map(_InputIterator __first, _InputIterator __last, | |
191 | size_type __n, | |
192 | const hasher& __hf, | |
193 | const allocator_type& __a) | |
12324b9a | 194 | : unordered_map(__first, __last, __n, __hf, key_equal(), __a) |
e55b80f5 FD |
195 | { } |
196 | ||
1ecd95ea TK |
197 | unordered_map(initializer_list<value_type> __l, |
198 | const allocator_type& __a) | |
199 | : unordered_map(__l, 0, hasher(), key_equal(), __a) | |
200 | { } | |
201 | ||
e55b80f5 FD |
202 | unordered_map(initializer_list<value_type> __l, |
203 | size_type __n, | |
204 | const allocator_type& __a) | |
12324b9a | 205 | : unordered_map(__l, __n, hasher(), key_equal(), __a) |
e55b80f5 FD |
206 | { } |
207 | ||
208 | unordered_map(initializer_list<value_type> __l, | |
209 | size_type __n, | |
210 | const hasher& __hf, | |
211 | const allocator_type& __a) | |
12324b9a | 212 | : unordered_map(__l, __n, __hf, key_equal(), __a) |
e55b80f5 FD |
213 | { } |
214 | ||
ae54d8cb | 215 | #if __glibcxx_containers_ranges // C++ >= 23 |
7cc40201 TK |
216 | template<__detail::__container_compatible_range<value_type> _Rg> |
217 | unordered_map(from_range_t, _Rg&& __rg, | |
218 | size_type __n = 0, | |
219 | const hasher& __hf = hasher(), | |
220 | const key_equal& __eql = key_equal(), | |
221 | const allocator_type& __a = allocator_type()) | |
222 | : _Base(from_range, std::forward<_Rg>(__rg), __n, __hf, __eql, __a) | |
223 | { } | |
224 | ||
225 | template<__detail::__container_compatible_range<value_type> _Rg> | |
226 | unordered_map(from_range_t, _Rg&& __rg, const allocator_type& __a) | |
227 | : _Base(from_range, std::forward<_Rg>(__rg), __a) | |
228 | { } | |
229 | ||
230 | template<__detail::__container_compatible_range<value_type> _Rg> | |
231 | unordered_map(from_range_t, _Rg&& __rg, size_type __n, | |
232 | const allocator_type& __a) | |
233 | : _Base(from_range, std::forward<_Rg>(__rg), __n, __a) | |
234 | { } | |
235 | ||
236 | template<__detail::__container_compatible_range<value_type> _Rg> | |
237 | unordered_map(from_range_t, _Rg&& __rg, size_type __n, | |
238 | const hasher& __hf, const allocator_type& __a) | |
239 | : _Base(from_range, std::forward<_Rg>(__rg), __n, __hf, __a) | |
240 | { } | |
241 | #endif | |
242 | ||
15ee1a77 | 243 | ~unordered_map() = default; |
6f59ea25 | 244 | |
ced3cb9f | 245 | unordered_map& |
15ee1a77 | 246 | operator=(const unordered_map&) = default; |
988499f4 | 247 | |
69b3331e | 248 | unordered_map& |
15ee1a77 | 249 | operator=(unordered_map&&) = default; |
69b3331e | 250 | |
988499f4 JM |
251 | unordered_map& |
252 | operator=(initializer_list<value_type> __l) | |
253 | { | |
e9a53a4f | 254 | _Base::operator=(__l); |
0462b6aa | 255 | this->_M_invalidate_all(); |
988499f4 JM |
256 | return *this; |
257 | } | |
258 | ||
f4b4ce15 FD |
259 | using _Base::get_allocator; |
260 | using _Base::empty; | |
261 | using _Base::size; | |
262 | using _Base::max_size; | |
263 | ||
e63637ea | 264 | void |
ff74fd13 | 265 | swap(unordered_map& __x) |
c5d9ec56 | 266 | noexcept( noexcept(declval<_Base&>().swap(__x)) ) |
e63637ea | 267 | { |
15ee1a77 | 268 | _Safe::_M_swap(__x); |
ced3cb9f | 269 | _Base::swap(__x); |
e63637ea | 270 | } |
69b3331e PC |
271 | |
272 | void | |
d3677132 | 273 | clear() noexcept |
69b3331e PC |
274 | { |
275 | _Base::clear(); | |
276 | this->_M_invalidate_all(); | |
277 | } | |
278 | ||
15ee1a77 | 279 | iterator |
d3677132 | 280 | begin() noexcept |
4b763dee | 281 | { return { _Base::begin(), this }; } |
ced3cb9f PC |
282 | |
283 | const_iterator | |
d3677132 | 284 | begin() const noexcept |
4b763dee | 285 | { return { _Base::begin(), this }; } |
ced3cb9f PC |
286 | |
287 | iterator | |
d3677132 | 288 | end() noexcept |
4b763dee | 289 | { return { _Base::end(), this }; } |
ced3cb9f PC |
290 | |
291 | const_iterator | |
d3677132 | 292 | end() const noexcept |
4b763dee | 293 | { return { _Base::end(), this }; } |
ced3cb9f PC |
294 | |
295 | const_iterator | |
d3677132 | 296 | cbegin() const noexcept |
4b763dee | 297 | { return { _Base::cbegin(), this }; } |
ced3cb9f PC |
298 | |
299 | const_iterator | |
d3677132 | 300 | cend() const noexcept |
4b763dee | 301 | { return { _Base::cend(), this }; } |
ced3cb9f PC |
302 | |
303 | // local versions | |
77e0bf4e FD |
304 | local_iterator |
305 | begin(size_type __b) | |
7181e991 FD |
306 | { |
307 | __glibcxx_check_bucket_index(__b); | |
4b763dee | 308 | return { _Base::begin(__b), this }; |
7181e991 | 309 | } |
77e0bf4e FD |
310 | |
311 | local_iterator | |
312 | end(size_type __b) | |
7181e991 FD |
313 | { |
314 | __glibcxx_check_bucket_index(__b); | |
4b763dee | 315 | return { _Base::end(__b), this }; |
7181e991 | 316 | } |
77e0bf4e FD |
317 | |
318 | const_local_iterator | |
319 | begin(size_type __b) const | |
7181e991 FD |
320 | { |
321 | __glibcxx_check_bucket_index(__b); | |
4b763dee | 322 | return { _Base::begin(__b), this }; |
7181e991 | 323 | } |
77e0bf4e FD |
324 | |
325 | const_local_iterator | |
326 | end(size_type __b) const | |
7181e991 FD |
327 | { |
328 | __glibcxx_check_bucket_index(__b); | |
4b763dee | 329 | return { _Base::end(__b), this }; |
7181e991 | 330 | } |
77e0bf4e FD |
331 | |
332 | const_local_iterator | |
333 | cbegin(size_type __b) const | |
7181e991 FD |
334 | { |
335 | __glibcxx_check_bucket_index(__b); | |
4b763dee | 336 | return { _Base::cbegin(__b), this }; |
7181e991 | 337 | } |
77e0bf4e FD |
338 | |
339 | const_local_iterator | |
340 | cend(size_type __b) const | |
7181e991 FD |
341 | { |
342 | __glibcxx_check_bucket_index(__b); | |
4b763dee | 343 | return { _Base::cend(__b), this }; |
7181e991 FD |
344 | } |
345 | ||
f4b4ce15 FD |
346 | using _Base::bucket_count; |
347 | using _Base::max_bucket_count; | |
348 | using _Base::bucket; | |
349 | ||
7181e991 FD |
350 | size_type |
351 | bucket_size(size_type __b) const | |
352 | { | |
353 | __glibcxx_check_bucket_index(__b); | |
354 | return _Base::bucket_size(__b); | |
355 | } | |
ced3cb9f | 356 | |
f4b4ce15 FD |
357 | using _Base::load_factor; |
358 | ||
14cbb5d8 FD |
359 | float |
360 | max_load_factor() const noexcept | |
361 | { return _Base::max_load_factor(); } | |
362 | ||
363 | void | |
364 | max_load_factor(float __f) | |
365 | { | |
366 | __glibcxx_check_max_load_factor(__f); | |
367 | _Base::max_load_factor(__f); | |
368 | } | |
369 | ||
9b81593b FD |
370 | template<typename... _Args> |
371 | std::pair<iterator, bool> | |
372 | emplace(_Args&&... __args) | |
373 | { | |
374 | size_type __bucket_count = this->bucket_count(); | |
4b763dee | 375 | auto __res = _Base::emplace(std::forward<_Args>(__args)...); |
9b81593b | 376 | _M_check_rehashed(__bucket_count); |
4b763dee | 377 | return { { __res.first, this }, __res.second }; |
9b81593b FD |
378 | } |
379 | ||
380 | template<typename... _Args> | |
381 | iterator | |
382 | emplace_hint(const_iterator __hint, _Args&&... __args) | |
383 | { | |
384 | __glibcxx_check_insert(__hint); | |
385 | size_type __bucket_count = this->bucket_count(); | |
4b763dee FD |
386 | auto __it = _Base::emplace_hint(__hint.base(), |
387 | std::forward<_Args>(__args)...); | |
9b81593b | 388 | _M_check_rehashed(__bucket_count); |
4b763dee | 389 | return { __it, this }; |
9b81593b FD |
390 | } |
391 | ||
ced3cb9f PC |
392 | std::pair<iterator, bool> |
393 | insert(const value_type& __obj) | |
394 | { | |
77e0bf4e | 395 | size_type __bucket_count = this->bucket_count(); |
1679da15 | 396 | auto __res = _Base::insert(__obj); |
77e0bf4e | 397 | _M_check_rehashed(__bucket_count); |
4b763dee | 398 | return { { __res.first, this }, __res.second }; |
ced3cb9f PC |
399 | } |
400 | ||
1679da15 FD |
401 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
402 | // 2354. Unnecessary copying when inserting into maps with braced-init | |
403 | std::pair<iterator, bool> | |
404 | insert(value_type&& __x) | |
ced3cb9f | 405 | { |
77e0bf4e | 406 | size_type __bucket_count = this->bucket_count(); |
1679da15 | 407 | auto __res = _Base::insert(std::move(__x)); |
77e0bf4e | 408 | _M_check_rehashed(__bucket_count); |
4b763dee | 409 | return { { __res.first, this }, __res.second }; |
ced3cb9f PC |
410 | } |
411 | ||
fb7342fd | 412 | template<typename _Pair, typename = typename |
57cee56a PC |
413 | std::enable_if<std::is_constructible<value_type, |
414 | _Pair&&>::value>::type> | |
77e0bf4e FD |
415 | std::pair<iterator, bool> |
416 | insert(_Pair&& __obj) | |
417 | { | |
418 | size_type __bucket_count = this->bucket_count(); | |
4b763dee | 419 | auto __res = _Base::insert(std::forward<_Pair>(__obj)); |
77e0bf4e | 420 | _M_check_rehashed(__bucket_count); |
4b763dee | 421 | return { { __res.first, this }, __res.second }; |
fb7342fd PC |
422 | } |
423 | ||
1679da15 FD |
424 | iterator |
425 | insert(const_iterator __hint, const value_type& __obj) | |
426 | { | |
427 | __glibcxx_check_insert(__hint); | |
428 | size_type __bucket_count = this->bucket_count(); | |
4b763dee | 429 | auto __it = _Base::insert(__hint.base(), __obj); |
1679da15 | 430 | _M_check_rehashed(__bucket_count); |
4b763dee | 431 | return { __it, this }; |
1679da15 FD |
432 | } |
433 | ||
434 | // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
435 | // 2354. Unnecessary copying when inserting into maps with braced-init | |
436 | iterator | |
437 | insert(const_iterator __hint, value_type&& __x) | |
438 | { | |
439 | __glibcxx_check_insert(__hint); | |
440 | size_type __bucket_count = this->bucket_count(); | |
441 | auto __it = _Base::insert(__hint.base(), std::move(__x)); | |
442 | _M_check_rehashed(__bucket_count); | |
4b763dee | 443 | return { __it, this }; |
1679da15 FD |
444 | } |
445 | ||
fb7342fd | 446 | template<typename _Pair, typename = typename |
57cee56a PC |
447 | std::enable_if<std::is_constructible<value_type, |
448 | _Pair&&>::value>::type> | |
77e0bf4e FD |
449 | iterator |
450 | insert(const_iterator __hint, _Pair&& __obj) | |
451 | { | |
d66411ba | 452 | __glibcxx_check_insert(__hint); |
77e0bf4e | 453 | size_type __bucket_count = this->bucket_count(); |
4b763dee | 454 | auto __it = _Base::insert(__hint.base(), std::forward<_Pair>(__obj)); |
77e0bf4e | 455 | _M_check_rehashed(__bucket_count); |
4b763dee | 456 | return { __it, this }; |
fb7342fd PC |
457 | } |
458 | ||
ced3cb9f PC |
459 | void |
460 | insert(std::initializer_list<value_type> __l) | |
77e0bf4e FD |
461 | { |
462 | size_type __bucket_count = this->bucket_count(); | |
463 | _Base::insert(__l); | |
464 | _M_check_rehashed(__bucket_count); | |
465 | } | |
ced3cb9f PC |
466 | |
467 | template<typename _InputIterator> | |
77e0bf4e FD |
468 | void |
469 | insert(_InputIterator __first, _InputIterator __last) | |
470 | { | |
24167c42 FD |
471 | typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist; |
472 | __glibcxx_check_valid_range2(__first, __last, __dist); | |
77e0bf4e | 473 | size_type __bucket_count = this->bucket_count(); |
24167c42 FD |
474 | |
475 | if (__dist.second >= __gnu_debug::__dp_sign) | |
476 | _Base::insert(__gnu_debug::__unsafe(__first), | |
477 | __gnu_debug::__unsafe(__last)); | |
478 | else | |
479 | _Base::insert(__first, __last); | |
480 | ||
77e0bf4e | 481 | _M_check_rehashed(__bucket_count); |
ced3cb9f PC |
482 | } |
483 | ||
b66a57c0 | 484 | #ifdef __glibcxx_unordered_map_try_emplace // C++ >= 17 && HOSTED |
66c182be | 485 | template <typename... _Args> |
4b763dee FD |
486 | pair<iterator, bool> |
487 | try_emplace(const key_type& __k, _Args&&... __args) | |
488 | { | |
66c182be JW |
489 | auto __res = _Base::try_emplace(__k, |
490 | std::forward<_Args>(__args)...); | |
4b763dee | 491 | return { { __res.first, this }, __res.second }; |
66c182be JW |
492 | } |
493 | ||
494 | template <typename... _Args> | |
4b763dee FD |
495 | pair<iterator, bool> |
496 | try_emplace(key_type&& __k, _Args&&... __args) | |
497 | { | |
66c182be JW |
498 | auto __res = _Base::try_emplace(std::move(__k), |
499 | std::forward<_Args>(__args)...); | |
4b763dee | 500 | return { { __res.first, this }, __res.second }; |
66c182be JW |
501 | } |
502 | ||
503 | template <typename... _Args> | |
4b763dee FD |
504 | iterator |
505 | try_emplace(const_iterator __hint, const key_type& __k, | |
506 | _Args&&... __args) | |
507 | { | |
66c182be | 508 | __glibcxx_check_insert(__hint); |
4b763dee FD |
509 | return { _Base::try_emplace(__hint.base(), __k, |
510 | std::forward<_Args>(__args)...), | |
511 | this }; | |
66c182be JW |
512 | } |
513 | ||
514 | template <typename... _Args> | |
4b763dee FD |
515 | iterator |
516 | try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args) | |
517 | { | |
66c182be | 518 | __glibcxx_check_insert(__hint); |
4b763dee FD |
519 | return { _Base::try_emplace(__hint.base(), std::move(__k), |
520 | std::forward<_Args>(__args)...), | |
521 | this }; | |
66c182be JW |
522 | } |
523 | ||
524 | template <typename _Obj> | |
4b763dee FD |
525 | pair<iterator, bool> |
526 | insert_or_assign(const key_type& __k, _Obj&& __obj) | |
527 | { | |
66c182be JW |
528 | auto __res = _Base::insert_or_assign(__k, |
529 | std::forward<_Obj>(__obj)); | |
4b763dee | 530 | return { { __res.first, this }, __res.second }; |
66c182be JW |
531 | } |
532 | ||
533 | template <typename _Obj> | |
4b763dee FD |
534 | pair<iterator, bool> |
535 | insert_or_assign(key_type&& __k, _Obj&& __obj) | |
536 | { | |
66c182be JW |
537 | auto __res = _Base::insert_or_assign(std::move(__k), |
538 | std::forward<_Obj>(__obj)); | |
4b763dee | 539 | return { { __res.first, this }, __res.second }; |
66c182be JW |
540 | } |
541 | ||
542 | template <typename _Obj> | |
4b763dee FD |
543 | iterator |
544 | insert_or_assign(const_iterator __hint, const key_type& __k, | |
545 | _Obj&& __obj) | |
546 | { | |
66c182be | 547 | __glibcxx_check_insert(__hint); |
4b763dee FD |
548 | return { _Base::insert_or_assign(__hint.base(), __k, |
549 | std::forward<_Obj>(__obj)), | |
550 | this }; | |
66c182be JW |
551 | } |
552 | ||
553 | template <typename _Obj> | |
4b763dee FD |
554 | iterator |
555 | insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj) | |
556 | { | |
66c182be | 557 | __glibcxx_check_insert(__hint); |
4b763dee FD |
558 | return { _Base::insert_or_assign(__hint.base(), std::move(__k), |
559 | std::forward<_Obj>(__obj)), | |
560 | this }; | |
66c182be | 561 | } |
2dbe56bd | 562 | #endif // C++17 |
66c182be | 563 | |
2dbe56bd JW |
564 | #if __cplusplus > 201402L |
565 | using node_type = typename _Base::node_type; | |
adaefe2a | 566 | using insert_return_type = _Node_insert_return<iterator, node_type>; |
2dbe56bd JW |
567 | |
568 | node_type | |
569 | extract(const_iterator __position) | |
570 | { | |
571 | __glibcxx_check_erase(__position); | |
4b763dee | 572 | return _M_extract(__position.base()); |
2dbe56bd JW |
573 | } |
574 | ||
575 | node_type | |
576 | extract(const key_type& __key) | |
577 | { | |
4b763dee FD |
578 | const auto __position = _Base::find(__key); |
579 | if (__position != _Base::end()) | |
580 | return _M_extract(__position); | |
2dbe56bd JW |
581 | return {}; |
582 | } | |
583 | ||
584 | insert_return_type | |
585 | insert(node_type&& __nh) | |
586 | { | |
587 | auto __ret = _Base::insert(std::move(__nh)); | |
4b763dee FD |
588 | return |
589 | { { __ret.position, this }, __ret.inserted, std::move(__ret.node) }; | |
2dbe56bd JW |
590 | } |
591 | ||
592 | iterator | |
593 | insert(const_iterator __hint, node_type&& __nh) | |
594 | { | |
595 | __glibcxx_check_insert(__hint); | |
4b763dee | 596 | return { _Base::insert(__hint.base(), std::move(__nh)), this }; |
2dbe56bd JW |
597 | } |
598 | ||
f4b4ce15 FD |
599 | template<typename _H2, typename _P2> |
600 | void | |
601 | merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>& __source) | |
602 | { | |
603 | auto __guard | |
604 | = _Safe::_S_uc_guard(std::__detail::_Select1st{}, __source); | |
e9a53a4f | 605 | _Base::merge(__source); |
f4b4ce15 FD |
606 | } |
607 | ||
608 | template<typename _H2, typename _P2> | |
609 | void | |
610 | merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>&& __source) | |
611 | { merge(__source); } | |
612 | ||
613 | template<typename _H2, typename _P2> | |
614 | void | |
615 | merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>& __source) | |
616 | { | |
617 | auto __guard | |
618 | = _Safe::_S_umc_guard(std::__detail::_Select1st{}, __source); | |
e9a53a4f | 619 | _Base::merge(__source); |
f4b4ce15 FD |
620 | } |
621 | ||
622 | template<typename _H2, typename _P2> | |
623 | void | |
624 | merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>&& __source) | |
625 | { merge(__source); } | |
2dbe56bd | 626 | #endif // C++17 |
66c182be | 627 | |
f4b4ce15 FD |
628 | using _Base::hash_function; |
629 | using _Base::key_eq; | |
630 | ||
ced3cb9f PC |
631 | iterator |
632 | find(const key_type& __key) | |
4b763dee | 633 | { return { _Base::find(__key), this }; } |
ced3cb9f | 634 | |
d2b1a684 FD |
635 | #if __cplusplus > 201703L |
636 | template<typename _Kt, | |
637 | typename = std::__has_is_transparent_t<_Hash, _Kt>, | |
638 | typename = std::__has_is_transparent_t<_Pred, _Kt>> | |
639 | iterator | |
640 | find(const _Kt& __k) | |
641 | { return { _Base::find(__k), this }; } | |
642 | #endif | |
643 | ||
ced3cb9f PC |
644 | const_iterator |
645 | find(const key_type& __key) const | |
4b763dee | 646 | { return { _Base::find(__key), this }; } |
ced3cb9f | 647 | |
d2b1a684 FD |
648 | #if __cplusplus > 201703L |
649 | template<typename _Kt, | |
650 | typename = std::__has_is_transparent_t<_Hash, _Kt>, | |
651 | typename = std::__has_is_transparent_t<_Pred, _Kt>> | |
652 | const_iterator | |
653 | find(const _Kt& __k) const | |
654 | { return { _Base::find(__k), this }; } | |
655 | #endif | |
656 | ||
f4b4ce15 FD |
657 | using _Base::count; |
658 | #if __cplusplus > 201703L | |
659 | using _Base::contains; | |
660 | #endif | |
661 | ||
ced3cb9f PC |
662 | std::pair<iterator, iterator> |
663 | equal_range(const key_type& __key) | |
664 | { | |
4b763dee FD |
665 | auto __res = _Base::equal_range(__key); |
666 | return { { __res.first, this }, { __res.second, this } }; | |
ced3cb9f PC |
667 | } |
668 | ||
d2b1a684 FD |
669 | #if __cplusplus > 201703L |
670 | template<typename _Kt, | |
671 | typename = std::__has_is_transparent_t<_Hash, _Kt>, | |
672 | typename = std::__has_is_transparent_t<_Pred, _Kt>> | |
673 | std::pair<iterator, iterator> | |
674 | equal_range(const _Kt& __k) | |
675 | { | |
676 | auto __res = _Base::equal_range(__k); | |
677 | return { { __res.first, this }, { __res.second, this } }; | |
678 | } | |
679 | #endif | |
680 | ||
ced3cb9f PC |
681 | std::pair<const_iterator, const_iterator> |
682 | equal_range(const key_type& __key) const | |
683 | { | |
4b763dee FD |
684 | auto __res = _Base::equal_range(__key); |
685 | return { { __res.first, this }, { __res.second, this } }; | |
ced3cb9f PC |
686 | } |
687 | ||
d2b1a684 FD |
688 | #if __cplusplus > 201703L |
689 | template<typename _Kt, | |
690 | typename = std::__has_is_transparent_t<_Hash, _Kt>, | |
691 | typename = std::__has_is_transparent_t<_Pred, _Kt>> | |
692 | std::pair<const_iterator, const_iterator> | |
693 | equal_range(const _Kt& __k) const | |
694 | { | |
695 | auto __res = _Base::equal_range(__k); | |
696 | return { { __res.first, this }, { __res.second, this } }; | |
697 | } | |
698 | #endif | |
699 | ||
f4b4ce15 FD |
700 | using _Base::operator[]; |
701 | using _Base::at; | |
702 | ||
ced3cb9f PC |
703 | size_type |
704 | erase(const key_type& __key) | |
705 | { | |
706 | size_type __ret(0); | |
4b763dee | 707 | auto __victim = _Base::find(__key); |
afe96d41 | 708 | if (__victim != _Base::end()) |
ced3cb9f | 709 | { |
4b763dee | 710 | _M_erase(__victim); |
ced3cb9f PC |
711 | __ret = 1; |
712 | } | |
713 | return __ret; | |
714 | } | |
715 | ||
d723ced2 | 716 | iterator |
ced3cb9f PC |
717 | erase(const_iterator __it) |
718 | { | |
719 | __glibcxx_check_erase(__it); | |
4b763dee | 720 | return { _M_erase(__it.base()), this }; |
ced3cb9f PC |
721 | } |
722 | ||
5f40d34b FD |
723 | _Base_iterator |
724 | erase(_Base_const_iterator __it) | |
725 | { | |
726 | __glibcxx_check_erase2(__it); | |
727 | return _M_erase(__it); | |
728 | } | |
729 | ||
6dc88283 PC |
730 | iterator |
731 | erase(iterator __it) | |
4b763dee FD |
732 | { |
733 | __glibcxx_check_erase(__it); | |
734 | return { _M_erase(__it.base()), this }; | |
735 | } | |
6dc88283 | 736 | |
d723ced2 | 737 | iterator |
ced3cb9f PC |
738 | erase(const_iterator __first, const_iterator __last) |
739 | { | |
740 | __glibcxx_check_erase_range(__first, __last); | |
4b763dee | 741 | for (auto __tmp = __first.base(); __tmp != __last.base(); ++__tmp) |
afe96d41 | 742 | { |
4b763dee | 743 | _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::cend(), |
afe96d41 FD |
744 | _M_message(__gnu_debug::__msg_valid_range) |
745 | ._M_iterator(__first, "first") | |
746 | ._M_iterator(__last, "last")); | |
4b763dee | 747 | _M_invalidate(__tmp); |
afe96d41 | 748 | } |
4b763dee | 749 | |
77e0bf4e | 750 | size_type __bucket_count = this->bucket_count(); |
4b763dee | 751 | auto __next = _Base::erase(__first.base(), __last.base()); |
77e0bf4e | 752 | _M_check_rehashed(__bucket_count); |
4b763dee | 753 | return { __next, this }; |
ced3cb9f PC |
754 | } |
755 | ||
f4b4ce15 FD |
756 | using _Base::rehash; |
757 | using _Base::reserve; | |
758 | ||
ced3cb9f | 759 | _Base& |
15ee1a77 | 760 | _M_base() noexcept { return *this; } |
ced3cb9f PC |
761 | |
762 | const _Base& | |
15ee1a77 | 763 | _M_base() const noexcept { return *this; } |
ced3cb9f | 764 | |
69b3331e | 765 | private: |
77e0bf4e FD |
766 | void |
767 | _M_check_rehashed(size_type __prev_count) | |
768 | { | |
769 | if (__prev_count != this->bucket_count()) | |
20a4550c | 770 | this->_M_invalidate_all(); |
77e0bf4e | 771 | } |
4b763dee FD |
772 | |
773 | void | |
774 | _M_invalidate(_Base_const_iterator __victim) | |
775 | { | |
776 | this->_M_invalidate_if( | |
777 | [__victim](_Base_const_iterator __it) { return __it == __victim; }); | |
778 | this->_M_invalidate_local_if( | |
779 | [__victim](_Base_const_local_iterator __it) | |
acc1d1a9 | 780 | { return __it == __victim; }); |
4b763dee FD |
781 | } |
782 | ||
783 | _Base_iterator | |
784 | _M_erase(_Base_const_iterator __victim) | |
785 | { | |
786 | _M_invalidate(__victim); | |
787 | size_type __bucket_count = this->bucket_count(); | |
788 | _Base_iterator __next = _Base::erase(__victim); | |
789 | _M_check_rehashed(__bucket_count); | |
790 | return __next; | |
791 | } | |
792 | ||
793 | #if __cplusplus > 201402L | |
794 | node_type | |
795 | _M_extract(_Base_const_iterator __victim) | |
796 | { | |
797 | _M_invalidate(__victim); | |
798 | return _Base::extract(__victim); | |
799 | } | |
800 | #endif | |
e63637ea BK |
801 | }; |
802 | ||
957f5fea VV |
803 | #if __cpp_deduction_guides >= 201606 |
804 | ||
805 | template<typename _InputIterator, | |
806 | typename _Hash = hash<__iter_key_t<_InputIterator>>, | |
807 | typename _Pred = equal_to<__iter_key_t<_InputIterator>>, | |
808 | typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, | |
809 | typename = _RequireInputIter<_InputIterator>, | |
c0cb38c2 FD |
810 | typename = _RequireNotAllocatorOrIntegral<_Hash>, |
811 | typename = _RequireNotAllocator<_Pred>, | |
957f5fea VV |
812 | typename = _RequireAllocator<_Allocator>> |
813 | unordered_map(_InputIterator, _InputIterator, | |
814 | typename unordered_map<int, int>::size_type = {}, | |
815 | _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) | |
816 | -> unordered_map<__iter_key_t<_InputIterator>, | |
817 | __iter_val_t<_InputIterator>, | |
818 | _Hash, _Pred, _Allocator>; | |
819 | ||
820 | template<typename _Key, typename _Tp, typename _Hash = hash<_Key>, | |
821 | typename _Pred = equal_to<_Key>, | |
822 | typename _Allocator = allocator<pair<const _Key, _Tp>>, | |
c0cb38c2 FD |
823 | typename = _RequireNotAllocatorOrIntegral<_Hash>, |
824 | typename = _RequireNotAllocator<_Pred>, | |
957f5fea VV |
825 | typename = _RequireAllocator<_Allocator>> |
826 | unordered_map(initializer_list<pair<_Key, _Tp>>, | |
827 | typename unordered_map<int, int>::size_type = {}, | |
828 | _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) | |
829 | -> unordered_map<_Key, _Tp, _Hash, _Pred, _Allocator>; | |
830 | ||
831 | template<typename _InputIterator, typename _Allocator, | |
832 | typename = _RequireInputIter<_InputIterator>, | |
833 | typename = _RequireAllocator<_Allocator>> | |
834 | unordered_map(_InputIterator, _InputIterator, | |
835 | typename unordered_map<int, int>::size_type, _Allocator) | |
836 | -> unordered_map<__iter_key_t<_InputIterator>, | |
837 | __iter_val_t<_InputIterator>, | |
838 | hash<__iter_key_t<_InputIterator>>, | |
839 | equal_to<__iter_key_t<_InputIterator>>, | |
840 | _Allocator>; | |
841 | ||
842 | template<typename _InputIterator, typename _Allocator, | |
843 | typename = _RequireInputIter<_InputIterator>, | |
844 | typename = _RequireAllocator<_Allocator>> | |
845 | unordered_map(_InputIterator, _InputIterator, _Allocator) | |
846 | -> unordered_map<__iter_key_t<_InputIterator>, | |
847 | __iter_val_t<_InputIterator>, | |
848 | hash<__iter_key_t<_InputIterator>>, | |
849 | equal_to<__iter_key_t<_InputIterator>>, | |
850 | _Allocator>; | |
851 | ||
852 | template<typename _InputIterator, typename _Hash, typename _Allocator, | |
853 | typename = _RequireInputIter<_InputIterator>, | |
c0cb38c2 | 854 | typename = _RequireNotAllocatorOrIntegral<_Hash>, |
957f5fea VV |
855 | typename = _RequireAllocator<_Allocator>> |
856 | unordered_map(_InputIterator, _InputIterator, | |
857 | typename unordered_map<int, int>::size_type, | |
858 | _Hash, _Allocator) | |
859 | -> unordered_map<__iter_key_t<_InputIterator>, | |
860 | __iter_val_t<_InputIterator>, _Hash, | |
861 | equal_to<__iter_key_t<_InputIterator>>, _Allocator>; | |
862 | ||
863 | template<typename _Key, typename _Tp, typename _Allocator, | |
864 | typename = _RequireAllocator<_Allocator>> | |
865 | unordered_map(initializer_list<pair<_Key, _Tp>>, | |
866 | typename unordered_map<int, int>::size_type, | |
867 | _Allocator) | |
868 | -> unordered_map<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; | |
869 | ||
870 | template<typename _Key, typename _Tp, typename _Allocator, | |
68e601d8 | 871 | typename = _RequireAllocator<_Allocator>> |
957f5fea VV |
872 | unordered_map(initializer_list<pair<_Key, _Tp>>, _Allocator) |
873 | -> unordered_map<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; | |
874 | ||
875 | template<typename _Key, typename _Tp, typename _Hash, typename _Allocator, | |
c0cb38c2 | 876 | typename = _RequireNotAllocatorOrIntegral<_Hash>, |
957f5fea VV |
877 | typename = _RequireAllocator<_Allocator>> |
878 | unordered_map(initializer_list<pair<_Key, _Tp>>, | |
879 | typename unordered_map<int, int>::size_type, | |
880 | _Hash, _Allocator) | |
881 | -> unordered_map<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>; | |
882 | ||
ae54d8cb | 883 | #if __glibcxx_containers_ranges // C++ >= 23 |
7cc40201 TK |
884 | template<ranges::input_range _Rg, |
885 | __not_allocator_like _Hash = hash<__detail::__range_key_type<_Rg>>, | |
886 | __not_allocator_like _Pred = equal_to<__detail::__range_key_type<_Rg>>, | |
887 | __allocator_like _Allocator = | |
888 | allocator<__detail::__range_to_alloc_type<_Rg>>> | |
889 | unordered_map(from_range_t, _Rg&&, unordered_map<int, int>::size_type = {}, | |
890 | _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) | |
891 | -> unordered_map<__detail::__range_key_type<_Rg>, | |
892 | __detail::__range_mapped_type<_Rg>, | |
893 | _Hash, _Pred, _Allocator>; | |
894 | ||
895 | template<ranges::input_range _Rg, | |
896 | __allocator_like _Allocator> | |
897 | unordered_map(from_range_t, _Rg&&, unordered_map<int, int>::size_type, | |
898 | _Allocator) | |
899 | -> unordered_map<__detail::__range_key_type<_Rg>, | |
900 | __detail::__range_mapped_type<_Rg>, | |
901 | hash<__detail::__range_key_type<_Rg>>, | |
902 | equal_to<__detail::__range_key_type<_Rg>>, | |
903 | _Allocator>; | |
904 | ||
905 | template<ranges::input_range _Rg, | |
906 | __allocator_like _Allocator> | |
907 | unordered_map(from_range_t, _Rg&&, _Allocator) | |
908 | -> unordered_map<__detail::__range_key_type<_Rg>, | |
909 | __detail::__range_mapped_type<_Rg>, | |
910 | hash<__detail::__range_key_type<_Rg>>, | |
911 | equal_to<__detail::__range_key_type<_Rg>>, | |
912 | _Allocator>; | |
913 | ||
914 | template<ranges::input_range _Rg, | |
915 | __not_allocator_like _Hash, | |
916 | __allocator_like _Allocator> | |
917 | unordered_map(from_range_t, _Rg&&, unordered_map<int, int>::size_type, | |
918 | _Hash, _Allocator) | |
919 | -> unordered_map<__detail::__range_key_type<_Rg>, | |
920 | __detail::__range_mapped_type<_Rg>, | |
921 | _Hash, equal_to<__detail::__range_key_type<_Rg>>, | |
922 | _Allocator>; | |
923 | #endif | |
957f5fea VV |
924 | #endif |
925 | ||
e63637ea BK |
926 | template<typename _Key, typename _Tp, typename _Hash, |
927 | typename _Pred, typename _Alloc> | |
69b3331e PC |
928 | inline void |
929 | swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, | |
930 | unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) | |
c5d9ec56 | 931 | noexcept(noexcept(__x.swap(__y))) |
69b3331e | 932 | { __x.swap(__y); } |
e63637ea | 933 | |
5dc22714 PC |
934 | template<typename _Key, typename _Tp, typename _Hash, |
935 | typename _Pred, typename _Alloc> | |
936 | inline bool | |
937 | operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, | |
938 | const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) | |
099e644e | 939 | { return __x._M_base() == __y._M_base(); } |
5dc22714 | 940 | |
7ab9c243 | 941 | #if __cpp_impl_three_way_comparison < 201907L |
5dc22714 PC |
942 | template<typename _Key, typename _Tp, typename _Hash, |
943 | typename _Pred, typename _Alloc> | |
944 | inline bool | |
945 | operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, | |
946 | const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) | |
947 | { return !(__x == __y); } | |
7ab9c243 | 948 | #endif |
e63637ea | 949 | |
1ceb9e06 | 950 | /// Class std::unordered_multimap with safety/checking/debug instrumentation. |
e63637ea | 951 | template<typename _Key, typename _Tp, |
ced3cb9f | 952 | typename _Hash = std::hash<_Key>, |
e63637ea | 953 | typename _Pred = std::equal_to<_Key>, |
03d7aff6 | 954 | typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > > |
e63637ea | 955 | class unordered_multimap |
15ee1a77 FD |
956 | : public __gnu_debug::_Safe_container< |
957 | unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc, | |
958 | __gnu_debug::_Safe_unordered_container>, | |
c0cb38c2 FD |
959 | public _GLIBCXX_STD_C::unordered_multimap< |
960 | _Key, _Tp, _Hash, _Pred, _Alloc> | |
e63637ea | 961 | { |
12ffa228 | 962 | typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, |
15ee1a77 FD |
963 | _Pred, _Alloc> _Base; |
964 | typedef __gnu_debug::_Safe_container<unordered_multimap, | |
965 | _Alloc, __gnu_debug::_Safe_unordered_container> _Safe; | |
966 | typedef typename _Base::const_iterator _Base_const_iterator; | |
967 | typedef typename _Base::iterator _Base_iterator; | |
77e0bf4e | 968 | typedef typename _Base::const_local_iterator _Base_const_local_iterator; |
15ee1a77 | 969 | typedef typename _Base::local_iterator _Base_local_iterator; |
0462b6aa | 970 | |
e9afbed0 FD |
971 | template<typename _ItT, typename _SeqT, typename _CatT> |
972 | friend class ::__gnu_debug::_Safe_iterator; | |
973 | template<typename _ItT, typename _SeqT> | |
974 | friend class ::__gnu_debug::_Safe_local_iterator; | |
975 | ||
eca833b8 JW |
976 | // Reference wrapper for base class. See PR libstdc++/90102. |
977 | struct _Base_ref | |
978 | { | |
979 | _Base_ref(const _Base& __r) : _M_ref(__r) { } | |
980 | ||
981 | const _Base& _M_ref; | |
982 | }; | |
983 | ||
e63637ea | 984 | public: |
15ee1a77 FD |
985 | typedef typename _Base::size_type size_type; |
986 | typedef typename _Base::hasher hasher; | |
987 | typedef typename _Base::key_equal key_equal; | |
988 | typedef typename _Base::allocator_type allocator_type; | |
989 | ||
990 | typedef typename _Base::key_type key_type; | |
991 | typedef typename _Base::value_type value_type; | |
f4b4ce15 | 992 | typedef typename _Base::mapped_type mapped_type; |
15ee1a77 | 993 | |
f4b4ce15 FD |
994 | typedef typename _Base::pointer pointer; |
995 | typedef typename _Base::const_pointer const_pointer; | |
996 | typedef typename _Base::reference reference; | |
997 | typedef typename _Base::const_reference const_reference; | |
15ee1a77 FD |
998 | typedef __gnu_debug::_Safe_iterator< |
999 | _Base_iterator, unordered_multimap> iterator; | |
1000 | typedef __gnu_debug::_Safe_iterator< | |
1001 | _Base_const_iterator, unordered_multimap> const_iterator; | |
77e0bf4e | 1002 | typedef __gnu_debug::_Safe_local_iterator< |
15ee1a77 | 1003 | _Base_local_iterator, unordered_multimap> local_iterator; |
77e0bf4e | 1004 | typedef __gnu_debug::_Safe_local_iterator< |
e9afbed0 | 1005 | _Base_const_local_iterator, unordered_multimap> const_local_iterator; |
f4b4ce15 | 1006 | typedef typename _Base::difference_type difference_type; |
e63637ea | 1007 | |
da27f556 FD |
1008 | unordered_multimap() = default; |
1009 | ||
e63637ea | 1010 | explicit |
da27f556 | 1011 | unordered_multimap(size_type __n, |
ced3cb9f PC |
1012 | const hasher& __hf = hasher(), |
1013 | const key_equal& __eql = key_equal(), | |
1014 | const allocator_type& __a = allocator_type()) | |
1015 | : _Base(__n, __hf, __eql, __a) { } | |
e63637ea BK |
1016 | |
1017 | template<typename _InputIterator> | |
15ee1a77 | 1018 | unordered_multimap(_InputIterator __first, _InputIterator __last, |
417e896e | 1019 | size_type __n = 0, |
15ee1a77 FD |
1020 | const hasher& __hf = hasher(), |
1021 | const key_equal& __eql = key_equal(), | |
ced3cb9f | 1022 | const allocator_type& __a = allocator_type()) |
90aabc7e FD |
1023 | : _Base(__gnu_debug::__base( |
1024 | __glibcxx_check_valid_constructor_range(__first, __last)), | |
1f5ca1a1 | 1025 | __gnu_debug::__base(__last), __n, |
4c2d93db | 1026 | __hf, __eql, __a) { } |
ced3cb9f | 1027 | |
0462b6aa | 1028 | unordered_multimap(const unordered_multimap&) = default; |
ced3cb9f | 1029 | |
eca833b8 JW |
1030 | unordered_multimap(_Base_ref __x) |
1031 | : _Base(__x._M_ref) { } | |
ced3cb9f | 1032 | |
0462b6aa FD |
1033 | unordered_multimap(unordered_multimap&&) = default; |
1034 | ||
1035 | explicit | |
1036 | unordered_multimap(const allocator_type& __a) | |
15ee1a77 | 1037 | : _Base(__a) { } |
0462b6aa FD |
1038 | |
1039 | unordered_multimap(const unordered_multimap& __umap, | |
1040 | const allocator_type& __a) | |
15ee1a77 | 1041 | : _Base(__umap, __a) { } |
0462b6aa FD |
1042 | |
1043 | unordered_multimap(unordered_multimap&& __umap, | |
1044 | const allocator_type& __a) | |
e9a53a4f FD |
1045 | noexcept( noexcept(_Base(std::move(__umap), __a)) ) |
1046 | : _Safe(std::move(__umap), __a), | |
1047 | _Base(std::move(__umap), __a) { } | |
e63637ea | 1048 | |
988499f4 | 1049 | unordered_multimap(initializer_list<value_type> __l, |
417e896e | 1050 | size_type __n = 0, |
988499f4 JM |
1051 | const hasher& __hf = hasher(), |
1052 | const key_equal& __eql = key_equal(), | |
1053 | const allocator_type& __a = allocator_type()) | |
4c2d93db | 1054 | : _Base(__l, __n, __hf, __eql, __a) { } |
e63637ea | 1055 | |
e55b80f5 FD |
1056 | unordered_multimap(size_type __n, const allocator_type& __a) |
1057 | : unordered_multimap(__n, hasher(), key_equal(), __a) | |
1058 | { } | |
1059 | ||
1060 | unordered_multimap(size_type __n, const hasher& __hf, | |
1061 | const allocator_type& __a) | |
1062 | : unordered_multimap(__n, __hf, key_equal(), __a) | |
1063 | { } | |
1064 | ||
1ecd95ea TK |
1065 | template<typename _InputIterator> |
1066 | unordered_multimap(_InputIterator __first, _InputIterator __last, | |
1067 | const allocator_type& __a) | |
1068 | : unordered_multimap(__first, __last, 0, hasher(), key_equal(), __a) | |
1069 | { } | |
1070 | ||
e55b80f5 FD |
1071 | template<typename _InputIterator> |
1072 | unordered_multimap(_InputIterator __first, _InputIterator __last, | |
1073 | size_type __n, | |
1074 | const allocator_type& __a) | |
12324b9a | 1075 | : unordered_multimap(__first, __last, __n, hasher(), key_equal(), __a) |
e55b80f5 FD |
1076 | { } |
1077 | ||
1078 | template<typename _InputIterator> | |
1079 | unordered_multimap(_InputIterator __first, _InputIterator __last, | |
1080 | size_type __n, const hasher& __hf, | |
1081 | const allocator_type& __a) | |
12324b9a | 1082 | : unordered_multimap(__first, __last, __n, __hf, key_equal(), __a) |
e55b80f5 FD |
1083 | { } |
1084 | ||
1ecd95ea TK |
1085 | unordered_multimap(initializer_list<value_type> __l, |
1086 | const allocator_type& __a) | |
1087 | : unordered_multimap(__l, 0, hasher(), key_equal(), __a) | |
1088 | { } | |
1089 | ||
e55b80f5 FD |
1090 | unordered_multimap(initializer_list<value_type> __l, |
1091 | size_type __n, | |
1092 | const allocator_type& __a) | |
12324b9a | 1093 | : unordered_multimap(__l, __n, hasher(), key_equal(), __a) |
e55b80f5 FD |
1094 | { } |
1095 | ||
1096 | unordered_multimap(initializer_list<value_type> __l, | |
1097 | size_type __n, const hasher& __hf, | |
1098 | const allocator_type& __a) | |
12324b9a | 1099 | : unordered_multimap(__l, __n, __hf, key_equal(), __a) |
e55b80f5 FD |
1100 | { } |
1101 | ||
ae54d8cb | 1102 | #if __glibcxx_containers_ranges // C++ >= 23 |
7cc40201 TK |
1103 | template<__detail::__container_compatible_range<value_type> _Rg> |
1104 | unordered_multimap(from_range_t, _Rg&& __rg, | |
1105 | size_type __n = 0, | |
1106 | const hasher& __hf = hasher(), | |
1107 | const key_equal& __eql = key_equal(), | |
1108 | const allocator_type& __a = allocator_type()) | |
1109 | : _Base(from_range, std::forward<_Rg>(__rg), __n, __hf, __eql, __a) | |
1110 | { } | |
1111 | ||
1112 | template<__detail::__container_compatible_range<value_type> _Rg> | |
1113 | unordered_multimap(from_range_t, _Rg&& __rg, const allocator_type& __a) | |
1114 | : _Base(from_range, std::forward<_Rg>(__rg), __a) | |
1115 | { } | |
1116 | ||
1117 | template<__detail::__container_compatible_range<value_type> _Rg> | |
1118 | unordered_multimap(from_range_t, _Rg&& __rg, size_type __n, | |
1119 | const allocator_type& __a) | |
1120 | : _Base(from_range, std::forward<_Rg>(__rg), __n, __a) | |
1121 | { } | |
1122 | ||
1123 | template<__detail::__container_compatible_range<value_type> _Rg> | |
1124 | unordered_multimap(from_range_t, _Rg&& __rg, size_type __n, | |
1125 | const hasher& __hf, const allocator_type& __a) | |
1126 | : _Base(from_range, std::forward<_Rg>(__rg), __n, __hf, __a) | |
1127 | { } | |
1128 | #endif | |
1129 | ||
15ee1a77 | 1130 | ~unordered_multimap() = default; |
6f59ea25 | 1131 | |
ced3cb9f | 1132 | unordered_multimap& |
15ee1a77 | 1133 | operator=(const unordered_multimap&) = default; |
69b3331e PC |
1134 | |
1135 | unordered_multimap& | |
15ee1a77 | 1136 | operator=(unordered_multimap&&) = default; |
69b3331e | 1137 | |
988499f4 JM |
1138 | unordered_multimap& |
1139 | operator=(initializer_list<value_type> __l) | |
1140 | { | |
e9a53a4f | 1141 | _Base::operator=(__l); |
0462b6aa | 1142 | this->_M_invalidate_all(); |
988499f4 JM |
1143 | return *this; |
1144 | } | |
1145 | ||
f4b4ce15 FD |
1146 | using _Base::get_allocator; |
1147 | using _Base::empty; | |
1148 | using _Base::size; | |
1149 | using _Base::max_size; | |
1150 | ||
e63637ea | 1151 | void |
ff74fd13 | 1152 | swap(unordered_multimap& __x) |
c5d9ec56 | 1153 | noexcept( noexcept(declval<_Base&>().swap(__x)) ) |
e63637ea | 1154 | { |
15ee1a77 | 1155 | _Safe::_M_swap(__x); |
ced3cb9f | 1156 | _Base::swap(__x); |
e63637ea | 1157 | } |
69b3331e PC |
1158 | |
1159 | void | |
d3677132 | 1160 | clear() noexcept |
69b3331e PC |
1161 | { |
1162 | _Base::clear(); | |
1163 | this->_M_invalidate_all(); | |
1164 | } | |
1165 | ||
15ee1a77 | 1166 | iterator |
d3677132 | 1167 | begin() noexcept |
4b763dee | 1168 | { return { _Base::begin(), this }; } |
ced3cb9f PC |
1169 | |
1170 | const_iterator | |
d3677132 | 1171 | begin() const noexcept |
4b763dee | 1172 | { return { _Base::begin(), this }; } |
ced3cb9f PC |
1173 | |
1174 | iterator | |
d3677132 | 1175 | end() noexcept |
4b763dee | 1176 | { return { _Base::end(), this }; } |
ced3cb9f PC |
1177 | |
1178 | const_iterator | |
d3677132 | 1179 | end() const noexcept |
4b763dee | 1180 | { return { _Base::end(), this }; } |
ced3cb9f PC |
1181 | |
1182 | const_iterator | |
d3677132 | 1183 | cbegin() const noexcept |
4b763dee | 1184 | { return { _Base::cbegin(), this }; } |
ced3cb9f PC |
1185 | |
1186 | const_iterator | |
d3677132 | 1187 | cend() const noexcept |
4b763dee | 1188 | { return { _Base::cend(), this }; } |
ced3cb9f PC |
1189 | |
1190 | // local versions | |
77e0bf4e FD |
1191 | local_iterator |
1192 | begin(size_type __b) | |
7181e991 FD |
1193 | { |
1194 | __glibcxx_check_bucket_index(__b); | |
4b763dee | 1195 | return { _Base::begin(__b), this }; |
7181e991 | 1196 | } |
77e0bf4e FD |
1197 | |
1198 | local_iterator | |
1199 | end(size_type __b) | |
7181e991 FD |
1200 | { |
1201 | __glibcxx_check_bucket_index(__b); | |
4b763dee | 1202 | return { _Base::end(__b), this }; |
7181e991 | 1203 | } |
77e0bf4e FD |
1204 | |
1205 | const_local_iterator | |
1206 | begin(size_type __b) const | |
7181e991 FD |
1207 | { |
1208 | __glibcxx_check_bucket_index(__b); | |
4b763dee | 1209 | return { _Base::begin(__b), this }; |
7181e991 | 1210 | } |
77e0bf4e FD |
1211 | |
1212 | const_local_iterator | |
1213 | end(size_type __b) const | |
7181e991 FD |
1214 | { |
1215 | __glibcxx_check_bucket_index(__b); | |
4b763dee | 1216 | return { _Base::end(__b), this }; |
7181e991 | 1217 | } |
77e0bf4e FD |
1218 | |
1219 | const_local_iterator | |
1220 | cbegin(size_type __b) const | |
7181e991 FD |
1221 | { |
1222 | __glibcxx_check_bucket_index(__b); | |
4b763dee | 1223 | return { _Base::cbegin(__b), this }; |
7181e991 | 1224 | } |
77e0bf4e FD |
1225 | |
1226 | const_local_iterator | |
1227 | cend(size_type __b) const | |
7181e991 FD |
1228 | { |
1229 | __glibcxx_check_bucket_index(__b); | |
4b763dee | 1230 | return { _Base::cend(__b), this }; |
7181e991 FD |
1231 | } |
1232 | ||
f4b4ce15 FD |
1233 | using _Base::bucket_count; |
1234 | using _Base::max_bucket_count; | |
1235 | using _Base::bucket; | |
1236 | ||
7181e991 FD |
1237 | size_type |
1238 | bucket_size(size_type __b) const | |
1239 | { | |
1240 | __glibcxx_check_bucket_index(__b); | |
1241 | return _Base::bucket_size(__b); | |
1242 | } | |
ced3cb9f | 1243 | |
14cbb5d8 FD |
1244 | float |
1245 | max_load_factor() const noexcept | |
1246 | { return _Base::max_load_factor(); } | |
1247 | ||
1248 | void | |
1249 | max_load_factor(float __f) | |
1250 | { | |
1251 | __glibcxx_check_max_load_factor(__f); | |
1252 | _Base::max_load_factor(__f); | |
1253 | } | |
1254 | ||
9b81593b FD |
1255 | template<typename... _Args> |
1256 | iterator | |
1257 | emplace(_Args&&... __args) | |
1258 | { | |
1259 | size_type __bucket_count = this->bucket_count(); | |
4b763dee | 1260 | auto __it = _Base::emplace(std::forward<_Args>(__args)...); |
9b81593b | 1261 | _M_check_rehashed(__bucket_count); |
4b763dee | 1262 | return { __it, this }; |
9b81593b FD |
1263 | } |
1264 | ||
1265 | template<typename... _Args> | |
1266 | iterator | |
1267 | emplace_hint(const_iterator __hint, _Args&&... __args) | |
1268 | { | |
1269 | __glibcxx_check_insert(__hint); | |
1270 | size_type __bucket_count = this->bucket_count(); | |
4b763dee FD |
1271 | auto __it = _Base::emplace_hint(__hint.base(), |
1272 | std::forward<_Args>(__args)...); | |
9b81593b | 1273 | _M_check_rehashed(__bucket_count); |
4b763dee | 1274 | return { __it, this }; |
9b81593b FD |
1275 | } |
1276 | ||
ced3cb9f PC |
1277 | iterator |
1278 | insert(const value_type& __obj) | |
77e0bf4e FD |
1279 | { |
1280 | size_type __bucket_count = this->bucket_count(); | |
4b763dee | 1281 | auto __it = _Base::insert(__obj); |
77e0bf4e | 1282 | _M_check_rehashed(__bucket_count); |
4b763dee | 1283 | return { __it, this }; |
77e0bf4e | 1284 | } |
ced3cb9f | 1285 | |
1679da15 FD |
1286 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1287 | // 2354. Unnecessary copying when inserting into maps with braced-init | |
1288 | iterator | |
1289 | insert(value_type&& __x) | |
1290 | { | |
1291 | size_type __bucket_count = this->bucket_count(); | |
1292 | auto __it = _Base::insert(std::move(__x)); | |
1293 | _M_check_rehashed(__bucket_count); | |
1294 | return { __it, this }; | |
1295 | } | |
1296 | ||
ced3cb9f | 1297 | iterator |
d66411ba FD |
1298 | insert(const_iterator __hint, const value_type& __obj) |
1299 | { | |
1300 | __glibcxx_check_insert(__hint); | |
77e0bf4e | 1301 | size_type __bucket_count = this->bucket_count(); |
4b763dee | 1302 | auto __it = _Base::insert(__hint.base(), __obj); |
77e0bf4e | 1303 | _M_check_rehashed(__bucket_count); |
4b763dee | 1304 | return { __it, this }; |
d66411ba | 1305 | } |
ced3cb9f | 1306 | |
1679da15 FD |
1307 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1308 | // 2354. Unnecessary copying when inserting into maps with braced-init | |
1309 | iterator | |
1310 | insert(const_iterator __hint, value_type&& __x) | |
1311 | { | |
1312 | __glibcxx_check_insert(__hint); | |
1313 | size_type __bucket_count = this->bucket_count(); | |
1314 | auto __it = _Base::insert(__hint.base(), std::move(__x)); | |
1315 | _M_check_rehashed(__bucket_count); | |
4b763dee | 1316 | return { __it, this }; |
1679da15 FD |
1317 | } |
1318 | ||
fb7342fd | 1319 | template<typename _Pair, typename = typename |
57cee56a PC |
1320 | std::enable_if<std::is_constructible<value_type, |
1321 | _Pair&&>::value>::type> | |
77e0bf4e FD |
1322 | iterator |
1323 | insert(_Pair&& __obj) | |
1324 | { | |
1325 | size_type __bucket_count = this->bucket_count(); | |
4b763dee | 1326 | auto __it = _Base::insert(std::forward<_Pair>(__obj)); |
77e0bf4e | 1327 | _M_check_rehashed(__bucket_count); |
4b763dee | 1328 | return { __it, this }; |
77e0bf4e | 1329 | } |
fb7342fd PC |
1330 | |
1331 | template<typename _Pair, typename = typename | |
57cee56a PC |
1332 | std::enable_if<std::is_constructible<value_type, |
1333 | _Pair&&>::value>::type> | |
afe96d41 | 1334 | iterator |
d66411ba FD |
1335 | insert(const_iterator __hint, _Pair&& __obj) |
1336 | { | |
1337 | __glibcxx_check_insert(__hint); | |
77e0bf4e | 1338 | size_type __bucket_count = this->bucket_count(); |
4b763dee | 1339 | auto __it = _Base::insert(__hint.base(), std::forward<_Pair>(__obj)); |
77e0bf4e | 1340 | _M_check_rehashed(__bucket_count); |
4b763dee | 1341 | return { __it, this }; |
d66411ba | 1342 | } |
fb7342fd | 1343 | |
ced3cb9f PC |
1344 | void |
1345 | insert(std::initializer_list<value_type> __l) | |
1346 | { _Base::insert(__l); } | |
1347 | ||
1348 | template<typename _InputIterator> | |
77e0bf4e FD |
1349 | void |
1350 | insert(_InputIterator __first, _InputIterator __last) | |
1351 | { | |
24167c42 FD |
1352 | typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist; |
1353 | __glibcxx_check_valid_range2(__first, __last, __dist); | |
77e0bf4e | 1354 | size_type __bucket_count = this->bucket_count(); |
24167c42 FD |
1355 | |
1356 | if (__dist.second >= __gnu_debug::__dp_sign) | |
1357 | _Base::insert(__gnu_debug::__unsafe(__first), | |
1358 | __gnu_debug::__unsafe(__last)); | |
1359 | else | |
1360 | _Base::insert(__first, __last); | |
1361 | ||
77e0bf4e | 1362 | _M_check_rehashed(__bucket_count); |
ced3cb9f PC |
1363 | } |
1364 | ||
2dbe56bd JW |
1365 | #if __cplusplus > 201402L |
1366 | using node_type = typename _Base::node_type; | |
1367 | ||
1368 | node_type | |
1369 | extract(const_iterator __position) | |
1370 | { | |
1371 | __glibcxx_check_erase(__position); | |
4b763dee | 1372 | return _M_extract(__position.base()); |
2dbe56bd JW |
1373 | } |
1374 | ||
1375 | node_type | |
1376 | extract(const key_type& __key) | |
1377 | { | |
4b763dee FD |
1378 | const auto __position = _Base::find(__key); |
1379 | if (__position != _Base::end()) | |
1380 | return _M_extract(__position); | |
2dbe56bd JW |
1381 | return {}; |
1382 | } | |
1383 | ||
1384 | iterator | |
1385 | insert(node_type&& __nh) | |
4b763dee | 1386 | { return { _Base::insert(std::move(__nh)), this }; } |
2dbe56bd JW |
1387 | |
1388 | iterator | |
1389 | insert(const_iterator __hint, node_type&& __nh) | |
1390 | { | |
1391 | __glibcxx_check_insert(__hint); | |
4b763dee | 1392 | return { _Base::insert(__hint.base(), std::move(__nh)), this }; |
2dbe56bd JW |
1393 | } |
1394 | ||
f4b4ce15 FD |
1395 | template<typename _H2, typename _P2> |
1396 | void | |
1397 | merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>& __source) | |
1398 | { | |
1399 | auto __guard | |
1400 | = _Safe::_S_umc_guard(std::__detail::_Select1st{}, __source); | |
e9a53a4f | 1401 | _Base::merge(__source); |
f4b4ce15 FD |
1402 | } |
1403 | ||
1404 | template<typename _H2, typename _P2> | |
1405 | void | |
1406 | merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>&& __source) | |
1407 | { merge(__source); } | |
1408 | ||
1409 | template<typename _H2, typename _P2> | |
1410 | void | |
1411 | merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>& __source) | |
1412 | { | |
1413 | auto __guard | |
1414 | = _Safe::_S_uc_guard(std::__detail::_Select1st{}, __source); | |
e9a53a4f | 1415 | _Base::merge(__source); |
f4b4ce15 FD |
1416 | } |
1417 | ||
1418 | template<typename _H2, typename _P2> | |
1419 | void | |
1420 | merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>&& __source) | |
1421 | { merge(__source); } | |
2dbe56bd JW |
1422 | #endif // C++17 |
1423 | ||
f4b4ce15 FD |
1424 | using _Base::hash_function; |
1425 | using _Base::key_eq; | |
1426 | ||
ced3cb9f PC |
1427 | iterator |
1428 | find(const key_type& __key) | |
4b763dee | 1429 | { return { _Base::find(__key), this }; } |
ced3cb9f | 1430 | |
d2b1a684 FD |
1431 | #if __cplusplus > 201703L |
1432 | template<typename _Kt, | |
1433 | typename = std::__has_is_transparent_t<_Hash, _Kt>, | |
1434 | typename = std::__has_is_transparent_t<_Pred, _Kt>> | |
1435 | iterator | |
1436 | find(const _Kt& __k) | |
1437 | { return { _Base::find(__k), this }; } | |
1438 | #endif | |
1439 | ||
ced3cb9f PC |
1440 | const_iterator |
1441 | find(const key_type& __key) const | |
4b763dee | 1442 | { return { _Base::find(__key), this }; } |
ced3cb9f | 1443 | |
d2b1a684 FD |
1444 | #if __cplusplus > 201703L |
1445 | template<typename _Kt, | |
1446 | typename = std::__has_is_transparent_t<_Hash, _Kt>, | |
1447 | typename = std::__has_is_transparent_t<_Pred, _Kt>> | |
1448 | const_iterator | |
1449 | find(const _Kt& __k) const | |
1450 | { return { _Base::find(__k), this }; } | |
1451 | #endif | |
1452 | ||
f4b4ce15 FD |
1453 | using _Base::count; |
1454 | #if __cplusplus > 201703L | |
1455 | using _Base::contains; | |
1456 | #endif | |
1457 | ||
ced3cb9f PC |
1458 | std::pair<iterator, iterator> |
1459 | equal_range(const key_type& __key) | |
1460 | { | |
4b763dee FD |
1461 | auto __res = _Base::equal_range(__key); |
1462 | return { { __res.first, this }, { __res.second, this } }; | |
ced3cb9f PC |
1463 | } |
1464 | ||
d2b1a684 FD |
1465 | #if __cplusplus > 201703L |
1466 | template<typename _Kt, | |
1467 | typename = std::__has_is_transparent_t<_Hash, _Kt>, | |
1468 | typename = std::__has_is_transparent_t<_Pred, _Kt>> | |
1469 | std::pair<iterator, iterator> | |
1470 | equal_range(const _Kt& __k) | |
1471 | { | |
1472 | auto __res = _Base::equal_range(__k); | |
1473 | return { { __res.first, this }, { __res.second, this } }; | |
1474 | } | |
1475 | #endif | |
1476 | ||
ced3cb9f PC |
1477 | std::pair<const_iterator, const_iterator> |
1478 | equal_range(const key_type& __key) const | |
1479 | { | |
4b763dee FD |
1480 | auto __res = _Base::equal_range(__key); |
1481 | return { { __res.first, this }, { __res.second, this } }; | |
ced3cb9f PC |
1482 | } |
1483 | ||
d2b1a684 FD |
1484 | #if __cplusplus > 201703L |
1485 | template<typename _Kt, | |
1486 | typename = std::__has_is_transparent_t<_Hash, _Kt>, | |
1487 | typename = std::__has_is_transparent_t<_Pred, _Kt>> | |
1488 | std::pair<const_iterator, const_iterator> | |
1489 | equal_range(const _Kt& __k) const | |
1490 | { | |
1491 | auto __res = _Base::equal_range(__k); | |
1492 | return { { __res.first, this }, { __res.second, this } }; | |
1493 | } | |
1494 | #endif | |
1495 | ||
ced3cb9f PC |
1496 | size_type |
1497 | erase(const key_type& __key) | |
1498 | { | |
1499 | size_type __ret(0); | |
77e0bf4e | 1500 | size_type __bucket_count = this->bucket_count(); |
4b763dee FD |
1501 | auto __pair = _Base::equal_range(__key); |
1502 | for (auto __victim = __pair.first; __victim != __pair.second;) | |
ced3cb9f | 1503 | { |
4b763dee FD |
1504 | _M_invalidate(__victim); |
1505 | __victim = _Base::erase(__victim); | |
d3b8263e | 1506 | ++__ret; |
ced3cb9f | 1507 | } |
4b763dee | 1508 | |
77e0bf4e | 1509 | _M_check_rehashed(__bucket_count); |
ced3cb9f PC |
1510 | return __ret; |
1511 | } | |
1512 | ||
d723ced2 | 1513 | iterator |
ced3cb9f PC |
1514 | erase(const_iterator __it) |
1515 | { | |
1516 | __glibcxx_check_erase(__it); | |
4b763dee | 1517 | return { _M_erase(__it.base()), this }; |
ced3cb9f PC |
1518 | } |
1519 | ||
5f40d34b FD |
1520 | _Base_iterator |
1521 | erase(_Base_const_iterator __it) | |
1522 | { | |
1523 | __glibcxx_check_erase2(__it); | |
1524 | return _M_erase(__it); | |
1525 | } | |
1526 | ||
6dc88283 PC |
1527 | iterator |
1528 | erase(iterator __it) | |
4b763dee FD |
1529 | { |
1530 | __glibcxx_check_erase(__it); | |
1531 | return { _M_erase(__it.base()), this }; | |
1532 | } | |
6dc88283 | 1533 | |
d723ced2 | 1534 | iterator |
ced3cb9f PC |
1535 | erase(const_iterator __first, const_iterator __last) |
1536 | { | |
1537 | __glibcxx_check_erase_range(__first, __last); | |
4b763dee | 1538 | for (auto __tmp = __first.base(); __tmp != __last.base(); ++__tmp) |
afe96d41 | 1539 | { |
4b763dee | 1540 | _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::cend(), |
afe96d41 FD |
1541 | _M_message(__gnu_debug::__msg_valid_range) |
1542 | ._M_iterator(__first, "first") | |
1543 | ._M_iterator(__last, "last")); | |
4b763dee | 1544 | _M_invalidate(__tmp); |
afe96d41 | 1545 | } |
4b763dee | 1546 | |
77e0bf4e | 1547 | size_type __bucket_count = this->bucket_count(); |
4b763dee | 1548 | auto __next = _Base::erase(__first.base(), __last.base()); |
77e0bf4e | 1549 | _M_check_rehashed(__bucket_count); |
4b763dee | 1550 | return { __next, this }; |
ced3cb9f PC |
1551 | } |
1552 | ||
f4b4ce15 FD |
1553 | using _Base::rehash; |
1554 | using _Base::reserve; | |
1555 | ||
ced3cb9f | 1556 | _Base& |
15ee1a77 | 1557 | _M_base() noexcept { return *this; } |
ced3cb9f PC |
1558 | |
1559 | const _Base& | |
d3677132 | 1560 | _M_base() const noexcept { return *this; } |
ced3cb9f | 1561 | |
69b3331e | 1562 | private: |
77e0bf4e FD |
1563 | void |
1564 | _M_check_rehashed(size_type __prev_count) | |
1565 | { | |
1566 | if (__prev_count != this->bucket_count()) | |
20a4550c | 1567 | this->_M_invalidate_all(); |
77e0bf4e | 1568 | } |
4b763dee FD |
1569 | |
1570 | void | |
1571 | _M_invalidate(_Base_const_iterator __victim) | |
1572 | { | |
1573 | this->_M_invalidate_if( | |
1574 | [__victim](_Base_const_iterator __it) { return __it == __victim; }); | |
1575 | this->_M_invalidate_local_if( | |
1576 | [__victim](_Base_const_local_iterator __it) | |
acc1d1a9 | 1577 | { return __it == __victim; }); |
4b763dee FD |
1578 | } |
1579 | ||
1580 | _Base_iterator | |
1581 | _M_erase(_Base_const_iterator __victim) | |
1582 | { | |
1583 | _M_invalidate(__victim); | |
1584 | size_type __bucket_count = this->bucket_count(); | |
1585 | _Base_iterator __next = _Base::erase(__victim); | |
1586 | _M_check_rehashed(__bucket_count); | |
1587 | return __next; | |
1588 | } | |
1589 | ||
1590 | #if __cplusplus > 201402L | |
1591 | node_type | |
1592 | _M_extract(_Base_const_iterator __victim) | |
1593 | { | |
1594 | _M_invalidate(__victim); | |
1595 | return _Base::extract(__victim); | |
1596 | } | |
1597 | #endif | |
e63637ea BK |
1598 | }; |
1599 | ||
957f5fea VV |
1600 | #if __cpp_deduction_guides >= 201606 |
1601 | ||
1602 | template<typename _InputIterator, | |
1603 | typename _Hash = hash<__iter_key_t<_InputIterator>>, | |
1604 | typename _Pred = equal_to<__iter_key_t<_InputIterator>>, | |
1605 | typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, | |
1606 | typename = _RequireInputIter<_InputIterator>, | |
c0cb38c2 FD |
1607 | typename = _RequireNotAllocatorOrIntegral<_Hash>, |
1608 | typename = _RequireNotAllocator<_Pred>, | |
957f5fea VV |
1609 | typename = _RequireAllocator<_Allocator>> |
1610 | unordered_multimap(_InputIterator, _InputIterator, | |
1611 | unordered_multimap<int, int>::size_type = {}, | |
1612 | _Hash = _Hash(), _Pred = _Pred(), | |
1613 | _Allocator = _Allocator()) | |
1614 | -> unordered_multimap<__iter_key_t<_InputIterator>, | |
1615 | __iter_val_t<_InputIterator>, _Hash, _Pred, | |
1616 | _Allocator>; | |
1617 | ||
1618 | template<typename _Key, typename _Tp, typename _Hash = hash<_Key>, | |
1619 | typename _Pred = equal_to<_Key>, | |
1620 | typename _Allocator = allocator<pair<const _Key, _Tp>>, | |
c0cb38c2 FD |
1621 | typename = _RequireNotAllocatorOrIntegral<_Hash>, |
1622 | typename = _RequireNotAllocator<_Pred>, | |
957f5fea VV |
1623 | typename = _RequireAllocator<_Allocator>> |
1624 | unordered_multimap(initializer_list<pair<_Key, _Tp>>, | |
1625 | unordered_multimap<int, int>::size_type = {}, | |
1626 | _Hash = _Hash(), _Pred = _Pred(), | |
1627 | _Allocator = _Allocator()) | |
1628 | -> unordered_multimap<_Key, _Tp, _Hash, _Pred, _Allocator>; | |
1629 | ||
1630 | template<typename _InputIterator, typename _Allocator, | |
1631 | typename = _RequireInputIter<_InputIterator>, | |
1632 | typename = _RequireAllocator<_Allocator>> | |
1633 | unordered_multimap(_InputIterator, _InputIterator, | |
1634 | unordered_multimap<int, int>::size_type, _Allocator) | |
1635 | -> unordered_multimap<__iter_key_t<_InputIterator>, | |
1636 | __iter_val_t<_InputIterator>, | |
1637 | hash<__iter_key_t<_InputIterator>>, | |
1638 | equal_to<__iter_key_t<_InputIterator>>, _Allocator>; | |
1639 | ||
1640 | template<typename _InputIterator, typename _Allocator, | |
1641 | typename = _RequireInputIter<_InputIterator>, | |
1642 | typename = _RequireAllocator<_Allocator>> | |
1643 | unordered_multimap(_InputIterator, _InputIterator, _Allocator) | |
1644 | -> unordered_multimap<__iter_key_t<_InputIterator>, | |
1645 | __iter_val_t<_InputIterator>, | |
1646 | hash<__iter_key_t<_InputIterator>>, | |
1647 | equal_to<__iter_key_t<_InputIterator>>, _Allocator>; | |
1648 | ||
1649 | template<typename _InputIterator, typename _Hash, typename _Allocator, | |
1650 | typename = _RequireInputIter<_InputIterator>, | |
c0cb38c2 | 1651 | typename = _RequireNotAllocatorOrIntegral<_Hash>, |
957f5fea VV |
1652 | typename = _RequireAllocator<_Allocator>> |
1653 | unordered_multimap(_InputIterator, _InputIterator, | |
1654 | unordered_multimap<int, int>::size_type, _Hash, | |
1655 | _Allocator) | |
1656 | -> unordered_multimap<__iter_key_t<_InputIterator>, | |
1657 | __iter_val_t<_InputIterator>, _Hash, | |
1658 | equal_to<__iter_key_t<_InputIterator>>, _Allocator>; | |
1659 | ||
1660 | template<typename _Key, typename _Tp, typename _Allocator, | |
1661 | typename = _RequireAllocator<_Allocator>> | |
1662 | unordered_multimap(initializer_list<pair<_Key, _Tp>>, | |
1663 | unordered_multimap<int, int>::size_type, | |
1664 | _Allocator) | |
1665 | -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; | |
1666 | ||
1667 | template<typename _Key, typename _Tp, typename _Allocator, | |
1668 | typename = _RequireAllocator<_Allocator>> | |
1669 | unordered_multimap(initializer_list<pair<_Key, _Tp>>, _Allocator) | |
1670 | -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; | |
1671 | ||
1672 | template<typename _Key, typename _Tp, typename _Hash, typename _Allocator, | |
c0cb38c2 | 1673 | typename = _RequireNotAllocatorOrIntegral<_Hash>, |
957f5fea VV |
1674 | typename = _RequireAllocator<_Allocator>> |
1675 | unordered_multimap(initializer_list<pair<_Key, _Tp>>, | |
1676 | unordered_multimap<int, int>::size_type, | |
1677 | _Hash, _Allocator) | |
1678 | -> unordered_multimap<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>; | |
1679 | ||
ae54d8cb | 1680 | #if __glibcxx_containers_ranges // C++ >= 23 |
7cc40201 TK |
1681 | template<ranges::input_range _Rg, |
1682 | __not_allocator_like _Hash = hash<__detail::__range_key_type<_Rg>>, | |
1683 | __not_allocator_like _Pred = equal_to<__detail::__range_key_type<_Rg>>, | |
1684 | __allocator_like _Allocator = | |
1685 | allocator<__detail::__range_to_alloc_type<_Rg>>> | |
1686 | unordered_multimap(from_range_t, _Rg&&, | |
1687 | unordered_multimap<int, int>::size_type = {}, | |
1688 | _Hash = _Hash(), _Pred = _Pred(), | |
1689 | _Allocator = _Allocator()) | |
1690 | -> unordered_multimap<__detail::__range_key_type<_Rg>, | |
1691 | __detail::__range_mapped_type<_Rg>, | |
1692 | _Hash, _Pred, _Allocator>; | |
1693 | ||
1694 | template<ranges::input_range _Rg, | |
1695 | __allocator_like _Allocator> | |
1696 | unordered_multimap(from_range_t, _Rg&&, unordered_multimap<int, int>::size_type, | |
1697 | _Allocator) | |
1698 | -> unordered_multimap<__detail::__range_key_type<_Rg>, | |
1699 | __detail::__range_mapped_type<_Rg>, | |
1700 | hash<__detail::__range_key_type<_Rg>>, | |
1701 | equal_to<__detail::__range_key_type<_Rg>>, | |
1702 | _Allocator>; | |
1703 | ||
1704 | template<ranges::input_range _Rg, | |
1705 | __allocator_like _Allocator> | |
1706 | unordered_multimap(from_range_t, _Rg&&, _Allocator) | |
1707 | -> unordered_multimap<__detail::__range_key_type<_Rg>, | |
1708 | __detail::__range_mapped_type<_Rg>, | |
1709 | hash<__detail::__range_key_type<_Rg>>, | |
1710 | equal_to<__detail::__range_key_type<_Rg>>, | |
1711 | _Allocator>; | |
1712 | ||
1713 | template<ranges::input_range _Rg, | |
1714 | __not_allocator_like _Hash, | |
1715 | __allocator_like _Allocator> | |
1716 | unordered_multimap(from_range_t, _Rg&&, | |
1717 | unordered_multimap<int, int>::size_type, | |
1718 | _Hash, _Allocator) | |
1719 | -> unordered_multimap<__detail::__range_key_type<_Rg>, | |
1720 | __detail::__range_mapped_type<_Rg>, | |
1721 | _Hash, equal_to<__detail::__range_key_type<_Rg>>, | |
1722 | _Allocator>; | |
1723 | #endif | |
957f5fea VV |
1724 | #endif |
1725 | ||
e63637ea BK |
1726 | template<typename _Key, typename _Tp, typename _Hash, |
1727 | typename _Pred, typename _Alloc> | |
69b3331e PC |
1728 | inline void |
1729 | swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, | |
1730 | unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) | |
c5d9ec56 | 1731 | noexcept(noexcept(__x.swap(__y))) |
69b3331e | 1732 | { __x.swap(__y); } |
e63637ea | 1733 | |
5dc22714 PC |
1734 | template<typename _Key, typename _Tp, typename _Hash, |
1735 | typename _Pred, typename _Alloc> | |
1736 | inline bool | |
1737 | operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, | |
1738 | const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) | |
099e644e | 1739 | { return __x._M_base() == __y._M_base(); } |
5dc22714 | 1740 | |
7ab9c243 | 1741 | #if __cpp_impl_three_way_comparison < 201907L |
5dc22714 PC |
1742 | template<typename _Key, typename _Tp, typename _Hash, |
1743 | typename _Pred, typename _Alloc> | |
1744 | inline bool | |
1745 | operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, | |
1746 | const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) | |
1747 | { return !(__x == __y); } | |
7ab9c243 | 1748 | #endif |
5dc22714 | 1749 | |
e63637ea BK |
1750 | } // namespace __debug |
1751 | } // namespace std | |
1752 | ||
734f5023 | 1753 | #endif // C++11 |
c878d6ba | 1754 | |
e63637ea | 1755 | #endif |