libstdc++

debug/unordered_set
Go to the documentation of this file.
1 // Debugging unordered_set/unordered_multiset implementation -*- C++ -*-
2
3 // Copyright (C) 2003-2013 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 #if __cplusplus < 201103L
33 # include <bits/c++0x_warning.h>
34 #else
35 # include <unordered_set>
36
37 #include <debug/safe_unordered_container.h>
38 #include <debug/safe_iterator.h>
39 #include <debug/safe_local_iterator.h>
40
41 namespace std _GLIBCXX_VISIBILITY(default)
42 {
43 namespace __debug
44 {
45 /// Class std::unordered_set with safety/checking/debug instrumentation.
46 template<typename _Value,
47 typename _Hash = std::hash<_Value>,
48 typename _Pred = std::equal_to<_Value>,
49 typename _Alloc = std::allocator<_Value> >
50 class unordered_set
51 : public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc>,
52 public __gnu_debug::_Safe_unordered_container<unordered_set<_Value, _Hash,
53 _Pred, _Alloc> >
54 {
55 typedef _GLIBCXX_STD_C::unordered_set<_Value, _Hash,
56 _Pred, _Alloc> _Base;
57 typedef __gnu_debug::_Safe_unordered_container<unordered_set> _Safe_base;
58 typedef typename _Base::const_iterator _Base_const_iterator;
59 typedef typename _Base::iterator _Base_iterator;
60 typedef typename _Base::const_local_iterator _Base_const_local_iterator;
61 typedef typename _Base::local_iterator _Base_local_iterator;
62
63 public:
64 typedef typename _Base::size_type size_type;
65 typedef typename _Base::hasher hasher;
66 typedef typename _Base::key_equal key_equal;
67 typedef typename _Base::allocator_type allocator_type;
68
69 typedef typename _Base::key_type key_type;
70 typedef typename _Base::value_type value_type;
71
72 typedef __gnu_debug::_Safe_iterator<_Base_iterator,
73 unordered_set> iterator;
74 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
75 unordered_set> const_iterator;
76 typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator,
77 unordered_set> local_iterator;
78 typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator,
79 unordered_set> const_local_iterator;
80
81 explicit
82 unordered_set(size_type __n = 10,
83 const hasher& __hf = hasher(),
84 const key_equal& __eql = key_equal(),
85 const allocator_type& __a = allocator_type())
86 : _Base(__n, __hf, __eql, __a) { }
87
88 template<typename _InputIterator>
89 unordered_set(_InputIterator __first, _InputIterator __last,
90 size_type __n = 0,
91 const hasher& __hf = hasher(),
92 const key_equal& __eql = key_equal(),
93 const allocator_type& __a = allocator_type())
94 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
95 __last)),
96 __gnu_debug::__base(__last), __n,
97 __hf, __eql, __a) { }
98
99 unordered_set(const unordered_set& __x) = default;
100
101 unordered_set(const _Base& __x)
102 : _Base(__x) { }
103
104 unordered_set(unordered_set&& __x) = default;
105
106 unordered_set(initializer_list<value_type> __l,
107 size_type __n = 0,
108 const hasher& __hf = hasher(),
109 const key_equal& __eql = key_equal(),
110 const allocator_type& __a = allocator_type())
111 : _Base(__l, __n, __hf, __eql, __a) { }
112
113 ~unordered_set() noexcept { }
114
115 unordered_set&
116 operator=(const unordered_set& __x)
117 {
118 *static_cast<_Base*>(this) = __x;
119 this->_M_invalidate_all();
120 return *this;
121 }
122
123 unordered_set&
124 operator=(unordered_set&& __x)
125 {
126 // NB: DR 1204.
127 // NB: DR 675.
128 __glibcxx_check_self_move_assign(__x);
129 clear();
130 swap(__x);
131 return *this;
132 }
133
134 unordered_set&
135 operator=(initializer_list<value_type> __l)
136 {
137 this->clear();
138 this->insert(__l);
139 return *this;
140 }
141
142 void
143 swap(unordered_set& __x)
144 {
145 _Base::swap(__x);
146 _Safe_base::_M_swap(__x);
147 }
148
149 void
150 clear() noexcept
151 {
152 _Base::clear();
153 this->_M_invalidate_all();
154 }
155
156 iterator
157 begin() noexcept
158 { return iterator(_Base::begin(), this); }
159
160 const_iterator
161 begin() const noexcept
162 { return const_iterator(_Base::begin(), this); }
163
164 iterator
165 end() noexcept
166 { return iterator(_Base::end(), this); }
167
168 const_iterator
169 end() const noexcept
170 { return const_iterator(_Base::end(), this); }
171
172 const_iterator
173 cbegin() const noexcept
174 { return const_iterator(_Base::begin(), this); }
175
176 const_iterator
177 cend() const noexcept
178 { return const_iterator(_Base::end(), this); }
179
180 // local versions
181 local_iterator
182 begin(size_type __b)
183 {
184 __glibcxx_check_bucket_index(__b);
185 return local_iterator(_Base::begin(__b), __b, this);
186 }
187
188 local_iterator
189 end(size_type __b)
190 {
191 __glibcxx_check_bucket_index(__b);
192 return local_iterator(_Base::end(__b), __b, this);
193 }
194
195 const_local_iterator
196 begin(size_type __b) const
197 {
198 __glibcxx_check_bucket_index(__b);
199 return const_local_iterator(_Base::begin(__b), __b, this);
200 }
201
202 const_local_iterator
203 end(size_type __b) const
204 {
205 __glibcxx_check_bucket_index(__b);
206 return const_local_iterator(_Base::end(__b), __b, this);
207 }
208
209 const_local_iterator
210 cbegin(size_type __b) const
211 {
212 __glibcxx_check_bucket_index(__b);
213 return const_local_iterator(_Base::cbegin(__b), __b, this);
214 }
215
216 const_local_iterator
217 cend(size_type __b) const
218 {
219 __glibcxx_check_bucket_index(__b);
220 return const_local_iterator(_Base::cend(__b), __b, this);
221 }
222
223 size_type
224 bucket_size(size_type __b) const
225 {
226 __glibcxx_check_bucket_index(__b);
227 return _Base::bucket_size(__b);
228 }
229
230 float
231 max_load_factor() const noexcept
232 { return _Base::max_load_factor(); }
233
234 void
235 max_load_factor(float __f)
236 {
237 __glibcxx_check_max_load_factor(__f);
238 _Base::max_load_factor(__f);
239 }
240
241 template<typename... _Args>
242 std::pair<iterator, bool>
243 emplace(_Args&&... __args)
244 {
245 size_type __bucket_count = this->bucket_count();
246 std::pair<_Base_iterator, bool> __res
247 = _Base::emplace(std::forward<_Args>(__args)...);
248 _M_check_rehashed(__bucket_count);
249 return std::make_pair(iterator(__res.first, this), __res.second);
250 }
251
252 template<typename... _Args>
253 iterator
254 emplace_hint(const_iterator __hint, _Args&&... __args)
255 {
256 __glibcxx_check_insert(__hint);
257 size_type __bucket_count = this->bucket_count();
258 _Base_iterator __it = _Base::emplace_hint(__hint.base(),
259 std::forward<_Args>(__args)...);
260 _M_check_rehashed(__bucket_count);
261 return iterator(__it, this);
262 }
263
264 std::pair<iterator, bool>
265 insert(const value_type& __obj)
266 {
267 size_type __bucket_count = this->bucket_count();
268 typedef std::pair<_Base_iterator, bool> __pair_type;
269 __pair_type __res = _Base::insert(__obj);
270 _M_check_rehashed(__bucket_count);
271 return std::make_pair(iterator(__res.first, this), __res.second);
272 }
273
274 iterator
275 insert(const_iterator __hint, const value_type& __obj)
276 {
277 __glibcxx_check_insert(__hint);
278 size_type __bucket_count = this->bucket_count();
279 _Base_iterator __it = _Base::insert(__hint.base(), __obj);
280 _M_check_rehashed(__bucket_count);
281 return iterator(__it, this);
282 }
283
284 std::pair<iterator, bool>
285 insert(value_type&& __obj)
286 {
287 size_type __bucket_count = this->bucket_count();
288 typedef std::pair<typename _Base::iterator, bool> __pair_type;
289 __pair_type __res = _Base::insert(std::move(__obj));
290 _M_check_rehashed(__bucket_count);
291 return std::make_pair(iterator(__res.first, this), __res.second);
292 }
293
294 iterator
295 insert(const_iterator __hint, value_type&& __obj)
296 {
297 __glibcxx_check_insert(__hint);
298 size_type __bucket_count = this->bucket_count();
299 _Base_iterator __it = _Base::insert(__hint.base(), std::move(__obj));
300 _M_check_rehashed(__bucket_count);
301 return iterator(__it, this);
302 }
303
304 void
305 insert(std::initializer_list<value_type> __l)
306 {
307 size_type __bucket_count = this->bucket_count();
308 _Base::insert(__l);
309 _M_check_rehashed(__bucket_count);
310 }
311
312 template<typename _InputIterator>
313 void
314 insert(_InputIterator __first, _InputIterator __last)
315 {
316 __glibcxx_check_valid_range(__first, __last);
317 size_type __bucket_count = this->bucket_count();
318 _Base::insert(__gnu_debug::__base(__first),
319 __gnu_debug::__base(__last));
320 _M_check_rehashed(__bucket_count);
321 }
322
323 iterator
324 find(const key_type& __key)
325 { return iterator(_Base::find(__key), this); }
326
327 const_iterator
328 find(const key_type& __key) const
329 { return const_iterator(_Base::find(__key), this); }
330
331 std::pair<iterator, iterator>
332 equal_range(const key_type& __key)
333 {
334 typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
335 __pair_type __res = _Base::equal_range(__key);
336 return std::make_pair(iterator(__res.first, this),
337 iterator(__res.second, this));
338 }
339
340 std::pair<const_iterator, const_iterator>
341 equal_range(const key_type& __key) const
342 {
343 std::pair<_Base_const_iterator, _Base_const_iterator>
344 __res = _Base::equal_range(__key);
345 return std::make_pair(const_iterator(__res.first, this),
346 const_iterator(__res.second, this));
347 }
348
349 size_type
350 erase(const key_type& __key)
351 {
352 size_type __ret(0);
353 _Base_iterator __victim(_Base::find(__key));
354 if (__victim != _Base::end())
355 {
356 this->_M_invalidate_if(
357 [__victim](_Base_const_iterator __it)
358 { return __it == __victim; });
359 this->_M_invalidate_local_if(
360 [__victim](_Base_const_local_iterator __it)
361 { return __it._M_cur == __victim._M_cur; });
362 size_type __bucket_count = this->bucket_count();
363 _Base::erase(__victim);
364 _M_check_rehashed(__bucket_count);
365 __ret = 1;
366 }
367 return __ret;
368 }
369
370 iterator
371 erase(const_iterator __it)
372 {
373 __glibcxx_check_erase(__it);
374 _Base_const_iterator __victim = __it.base();
375 this->_M_invalidate_if(
376 [__victim](_Base_const_iterator __it)
377 { return __it == __victim; });
378 this->_M_invalidate_local_if(
379 [__victim](_Base_const_local_iterator __it)
380 { return __it._M_cur == __victim._M_cur; });
381 size_type __bucket_count = this->bucket_count();
382 _Base_iterator __next = _Base::erase(__it.base());
383 _M_check_rehashed(__bucket_count);
384 return iterator(__next, this);
385 }
386
387 iterator
388 erase(iterator __it)
389 { return erase(const_iterator(__it)); }
390
391 iterator
392 erase(const_iterator __first, const_iterator __last)
393 {
394 __glibcxx_check_erase_range(__first, __last);
395 for (_Base_const_iterator __tmp = __first.base();
396 __tmp != __last.base(); ++__tmp)
397 {
398 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
399 _M_message(__gnu_debug::__msg_valid_range)
400 ._M_iterator(__first, "first")
401 ._M_iterator(__last, "last"));
402 this->_M_invalidate_if(
403 [__tmp](_Base_const_iterator __it)
404 { return __it == __tmp; });
405 this->_M_invalidate_local_if(
406 [__tmp](_Base_const_local_iterator __it)
407 { return __it._M_cur == __tmp._M_cur; });
408 }
409 size_type __bucket_count = this->bucket_count();
410 _Base_iterator __next = _Base::erase(__first.base(),
411 __last.base());
412 _M_check_rehashed(__bucket_count);
413 return iterator(__next, this);
414 }
415
416 _Base&
417 _M_base() noexcept { return *this; }
418
419 const _Base&
420 _M_base() const noexcept { return *this; }
421
422 private:
423 void
424 _M_invalidate_locals()
425 {
426 _Base_local_iterator __local_end = _Base::end(0);
427 this->_M_invalidate_local_if(
428 [__local_end](_Base_const_local_iterator __it)
429 { return __it != __local_end; });
430 }
431
432 void
433 _M_invalidate_all()
434 {
435 _Base_iterator __end = _Base::end();
436 this->_M_invalidate_if(
437 [__end](_Base_const_iterator __it)
438 { return __it != __end; });
439 _M_invalidate_locals();
440 }
441
442 void
443 _M_check_rehashed(size_type __prev_count)
444 {
445 if (__prev_count != this->bucket_count())
446 _M_invalidate_locals();
447 }
448 };
449
450 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
451 inline void
452 swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
453 unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
454 { __x.swap(__y); }
455
456 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
457 inline bool
458 operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
459 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
460 { return __x._M_base() == __y._M_base(); }
461
462 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
463 inline bool
464 operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
465 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
466 { return !(__x == __y); }
467
468
469 /// Class std::unordered_multiset with safety/checking/debug instrumentation.
470 template<typename _Value,
471 typename _Hash = std::hash<_Value>,
472 typename _Pred = std::equal_to<_Value>,
473 typename _Alloc = std::allocator<_Value> >
474 class unordered_multiset
475 : public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc>,
476 public __gnu_debug::_Safe_unordered_container<
477 unordered_multiset<_Value, _Hash, _Pred, _Alloc> >
478 {
479 typedef _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash,
480 _Pred, _Alloc> _Base;
481 typedef __gnu_debug::_Safe_unordered_container<unordered_multiset>
482 _Safe_base;
483 typedef typename _Base::const_iterator _Base_const_iterator;
484 typedef typename _Base::iterator _Base_iterator;
485 typedef typename _Base::const_local_iterator _Base_const_local_iterator;
486 typedef typename _Base::local_iterator _Base_local_iterator;
487
488 public:
489 typedef typename _Base::size_type size_type;
490 typedef typename _Base::hasher hasher;
491 typedef typename _Base::key_equal key_equal;
492 typedef typename _Base::allocator_type allocator_type;
493
494 typedef typename _Base::key_type key_type;
495 typedef typename _Base::value_type value_type;
496
497 typedef __gnu_debug::_Safe_iterator<_Base_iterator,
498 unordered_multiset> iterator;
499 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
500 unordered_multiset> const_iterator;
501 typedef __gnu_debug::_Safe_local_iterator<
502 _Base_local_iterator, unordered_multiset> local_iterator;
503 typedef __gnu_debug::_Safe_local_iterator<
504 _Base_const_local_iterator, unordered_multiset> const_local_iterator;
505
506 explicit
507 unordered_multiset(size_type __n = 10,
508 const hasher& __hf = hasher(),
509 const key_equal& __eql = key_equal(),
510 const allocator_type& __a = allocator_type())
511 : _Base(__n, __hf, __eql, __a) { }
512
513 template<typename _InputIterator>
514 unordered_multiset(_InputIterator __first, _InputIterator __last,
515 size_type __n = 0,
516 const hasher& __hf = hasher(),
517 const key_equal& __eql = key_equal(),
518 const allocator_type& __a = allocator_type())
519 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
520 __last)),
521 __gnu_debug::__base(__last), __n,
522 __hf, __eql, __a) { }
523
524 unordered_multiset(const unordered_multiset& __x) = default;
525
526 unordered_multiset(const _Base& __x)
527 : _Base(__x) { }
528
529 unordered_multiset(unordered_multiset&& __x) = default;
530
531 unordered_multiset(initializer_list<value_type> __l,
532 size_type __n = 0,
533 const hasher& __hf = hasher(),
534 const key_equal& __eql = key_equal(),
535 const allocator_type& __a = allocator_type())
536 : _Base(__l, __n, __hf, __eql, __a) { }
537
538 ~unordered_multiset() noexcept { }
539
540 unordered_multiset&
541 operator=(const unordered_multiset& __x)
542 {
543 *static_cast<_Base*>(this) = __x;
544 this->_M_invalidate_all();
545 return *this;
546 }
547
548 unordered_multiset&
549 operator=(unordered_multiset&& __x)
550 {
551 // NB: DR 1204.
552 // NB: DR 675.
553 __glibcxx_check_self_move_assign(__x);
554 clear();
555 swap(__x);
556 return *this;
557 }
558
559 unordered_multiset&
560 operator=(initializer_list<value_type> __l)
561 {
562 this->clear();
563 this->insert(__l);
564 return *this;
565 }
566
567 void
568 swap(unordered_multiset& __x)
569 {
570 _Base::swap(__x);
571 _Safe_base::_M_swap(__x);
572 }
573
574 void
575 clear() noexcept
576 {
577 _Base::clear();
578 this->_M_invalidate_all();
579 }
580
581 iterator
582 begin() noexcept
583 { return iterator(_Base::begin(), this); }
584
585 const_iterator
586 begin() const noexcept
587 { return const_iterator(_Base::begin(), this); }
588
589 iterator
590 end() noexcept
591 { return iterator(_Base::end(), this); }
592
593 const_iterator
594 end() const noexcept
595 { return const_iterator(_Base::end(), this); }
596
597 const_iterator
598 cbegin() const noexcept
599 { return const_iterator(_Base::begin(), this); }
600
601 const_iterator
602 cend() const noexcept
603 { return const_iterator(_Base::end(), this); }
604
605 // local versions
606 local_iterator
607 begin(size_type __b)
608 {
609 __glibcxx_check_bucket_index(__b);
610 return local_iterator(_Base::begin(__b), __b, this);
611 }
612
613 local_iterator
614 end(size_type __b)
615 {
616 __glibcxx_check_bucket_index(__b);
617 return local_iterator(_Base::end(__b), __b, this);
618 }
619
620 const_local_iterator
621 begin(size_type __b) const
622 {
623 __glibcxx_check_bucket_index(__b);
624 return const_local_iterator(_Base::begin(__b), __b, this);
625 }
626
627 const_local_iterator
628 end(size_type __b) const
629 {
630 __glibcxx_check_bucket_index(__b);
631 return const_local_iterator(_Base::end(__b), __b, this);
632 }
633
634 const_local_iterator
635 cbegin(size_type __b) const
636 {
637 __glibcxx_check_bucket_index(__b);
638 return const_local_iterator(_Base::cbegin(__b), __b, this);
639 }
640
641 const_local_iterator
642 cend(size_type __b) const
643 {
644 __glibcxx_check_bucket_index(__b);
645 return const_local_iterator(_Base::cend(__b), __b, this);
646 }
647
648 size_type
649 bucket_size(size_type __b) const
650 {
651 __glibcxx_check_bucket_index(__b);
652 return _Base::bucket_size(__b);
653 }
654
655 float
656 max_load_factor() const noexcept
657 { return _Base::max_load_factor(); }
658
659 void
660 max_load_factor(float __f)
661 {
662 __glibcxx_check_max_load_factor(__f);
663 _Base::max_load_factor(__f);
664 }
665
666 template<typename... _Args>
667 iterator
668 emplace(_Args&&... __args)
669 {
670 size_type __bucket_count = this->bucket_count();
671 _Base_iterator __it
672 = _Base::emplace(std::forward<_Args>(__args)...);
673 _M_check_rehashed(__bucket_count);
674 return iterator(__it, this);
675 }
676
677 template<typename... _Args>
678 iterator
679 emplace_hint(const_iterator __hint, _Args&&... __args)
680 {
681 __glibcxx_check_insert(__hint);
682 size_type __bucket_count = this->bucket_count();
683 _Base_iterator __it = _Base::emplace_hint(__hint.base(),
684 std::forward<_Args>(__args)...);
685 _M_check_rehashed(__bucket_count);
686 return iterator(__it, this);
687 }
688
689 iterator
690 insert(const value_type& __obj)
691 {
692 size_type __bucket_count = this->bucket_count();
693 _Base_iterator __it = _Base::insert(__obj);
694 _M_check_rehashed(__bucket_count);
695 return iterator(__it, this);
696 }
697
698 iterator
699 insert(const_iterator __hint, const value_type& __obj)
700 {
701 __glibcxx_check_insert(__hint);
702 size_type __bucket_count = this->bucket_count();
703 _Base_iterator __it = _Base::insert(__hint.base(), __obj);
704 _M_check_rehashed(__bucket_count);
705 return iterator(__it, this);
706 }
707
708 iterator
709 insert(value_type&& __obj)
710 {
711 size_type __bucket_count = this->bucket_count();
712 _Base_iterator __it = _Base::insert(std::move(__obj));
713 _M_check_rehashed(__bucket_count);
714 return iterator(__it, this);
715 }
716
717 iterator
718 insert(const_iterator __hint, value_type&& __obj)
719 {
720 __glibcxx_check_insert(__hint);
721 size_type __bucket_count = this->bucket_count();
722 _Base_iterator __it = _Base::insert(__hint.base(), std::move(__obj));
723 _M_check_rehashed(__bucket_count);
724 return iterator(__it, this);
725 }
726
727 void
728 insert(std::initializer_list<value_type> __l)
729 {
730 size_type __bucket_count = this->bucket_count();
731 _Base::insert(__l);
732 _M_check_rehashed(__bucket_count);
733 }
734
735 template<typename _InputIterator>
736 void
737 insert(_InputIterator __first, _InputIterator __last)
738 {
739 __glibcxx_check_valid_range(__first, __last);
740 size_type __bucket_count = this->bucket_count();
741 _Base::insert(__gnu_debug::__base(__first),
742 __gnu_debug::__base(__last));
743 _M_check_rehashed(__bucket_count);
744 }
745
746 iterator
747 find(const key_type& __key)
748 { return iterator(_Base::find(__key), this); }
749
750 const_iterator
751 find(const key_type& __key) const
752 { return const_iterator(_Base::find(__key), this); }
753
754 std::pair<iterator, iterator>
755 equal_range(const key_type& __key)
756 {
757 typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
758 __pair_type __res = _Base::equal_range(__key);
759 return std::make_pair(iterator(__res.first, this),
760 iterator(__res.second, this));
761 }
762
763 std::pair<const_iterator, const_iterator>
764 equal_range(const key_type& __key) const
765 {
766 std::pair<_Base_const_iterator, _Base_const_iterator>
767 __res = _Base::equal_range(__key);
768 return std::make_pair(const_iterator(__res.first, this),
769 const_iterator(__res.second, this));
770 }
771
772 size_type
773 erase(const key_type& __key)
774 {
775 size_type __ret(0);
776 std::pair<_Base_iterator, _Base_iterator> __pair =
777 _Base::equal_range(__key);
778 for (_Base_iterator __victim = __pair.first; __victim != __pair.second;)
779 {
780 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
781 { return __it == __victim; });
782 this->_M_invalidate_local_if(
783 [__victim](_Base_const_local_iterator __it)
784 { return __it._M_cur == __victim._M_cur; });
785 _Base::erase(__victim++);
786 ++__ret;
787 }
788 return __ret;
789 }
790
791 iterator
792 erase(const_iterator __it)
793 {
794 __glibcxx_check_erase(__it);
795 _Base_const_iterator __victim = __it.base();
796 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
797 { return __it == __victim; });
798 this->_M_invalidate_local_if(
799 [__victim](_Base_const_local_iterator __it)
800 { return __it._M_cur == __victim._M_cur; });
801 return iterator(_Base::erase(__it.base()), this);
802 }
803
804 iterator
805 erase(iterator __it)
806 { return erase(const_iterator(__it)); }
807
808 iterator
809 erase(const_iterator __first, const_iterator __last)
810 {
811 __glibcxx_check_erase_range(__first, __last);
812 for (_Base_const_iterator __tmp = __first.base();
813 __tmp != __last.base(); ++__tmp)
814 {
815 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
816 _M_message(__gnu_debug::__msg_valid_range)
817 ._M_iterator(__first, "first")
818 ._M_iterator(__last, "last"));
819 this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
820 { return __it == __tmp; });
821 this->_M_invalidate_local_if(
822 [__tmp](_Base_const_local_iterator __it)
823 { return __it._M_cur == __tmp._M_cur; });
824 }
825 return iterator(_Base::erase(__first.base(),
826 __last.base()), this);
827 }
828
829 _Base&
830 _M_base() noexcept { return *this; }
831
832 const _Base&
833 _M_base() const noexcept { return *this; }
834
835 private:
836 void
837 _M_invalidate_locals()
838 {
839 _Base_local_iterator __local_end = _Base::end(0);
840 this->_M_invalidate_local_if(
841 [__local_end](_Base_const_local_iterator __it)
842 { return __it != __local_end; });
843 }
844
845 void
846 _M_invalidate_all()
847 {
848 _Base_iterator __end = _Base::end();
849 this->_M_invalidate_if([__end](_Base_const_iterator __it)
850 { return __it != __end; });
851 _M_invalidate_locals();
852 }
853
854 void
855 _M_check_rehashed(size_type __prev_count)
856 {
857 if (__prev_count != this->bucket_count())
858 _M_invalidate_locals();
859 }
860 };
861
862 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
863 inline void
864 swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
865 unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
866 { __x.swap(__y); }
867
868 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
869 inline bool
870 operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
871 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
872 { return __x._M_base() == __y._M_base(); }
873
874 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
875 inline bool
876 operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
877 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
878 { return !(__x == __y); }
879
880 } // namespace __debug
881 } // namespace std
882
883 #endif // C++11
884
885 #endif