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