OSDN Git Service

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