]>
Commit | Line | Data |
---|---|---|
1 | // Debugging unordered_map/unordered_multimap implementation -*- C++ -*- | |
2 | ||
3 | // Copyright (C) 2003-2025 Free Software Foundation, Inc. | |
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 | |
8 | // Free Software Foundation; either version 3, or (at your option) | |
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 | ||
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/>. | |
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 | ||
32 | #ifdef _GLIBCXX_SYSHDR | |
33 | #pragma GCC system_header | |
34 | #endif | |
35 | ||
36 | #if __cplusplus < 201103L | |
37 | # include <bits/c++0x_warning.h> | |
38 | #else | |
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 | ||
49 | # include <unordered_map> | |
50 | ||
51 | #include <debug/safe_unordered_container.h> | |
52 | #include <debug/safe_container.h> | |
53 | #include <debug/safe_iterator.h> | |
54 | #include <debug/safe_local_iterator.h> | |
55 | ||
56 | namespace std _GLIBCXX_VISIBILITY(default) | |
57 | { | |
58 | namespace __debug | |
59 | { | |
60 | /// Class std::unordered_map with safety/checking/debug instrumentation. | |
61 | template<typename _Key, typename _Tp, | |
62 | typename _Hash = std::hash<_Key>, | |
63 | typename _Pred = std::equal_to<_Key>, | |
64 | typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > > | |
65 | class unordered_map | |
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> | |
70 | { | |
71 | typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, | |
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; | |
80 | ||
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 | ||
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 | ||
94 | public: | |
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; | |
102 | typedef typename _Base::mapped_type mapped_type; | |
103 | ||
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; | |
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; | |
116 | typedef typename _Base::difference_type difference_type; | |
117 | ||
118 | unordered_map() = default; | |
119 | ||
120 | explicit | |
121 | unordered_map(size_type __n, | |
122 | const hasher& __hf = hasher(), | |
123 | const key_equal& __eql = key_equal(), | |
124 | const allocator_type& __a = allocator_type()) | |
125 | : _Base(__n, __hf, __eql, __a) { } | |
126 | ||
127 | template<typename _InputIterator> | |
128 | unordered_map(_InputIterator __first, _InputIterator __last, | |
129 | size_type __n = 0, | |
130 | const hasher& __hf = hasher(), | |
131 | const key_equal& __eql = key_equal(), | |
132 | const allocator_type& __a = allocator_type()) | |
133 | : _Base(__gnu_debug::__base( | |
134 | __glibcxx_check_valid_constructor_range(__first, __last)), | |
135 | __gnu_debug::__base(__last), __n, | |
136 | __hf, __eql, __a) { } | |
137 | ||
138 | unordered_map(const unordered_map&) = default; | |
139 | ||
140 | unordered_map(_Base_ref __x) | |
141 | : _Base(__x._M_ref) { } | |
142 | ||
143 | unordered_map(unordered_map&&) = default; | |
144 | ||
145 | explicit | |
146 | unordered_map(const allocator_type& __a) | |
147 | : _Base(__a) { } | |
148 | ||
149 | unordered_map(const unordered_map& __umap, | |
150 | const allocator_type& __a) | |
151 | : _Base(__umap, __a) { } | |
152 | ||
153 | unordered_map(unordered_map&& __umap, | |
154 | const allocator_type& __a) | |
155 | noexcept( noexcept(_Base(std::move(__umap), __a)) ) | |
156 | : _Safe(std::move(__umap), __a), | |
157 | _Base(std::move(__umap), __a) { } | |
158 | ||
159 | unordered_map(initializer_list<value_type> __l, | |
160 | size_type __n = 0, | |
161 | const hasher& __hf = hasher(), | |
162 | const key_equal& __eql = key_equal(), | |
163 | const allocator_type& __a = allocator_type()) | |
164 | : _Base(__l, __n, __hf, __eql, __a) { } | |
165 | ||
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 | ||
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 | ||
182 | template<typename _InputIterator> | |
183 | unordered_map(_InputIterator __first, _InputIterator __last, | |
184 | size_type __n, | |
185 | const allocator_type& __a) | |
186 | : unordered_map(__first, __last, __n, hasher(), key_equal(), __a) | |
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) | |
194 | : unordered_map(__first, __last, __n, __hf, key_equal(), __a) | |
195 | { } | |
196 | ||
197 | unordered_map(initializer_list<value_type> __l, | |
198 | const allocator_type& __a) | |
199 | : unordered_map(__l, 0, hasher(), key_equal(), __a) | |
200 | { } | |
201 | ||
202 | unordered_map(initializer_list<value_type> __l, | |
203 | size_type __n, | |
204 | const allocator_type& __a) | |
205 | : unordered_map(__l, __n, hasher(), key_equal(), __a) | |
206 | { } | |
207 | ||
208 | unordered_map(initializer_list<value_type> __l, | |
209 | size_type __n, | |
210 | const hasher& __hf, | |
211 | const allocator_type& __a) | |
212 | : unordered_map(__l, __n, __hf, key_equal(), __a) | |
213 | { } | |
214 | ||
215 | #if __glibcxx_containers_ranges // C++ >= 23 | |
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 | ||
243 | ~unordered_map() = default; | |
244 | ||
245 | unordered_map& | |
246 | operator=(const unordered_map&) = default; | |
247 | ||
248 | unordered_map& | |
249 | operator=(unordered_map&&) = default; | |
250 | ||
251 | unordered_map& | |
252 | operator=(initializer_list<value_type> __l) | |
253 | { | |
254 | _Base::operator=(__l); | |
255 | this->_M_invalidate_all(); | |
256 | return *this; | |
257 | } | |
258 | ||
259 | using _Base::get_allocator; | |
260 | using _Base::empty; | |
261 | using _Base::size; | |
262 | using _Base::max_size; | |
263 | ||
264 | void | |
265 | swap(unordered_map& __x) | |
266 | noexcept( noexcept(declval<_Base&>().swap(__x)) ) | |
267 | { | |
268 | _Safe::_M_swap(__x); | |
269 | _Base::swap(__x); | |
270 | } | |
271 | ||
272 | void | |
273 | clear() noexcept | |
274 | { | |
275 | _Base::clear(); | |
276 | this->_M_invalidate_all(); | |
277 | } | |
278 | ||
279 | iterator | |
280 | begin() noexcept | |
281 | { return { _Base::begin(), this }; } | |
282 | ||
283 | const_iterator | |
284 | begin() const noexcept | |
285 | { return { _Base::begin(), this }; } | |
286 | ||
287 | iterator | |
288 | end() noexcept | |
289 | { return { _Base::end(), this }; } | |
290 | ||
291 | const_iterator | |
292 | end() const noexcept | |
293 | { return { _Base::end(), this }; } | |
294 | ||
295 | const_iterator | |
296 | cbegin() const noexcept | |
297 | { return { _Base::cbegin(), this }; } | |
298 | ||
299 | const_iterator | |
300 | cend() const noexcept | |
301 | { return { _Base::cend(), this }; } | |
302 | ||
303 | // local versions | |
304 | local_iterator | |
305 | begin(size_type __b) | |
306 | { | |
307 | __glibcxx_check_bucket_index(__b); | |
308 | return { _Base::begin(__b), this }; | |
309 | } | |
310 | ||
311 | local_iterator | |
312 | end(size_type __b) | |
313 | { | |
314 | __glibcxx_check_bucket_index(__b); | |
315 | return { _Base::end(__b), this }; | |
316 | } | |
317 | ||
318 | const_local_iterator | |
319 | begin(size_type __b) const | |
320 | { | |
321 | __glibcxx_check_bucket_index(__b); | |
322 | return { _Base::begin(__b), this }; | |
323 | } | |
324 | ||
325 | const_local_iterator | |
326 | end(size_type __b) const | |
327 | { | |
328 | __glibcxx_check_bucket_index(__b); | |
329 | return { _Base::end(__b), this }; | |
330 | } | |
331 | ||
332 | const_local_iterator | |
333 | cbegin(size_type __b) const | |
334 | { | |
335 | __glibcxx_check_bucket_index(__b); | |
336 | return { _Base::cbegin(__b), this }; | |
337 | } | |
338 | ||
339 | const_local_iterator | |
340 | cend(size_type __b) const | |
341 | { | |
342 | __glibcxx_check_bucket_index(__b); | |
343 | return { _Base::cend(__b), this }; | |
344 | } | |
345 | ||
346 | using _Base::bucket_count; | |
347 | using _Base::max_bucket_count; | |
348 | using _Base::bucket; | |
349 | ||
350 | size_type | |
351 | bucket_size(size_type __b) const | |
352 | { | |
353 | __glibcxx_check_bucket_index(__b); | |
354 | return _Base::bucket_size(__b); | |
355 | } | |
356 | ||
357 | using _Base::load_factor; | |
358 | ||
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 | ||
370 | template<typename... _Args> | |
371 | std::pair<iterator, bool> | |
372 | emplace(_Args&&... __args) | |
373 | { | |
374 | size_type __bucket_count = this->bucket_count(); | |
375 | auto __res = _Base::emplace(std::forward<_Args>(__args)...); | |
376 | _M_check_rehashed(__bucket_count); | |
377 | return { { __res.first, this }, __res.second }; | |
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(); | |
386 | auto __it = _Base::emplace_hint(__hint.base(), | |
387 | std::forward<_Args>(__args)...); | |
388 | _M_check_rehashed(__bucket_count); | |
389 | return { __it, this }; | |
390 | } | |
391 | ||
392 | std::pair<iterator, bool> | |
393 | insert(const value_type& __obj) | |
394 | { | |
395 | size_type __bucket_count = this->bucket_count(); | |
396 | auto __res = _Base::insert(__obj); | |
397 | _M_check_rehashed(__bucket_count); | |
398 | return { { __res.first, this }, __res.second }; | |
399 | } | |
400 | ||
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) | |
405 | { | |
406 | size_type __bucket_count = this->bucket_count(); | |
407 | auto __res = _Base::insert(std::move(__x)); | |
408 | _M_check_rehashed(__bucket_count); | |
409 | return { { __res.first, this }, __res.second }; | |
410 | } | |
411 | ||
412 | template<typename _Pair, typename = typename | |
413 | std::enable_if<std::is_constructible<value_type, | |
414 | _Pair&&>::value>::type> | |
415 | std::pair<iterator, bool> | |
416 | insert(_Pair&& __obj) | |
417 | { | |
418 | size_type __bucket_count = this->bucket_count(); | |
419 | auto __res = _Base::insert(std::forward<_Pair>(__obj)); | |
420 | _M_check_rehashed(__bucket_count); | |
421 | return { { __res.first, this }, __res.second }; | |
422 | } | |
423 | ||
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(); | |
429 | auto __it = _Base::insert(__hint.base(), __obj); | |
430 | _M_check_rehashed(__bucket_count); | |
431 | return { __it, this }; | |
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); | |
443 | return { __it, this }; | |
444 | } | |
445 | ||
446 | template<typename _Pair, typename = typename | |
447 | std::enable_if<std::is_constructible<value_type, | |
448 | _Pair&&>::value>::type> | |
449 | iterator | |
450 | insert(const_iterator __hint, _Pair&& __obj) | |
451 | { | |
452 | __glibcxx_check_insert(__hint); | |
453 | size_type __bucket_count = this->bucket_count(); | |
454 | auto __it = _Base::insert(__hint.base(), std::forward<_Pair>(__obj)); | |
455 | _M_check_rehashed(__bucket_count); | |
456 | return { __it, this }; | |
457 | } | |
458 | ||
459 | void | |
460 | insert(std::initializer_list<value_type> __l) | |
461 | { | |
462 | size_type __bucket_count = this->bucket_count(); | |
463 | _Base::insert(__l); | |
464 | _M_check_rehashed(__bucket_count); | |
465 | } | |
466 | ||
467 | template<typename _InputIterator> | |
468 | void | |
469 | insert(_InputIterator __first, _InputIterator __last) | |
470 | { | |
471 | typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist; | |
472 | __glibcxx_check_valid_range2(__first, __last, __dist); | |
473 | size_type __bucket_count = this->bucket_count(); | |
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 | ||
481 | _M_check_rehashed(__bucket_count); | |
482 | } | |
483 | ||
484 | #ifdef __glibcxx_unordered_map_try_emplace // C++ >= 17 && HOSTED | |
485 | template <typename... _Args> | |
486 | pair<iterator, bool> | |
487 | try_emplace(const key_type& __k, _Args&&... __args) | |
488 | { | |
489 | auto __res = _Base::try_emplace(__k, | |
490 | std::forward<_Args>(__args)...); | |
491 | return { { __res.first, this }, __res.second }; | |
492 | } | |
493 | ||
494 | template <typename... _Args> | |
495 | pair<iterator, bool> | |
496 | try_emplace(key_type&& __k, _Args&&... __args) | |
497 | { | |
498 | auto __res = _Base::try_emplace(std::move(__k), | |
499 | std::forward<_Args>(__args)...); | |
500 | return { { __res.first, this }, __res.second }; | |
501 | } | |
502 | ||
503 | template <typename... _Args> | |
504 | iterator | |
505 | try_emplace(const_iterator __hint, const key_type& __k, | |
506 | _Args&&... __args) | |
507 | { | |
508 | __glibcxx_check_insert(__hint); | |
509 | return { _Base::try_emplace(__hint.base(), __k, | |
510 | std::forward<_Args>(__args)...), | |
511 | this }; | |
512 | } | |
513 | ||
514 | template <typename... _Args> | |
515 | iterator | |
516 | try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args) | |
517 | { | |
518 | __glibcxx_check_insert(__hint); | |
519 | return { _Base::try_emplace(__hint.base(), std::move(__k), | |
520 | std::forward<_Args>(__args)...), | |
521 | this }; | |
522 | } | |
523 | ||
524 | template <typename _Obj> | |
525 | pair<iterator, bool> | |
526 | insert_or_assign(const key_type& __k, _Obj&& __obj) | |
527 | { | |
528 | auto __res = _Base::insert_or_assign(__k, | |
529 | std::forward<_Obj>(__obj)); | |
530 | return { { __res.first, this }, __res.second }; | |
531 | } | |
532 | ||
533 | template <typename _Obj> | |
534 | pair<iterator, bool> | |
535 | insert_or_assign(key_type&& __k, _Obj&& __obj) | |
536 | { | |
537 | auto __res = _Base::insert_or_assign(std::move(__k), | |
538 | std::forward<_Obj>(__obj)); | |
539 | return { { __res.first, this }, __res.second }; | |
540 | } | |
541 | ||
542 | template <typename _Obj> | |
543 | iterator | |
544 | insert_or_assign(const_iterator __hint, const key_type& __k, | |
545 | _Obj&& __obj) | |
546 | { | |
547 | __glibcxx_check_insert(__hint); | |
548 | return { _Base::insert_or_assign(__hint.base(), __k, | |
549 | std::forward<_Obj>(__obj)), | |
550 | this }; | |
551 | } | |
552 | ||
553 | template <typename _Obj> | |
554 | iterator | |
555 | insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj) | |
556 | { | |
557 | __glibcxx_check_insert(__hint); | |
558 | return { _Base::insert_or_assign(__hint.base(), std::move(__k), | |
559 | std::forward<_Obj>(__obj)), | |
560 | this }; | |
561 | } | |
562 | #endif // C++17 | |
563 | ||
564 | #if __cplusplus > 201402L | |
565 | using node_type = typename _Base::node_type; | |
566 | using insert_return_type = _Node_insert_return<iterator, node_type>; | |
567 | ||
568 | node_type | |
569 | extract(const_iterator __position) | |
570 | { | |
571 | __glibcxx_check_erase(__position); | |
572 | return _M_extract(__position.base()); | |
573 | } | |
574 | ||
575 | node_type | |
576 | extract(const key_type& __key) | |
577 | { | |
578 | const auto __position = _Base::find(__key); | |
579 | if (__position != _Base::end()) | |
580 | return _M_extract(__position); | |
581 | return {}; | |
582 | } | |
583 | ||
584 | insert_return_type | |
585 | insert(node_type&& __nh) | |
586 | { | |
587 | auto __ret = _Base::insert(std::move(__nh)); | |
588 | return | |
589 | { { __ret.position, this }, __ret.inserted, std::move(__ret.node) }; | |
590 | } | |
591 | ||
592 | iterator | |
593 | insert(const_iterator __hint, node_type&& __nh) | |
594 | { | |
595 | __glibcxx_check_insert(__hint); | |
596 | return { _Base::insert(__hint.base(), std::move(__nh)), this }; | |
597 | } | |
598 | ||
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); | |
605 | _Base::merge(__source); | |
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); | |
619 | _Base::merge(__source); | |
620 | } | |
621 | ||
622 | template<typename _H2, typename _P2> | |
623 | void | |
624 | merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>&& __source) | |
625 | { merge(__source); } | |
626 | #endif // C++17 | |
627 | ||
628 | using _Base::hash_function; | |
629 | using _Base::key_eq; | |
630 | ||
631 | iterator | |
632 | find(const key_type& __key) | |
633 | { return { _Base::find(__key), this }; } | |
634 | ||
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 | ||
644 | const_iterator | |
645 | find(const key_type& __key) const | |
646 | { return { _Base::find(__key), this }; } | |
647 | ||
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 | ||
657 | using _Base::count; | |
658 | #if __cplusplus > 201703L | |
659 | using _Base::contains; | |
660 | #endif | |
661 | ||
662 | std::pair<iterator, iterator> | |
663 | equal_range(const key_type& __key) | |
664 | { | |
665 | auto __res = _Base::equal_range(__key); | |
666 | return { { __res.first, this }, { __res.second, this } }; | |
667 | } | |
668 | ||
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 | ||
681 | std::pair<const_iterator, const_iterator> | |
682 | equal_range(const key_type& __key) const | |
683 | { | |
684 | auto __res = _Base::equal_range(__key); | |
685 | return { { __res.first, this }, { __res.second, this } }; | |
686 | } | |
687 | ||
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 | ||
700 | using _Base::operator[]; | |
701 | using _Base::at; | |
702 | ||
703 | size_type | |
704 | erase(const key_type& __key) | |
705 | { | |
706 | size_type __ret(0); | |
707 | auto __victim = _Base::find(__key); | |
708 | if (__victim != _Base::end()) | |
709 | { | |
710 | _M_erase(__victim); | |
711 | __ret = 1; | |
712 | } | |
713 | return __ret; | |
714 | } | |
715 | ||
716 | iterator | |
717 | erase(const_iterator __it) | |
718 | { | |
719 | __glibcxx_check_erase(__it); | |
720 | return { _M_erase(__it.base()), this }; | |
721 | } | |
722 | ||
723 | _Base_iterator | |
724 | erase(_Base_const_iterator __it) | |
725 | { | |
726 | __glibcxx_check_erase2(__it); | |
727 | return _M_erase(__it); | |
728 | } | |
729 | ||
730 | iterator | |
731 | erase(iterator __it) | |
732 | { | |
733 | __glibcxx_check_erase(__it); | |
734 | return { _M_erase(__it.base()), this }; | |
735 | } | |
736 | ||
737 | iterator | |
738 | erase(const_iterator __first, const_iterator __last) | |
739 | { | |
740 | __glibcxx_check_erase_range(__first, __last); | |
741 | for (auto __tmp = __first.base(); __tmp != __last.base(); ++__tmp) | |
742 | { | |
743 | _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::cend(), | |
744 | _M_message(__gnu_debug::__msg_valid_range) | |
745 | ._M_iterator(__first, "first") | |
746 | ._M_iterator(__last, "last")); | |
747 | _M_invalidate(__tmp); | |
748 | } | |
749 | ||
750 | size_type __bucket_count = this->bucket_count(); | |
751 | auto __next = _Base::erase(__first.base(), __last.base()); | |
752 | _M_check_rehashed(__bucket_count); | |
753 | return { __next, this }; | |
754 | } | |
755 | ||
756 | using _Base::rehash; | |
757 | using _Base::reserve; | |
758 | ||
759 | _Base& | |
760 | _M_base() noexcept { return *this; } | |
761 | ||
762 | const _Base& | |
763 | _M_base() const noexcept { return *this; } | |
764 | ||
765 | private: | |
766 | void | |
767 | _M_check_rehashed(size_type __prev_count) | |
768 | { | |
769 | if (__prev_count != this->bucket_count()) | |
770 | this->_M_invalidate_all(); | |
771 | } | |
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) | |
780 | { return __it == __victim; }); | |
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 | |
801 | }; | |
802 | ||
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>, | |
810 | typename = _RequireNotAllocatorOrIntegral<_Hash>, | |
811 | typename = _RequireNotAllocator<_Pred>, | |
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>>, | |
823 | typename = _RequireNotAllocatorOrIntegral<_Hash>, | |
824 | typename = _RequireNotAllocator<_Pred>, | |
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>, | |
854 | typename = _RequireNotAllocatorOrIntegral<_Hash>, | |
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, | |
871 | typename = _RequireAllocator<_Allocator>> | |
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, | |
876 | typename = _RequireNotAllocatorOrIntegral<_Hash>, | |
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 | ||
883 | #if __glibcxx_containers_ranges // C++ >= 23 | |
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 | |
924 | #endif | |
925 | ||
926 | template<typename _Key, typename _Tp, typename _Hash, | |
927 | typename _Pred, typename _Alloc> | |
928 | inline void | |
929 | swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, | |
930 | unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) | |
931 | noexcept(noexcept(__x.swap(__y))) | |
932 | { __x.swap(__y); } | |
933 | ||
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) | |
939 | { return __x._M_base() == __y._M_base(); } | |
940 | ||
941 | #if __cpp_impl_three_way_comparison < 201907L | |
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); } | |
948 | #endif | |
949 | ||
950 | /// Class std::unordered_multimap with safety/checking/debug instrumentation. | |
951 | template<typename _Key, typename _Tp, | |
952 | typename _Hash = std::hash<_Key>, | |
953 | typename _Pred = std::equal_to<_Key>, | |
954 | typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > > | |
955 | class unordered_multimap | |
956 | : public __gnu_debug::_Safe_container< | |
957 | unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc, | |
958 | __gnu_debug::_Safe_unordered_container>, | |
959 | public _GLIBCXX_STD_C::unordered_multimap< | |
960 | _Key, _Tp, _Hash, _Pred, _Alloc> | |
961 | { | |
962 | typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, | |
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; | |
968 | typedef typename _Base::const_local_iterator _Base_const_local_iterator; | |
969 | typedef typename _Base::local_iterator _Base_local_iterator; | |
970 | ||
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 | ||
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 | ||
984 | public: | |
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; | |
992 | typedef typename _Base::mapped_type mapped_type; | |
993 | ||
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; | |
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; | |
1002 | typedef __gnu_debug::_Safe_local_iterator< | |
1003 | _Base_local_iterator, unordered_multimap> local_iterator; | |
1004 | typedef __gnu_debug::_Safe_local_iterator< | |
1005 | _Base_const_local_iterator, unordered_multimap> const_local_iterator; | |
1006 | typedef typename _Base::difference_type difference_type; | |
1007 | ||
1008 | unordered_multimap() = default; | |
1009 | ||
1010 | explicit | |
1011 | unordered_multimap(size_type __n, | |
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) { } | |
1016 | ||
1017 | template<typename _InputIterator> | |
1018 | unordered_multimap(_InputIterator __first, _InputIterator __last, | |
1019 | size_type __n = 0, | |
1020 | const hasher& __hf = hasher(), | |
1021 | const key_equal& __eql = key_equal(), | |
1022 | const allocator_type& __a = allocator_type()) | |
1023 | : _Base(__gnu_debug::__base( | |
1024 | __glibcxx_check_valid_constructor_range(__first, __last)), | |
1025 | __gnu_debug::__base(__last), __n, | |
1026 | __hf, __eql, __a) { } | |
1027 | ||
1028 | unordered_multimap(const unordered_multimap&) = default; | |
1029 | ||
1030 | unordered_multimap(_Base_ref __x) | |
1031 | : _Base(__x._M_ref) { } | |
1032 | ||
1033 | unordered_multimap(unordered_multimap&&) = default; | |
1034 | ||
1035 | explicit | |
1036 | unordered_multimap(const allocator_type& __a) | |
1037 | : _Base(__a) { } | |
1038 | ||
1039 | unordered_multimap(const unordered_multimap& __umap, | |
1040 | const allocator_type& __a) | |
1041 | : _Base(__umap, __a) { } | |
1042 | ||
1043 | unordered_multimap(unordered_multimap&& __umap, | |
1044 | const allocator_type& __a) | |
1045 | noexcept( noexcept(_Base(std::move(__umap), __a)) ) | |
1046 | : _Safe(std::move(__umap), __a), | |
1047 | _Base(std::move(__umap), __a) { } | |
1048 | ||
1049 | unordered_multimap(initializer_list<value_type> __l, | |
1050 | size_type __n = 0, | |
1051 | const hasher& __hf = hasher(), | |
1052 | const key_equal& __eql = key_equal(), | |
1053 | const allocator_type& __a = allocator_type()) | |
1054 | : _Base(__l, __n, __hf, __eql, __a) { } | |
1055 | ||
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 | ||
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 | ||
1071 | template<typename _InputIterator> | |
1072 | unordered_multimap(_InputIterator __first, _InputIterator __last, | |
1073 | size_type __n, | |
1074 | const allocator_type& __a) | |
1075 | : unordered_multimap(__first, __last, __n, hasher(), key_equal(), __a) | |
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) | |
1082 | : unordered_multimap(__first, __last, __n, __hf, key_equal(), __a) | |
1083 | { } | |
1084 | ||
1085 | unordered_multimap(initializer_list<value_type> __l, | |
1086 | const allocator_type& __a) | |
1087 | : unordered_multimap(__l, 0, hasher(), key_equal(), __a) | |
1088 | { } | |
1089 | ||
1090 | unordered_multimap(initializer_list<value_type> __l, | |
1091 | size_type __n, | |
1092 | const allocator_type& __a) | |
1093 | : unordered_multimap(__l, __n, hasher(), key_equal(), __a) | |
1094 | { } | |
1095 | ||
1096 | unordered_multimap(initializer_list<value_type> __l, | |
1097 | size_type __n, const hasher& __hf, | |
1098 | const allocator_type& __a) | |
1099 | : unordered_multimap(__l, __n, __hf, key_equal(), __a) | |
1100 | { } | |
1101 | ||
1102 | #if __glibcxx_containers_ranges // C++ >= 23 | |
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 | ||
1130 | ~unordered_multimap() = default; | |
1131 | ||
1132 | unordered_multimap& | |
1133 | operator=(const unordered_multimap&) = default; | |
1134 | ||
1135 | unordered_multimap& | |
1136 | operator=(unordered_multimap&&) = default; | |
1137 | ||
1138 | unordered_multimap& | |
1139 | operator=(initializer_list<value_type> __l) | |
1140 | { | |
1141 | _Base::operator=(__l); | |
1142 | this->_M_invalidate_all(); | |
1143 | return *this; | |
1144 | } | |
1145 | ||
1146 | using _Base::get_allocator; | |
1147 | using _Base::empty; | |
1148 | using _Base::size; | |
1149 | using _Base::max_size; | |
1150 | ||
1151 | void | |
1152 | swap(unordered_multimap& __x) | |
1153 | noexcept( noexcept(declval<_Base&>().swap(__x)) ) | |
1154 | { | |
1155 | _Safe::_M_swap(__x); | |
1156 | _Base::swap(__x); | |
1157 | } | |
1158 | ||
1159 | void | |
1160 | clear() noexcept | |
1161 | { | |
1162 | _Base::clear(); | |
1163 | this->_M_invalidate_all(); | |
1164 | } | |
1165 | ||
1166 | iterator | |
1167 | begin() noexcept | |
1168 | { return { _Base::begin(), this }; } | |
1169 | ||
1170 | const_iterator | |
1171 | begin() const noexcept | |
1172 | { return { _Base::begin(), this }; } | |
1173 | ||
1174 | iterator | |
1175 | end() noexcept | |
1176 | { return { _Base::end(), this }; } | |
1177 | ||
1178 | const_iterator | |
1179 | end() const noexcept | |
1180 | { return { _Base::end(), this }; } | |
1181 | ||
1182 | const_iterator | |
1183 | cbegin() const noexcept | |
1184 | { return { _Base::cbegin(), this }; } | |
1185 | ||
1186 | const_iterator | |
1187 | cend() const noexcept | |
1188 | { return { _Base::cend(), this }; } | |
1189 | ||
1190 | // local versions | |
1191 | local_iterator | |
1192 | begin(size_type __b) | |
1193 | { | |
1194 | __glibcxx_check_bucket_index(__b); | |
1195 | return { _Base::begin(__b), this }; | |
1196 | } | |
1197 | ||
1198 | local_iterator | |
1199 | end(size_type __b) | |
1200 | { | |
1201 | __glibcxx_check_bucket_index(__b); | |
1202 | return { _Base::end(__b), this }; | |
1203 | } | |
1204 | ||
1205 | const_local_iterator | |
1206 | begin(size_type __b) const | |
1207 | { | |
1208 | __glibcxx_check_bucket_index(__b); | |
1209 | return { _Base::begin(__b), this }; | |
1210 | } | |
1211 | ||
1212 | const_local_iterator | |
1213 | end(size_type __b) const | |
1214 | { | |
1215 | __glibcxx_check_bucket_index(__b); | |
1216 | return { _Base::end(__b), this }; | |
1217 | } | |
1218 | ||
1219 | const_local_iterator | |
1220 | cbegin(size_type __b) const | |
1221 | { | |
1222 | __glibcxx_check_bucket_index(__b); | |
1223 | return { _Base::cbegin(__b), this }; | |
1224 | } | |
1225 | ||
1226 | const_local_iterator | |
1227 | cend(size_type __b) const | |
1228 | { | |
1229 | __glibcxx_check_bucket_index(__b); | |
1230 | return { _Base::cend(__b), this }; | |
1231 | } | |
1232 | ||
1233 | using _Base::bucket_count; | |
1234 | using _Base::max_bucket_count; | |
1235 | using _Base::bucket; | |
1236 | ||
1237 | size_type | |
1238 | bucket_size(size_type __b) const | |
1239 | { | |
1240 | __glibcxx_check_bucket_index(__b); | |
1241 | return _Base::bucket_size(__b); | |
1242 | } | |
1243 | ||
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 | ||
1255 | template<typename... _Args> | |
1256 | iterator | |
1257 | emplace(_Args&&... __args) | |
1258 | { | |
1259 | size_type __bucket_count = this->bucket_count(); | |
1260 | auto __it = _Base::emplace(std::forward<_Args>(__args)...); | |
1261 | _M_check_rehashed(__bucket_count); | |
1262 | return { __it, this }; | |
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(); | |
1271 | auto __it = _Base::emplace_hint(__hint.base(), | |
1272 | std::forward<_Args>(__args)...); | |
1273 | _M_check_rehashed(__bucket_count); | |
1274 | return { __it, this }; | |
1275 | } | |
1276 | ||
1277 | iterator | |
1278 | insert(const value_type& __obj) | |
1279 | { | |
1280 | size_type __bucket_count = this->bucket_count(); | |
1281 | auto __it = _Base::insert(__obj); | |
1282 | _M_check_rehashed(__bucket_count); | |
1283 | return { __it, this }; | |
1284 | } | |
1285 | ||
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 | ||
1297 | iterator | |
1298 | insert(const_iterator __hint, const value_type& __obj) | |
1299 | { | |
1300 | __glibcxx_check_insert(__hint); | |
1301 | size_type __bucket_count = this->bucket_count(); | |
1302 | auto __it = _Base::insert(__hint.base(), __obj); | |
1303 | _M_check_rehashed(__bucket_count); | |
1304 | return { __it, this }; | |
1305 | } | |
1306 | ||
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); | |
1316 | return { __it, this }; | |
1317 | } | |
1318 | ||
1319 | template<typename _Pair, typename = typename | |
1320 | std::enable_if<std::is_constructible<value_type, | |
1321 | _Pair&&>::value>::type> | |
1322 | iterator | |
1323 | insert(_Pair&& __obj) | |
1324 | { | |
1325 | size_type __bucket_count = this->bucket_count(); | |
1326 | auto __it = _Base::insert(std::forward<_Pair>(__obj)); | |
1327 | _M_check_rehashed(__bucket_count); | |
1328 | return { __it, this }; | |
1329 | } | |
1330 | ||
1331 | template<typename _Pair, typename = typename | |
1332 | std::enable_if<std::is_constructible<value_type, | |
1333 | _Pair&&>::value>::type> | |
1334 | iterator | |
1335 | insert(const_iterator __hint, _Pair&& __obj) | |
1336 | { | |
1337 | __glibcxx_check_insert(__hint); | |
1338 | size_type __bucket_count = this->bucket_count(); | |
1339 | auto __it = _Base::insert(__hint.base(), std::forward<_Pair>(__obj)); | |
1340 | _M_check_rehashed(__bucket_count); | |
1341 | return { __it, this }; | |
1342 | } | |
1343 | ||
1344 | void | |
1345 | insert(std::initializer_list<value_type> __l) | |
1346 | { _Base::insert(__l); } | |
1347 | ||
1348 | template<typename _InputIterator> | |
1349 | void | |
1350 | insert(_InputIterator __first, _InputIterator __last) | |
1351 | { | |
1352 | typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist; | |
1353 | __glibcxx_check_valid_range2(__first, __last, __dist); | |
1354 | size_type __bucket_count = this->bucket_count(); | |
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 | ||
1362 | _M_check_rehashed(__bucket_count); | |
1363 | } | |
1364 | ||
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); | |
1372 | return _M_extract(__position.base()); | |
1373 | } | |
1374 | ||
1375 | node_type | |
1376 | extract(const key_type& __key) | |
1377 | { | |
1378 | const auto __position = _Base::find(__key); | |
1379 | if (__position != _Base::end()) | |
1380 | return _M_extract(__position); | |
1381 | return {}; | |
1382 | } | |
1383 | ||
1384 | iterator | |
1385 | insert(node_type&& __nh) | |
1386 | { return { _Base::insert(std::move(__nh)), this }; } | |
1387 | ||
1388 | iterator | |
1389 | insert(const_iterator __hint, node_type&& __nh) | |
1390 | { | |
1391 | __glibcxx_check_insert(__hint); | |
1392 | return { _Base::insert(__hint.base(), std::move(__nh)), this }; | |
1393 | } | |
1394 | ||
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); | |
1401 | _Base::merge(__source); | |
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); | |
1415 | _Base::merge(__source); | |
1416 | } | |
1417 | ||
1418 | template<typename _H2, typename _P2> | |
1419 | void | |
1420 | merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>&& __source) | |
1421 | { merge(__source); } | |
1422 | #endif // C++17 | |
1423 | ||
1424 | using _Base::hash_function; | |
1425 | using _Base::key_eq; | |
1426 | ||
1427 | iterator | |
1428 | find(const key_type& __key) | |
1429 | { return { _Base::find(__key), this }; } | |
1430 | ||
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 | ||
1440 | const_iterator | |
1441 | find(const key_type& __key) const | |
1442 | { return { _Base::find(__key), this }; } | |
1443 | ||
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 | ||
1453 | using _Base::count; | |
1454 | #if __cplusplus > 201703L | |
1455 | using _Base::contains; | |
1456 | #endif | |
1457 | ||
1458 | std::pair<iterator, iterator> | |
1459 | equal_range(const key_type& __key) | |
1460 | { | |
1461 | auto __res = _Base::equal_range(__key); | |
1462 | return { { __res.first, this }, { __res.second, this } }; | |
1463 | } | |
1464 | ||
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 | ||
1477 | std::pair<const_iterator, const_iterator> | |
1478 | equal_range(const key_type& __key) const | |
1479 | { | |
1480 | auto __res = _Base::equal_range(__key); | |
1481 | return { { __res.first, this }, { __res.second, this } }; | |
1482 | } | |
1483 | ||
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 | ||
1496 | size_type | |
1497 | erase(const key_type& __key) | |
1498 | { | |
1499 | size_type __ret(0); | |
1500 | size_type __bucket_count = this->bucket_count(); | |
1501 | auto __pair = _Base::equal_range(__key); | |
1502 | for (auto __victim = __pair.first; __victim != __pair.second;) | |
1503 | { | |
1504 | _M_invalidate(__victim); | |
1505 | __victim = _Base::erase(__victim); | |
1506 | ++__ret; | |
1507 | } | |
1508 | ||
1509 | _M_check_rehashed(__bucket_count); | |
1510 | return __ret; | |
1511 | } | |
1512 | ||
1513 | iterator | |
1514 | erase(const_iterator __it) | |
1515 | { | |
1516 | __glibcxx_check_erase(__it); | |
1517 | return { _M_erase(__it.base()), this }; | |
1518 | } | |
1519 | ||
1520 | _Base_iterator | |
1521 | erase(_Base_const_iterator __it) | |
1522 | { | |
1523 | __glibcxx_check_erase2(__it); | |
1524 | return _M_erase(__it); | |
1525 | } | |
1526 | ||
1527 | iterator | |
1528 | erase(iterator __it) | |
1529 | { | |
1530 | __glibcxx_check_erase(__it); | |
1531 | return { _M_erase(__it.base()), this }; | |
1532 | } | |
1533 | ||
1534 | iterator | |
1535 | erase(const_iterator __first, const_iterator __last) | |
1536 | { | |
1537 | __glibcxx_check_erase_range(__first, __last); | |
1538 | for (auto __tmp = __first.base(); __tmp != __last.base(); ++__tmp) | |
1539 | { | |
1540 | _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::cend(), | |
1541 | _M_message(__gnu_debug::__msg_valid_range) | |
1542 | ._M_iterator(__first, "first") | |
1543 | ._M_iterator(__last, "last")); | |
1544 | _M_invalidate(__tmp); | |
1545 | } | |
1546 | ||
1547 | size_type __bucket_count = this->bucket_count(); | |
1548 | auto __next = _Base::erase(__first.base(), __last.base()); | |
1549 | _M_check_rehashed(__bucket_count); | |
1550 | return { __next, this }; | |
1551 | } | |
1552 | ||
1553 | using _Base::rehash; | |
1554 | using _Base::reserve; | |
1555 | ||
1556 | _Base& | |
1557 | _M_base() noexcept { return *this; } | |
1558 | ||
1559 | const _Base& | |
1560 | _M_base() const noexcept { return *this; } | |
1561 | ||
1562 | private: | |
1563 | void | |
1564 | _M_check_rehashed(size_type __prev_count) | |
1565 | { | |
1566 | if (__prev_count != this->bucket_count()) | |
1567 | this->_M_invalidate_all(); | |
1568 | } | |
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) | |
1577 | { return __it == __victim; }); | |
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 | |
1598 | }; | |
1599 | ||
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>, | |
1607 | typename = _RequireNotAllocatorOrIntegral<_Hash>, | |
1608 | typename = _RequireNotAllocator<_Pred>, | |
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>>, | |
1621 | typename = _RequireNotAllocatorOrIntegral<_Hash>, | |
1622 | typename = _RequireNotAllocator<_Pred>, | |
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>, | |
1651 | typename = _RequireNotAllocatorOrIntegral<_Hash>, | |
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, | |
1673 | typename = _RequireNotAllocatorOrIntegral<_Hash>, | |
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 | ||
1680 | #if __glibcxx_containers_ranges // C++ >= 23 | |
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 | |
1724 | #endif | |
1725 | ||
1726 | template<typename _Key, typename _Tp, typename _Hash, | |
1727 | typename _Pred, typename _Alloc> | |
1728 | inline void | |
1729 | swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, | |
1730 | unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) | |
1731 | noexcept(noexcept(__x.swap(__y))) | |
1732 | { __x.swap(__y); } | |
1733 | ||
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) | |
1739 | { return __x._M_base() == __y._M_base(); } | |
1740 | ||
1741 | #if __cpp_impl_three_way_comparison < 201907L | |
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); } | |
1748 | #endif | |
1749 | ||
1750 | } // namespace __debug | |
1751 | } // namespace std | |
1752 | ||
1753 | #endif // C++11 | |
1754 | ||
1755 | #endif |