libstdc++
debug/unordered_set
Go to the documentation of this file.
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 
39 #include <debug/safe_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> >
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;
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,
75  typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
77  typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator,
79  typedef __gnu_debug::_Safe_local_iterator<_Base_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 
107  : _Base(std::move(__x)) { }
108 
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 
119  operator=(const unordered_set& __x)
120  {
121  *static_cast<_Base*>(this) = __x;
122  this->_M_invalidate_all();
123  return *this;
124  }
125 
127  operator=(unordered_set&& __x)
128  {
129  // NB: DR 1204.
130  // NB: DR 675.
131  clear();
132  swap(__x);
133  return *this;
134  }
135 
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 
163  begin() const noexcept
164  { return const_iterator(_Base::begin(), this); }
165 
166  iterator
167  end() noexcept
168  { return iterator(_Base::end(), this); }
169 
171  end() const noexcept
172  { return const_iterator(_Base::end(), this); }
173 
175  cbegin() const noexcept
176  { return const_iterator(_Base::begin(), this); }
177 
179  cend() const noexcept
180  { return const_iterator(_Base::end(), this); }
181 
182  // local versions
184  begin(size_type __b)
185  { return local_iterator(_Base::begin(__b), __b, this); }
186 
188  end(size_type __b)
189  { return local_iterator(_Base::end(__b), __b, this); }
190 
192  begin(size_type __b) const
193  { return const_local_iterator(_Base::begin(__b), __b, this); }
194 
196  end(size_type __b) const
197  { return const_local_iterator(_Base::end(__b), __b, this); }
198 
200  cbegin(size_type __b) const
201  { return const_local_iterator(_Base::cbegin(__b), __b, this); }
202 
204  cend(size_type __b) const
205  { return const_local_iterator(_Base::cend(__b), __b, this); }
206 
207  template<typename... _Args>
209  emplace(_Args&&... __args)
210  {
211  size_type __bucket_count = this->bucket_count();
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 
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 
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
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 
294  find(const key_type& __key) const
295  { return const_iterator(_Base::find(__key), this); }
296 
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 
307  equal_range(const key_type& __key) const
308  {
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);
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);
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);
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);
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
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,
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> >
460  : public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc>,
462  unordered_multiset<_Value, _Hash, _Pred, _Alloc> >
463  {
464  typedef _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash,
465  _Pred, _Alloc> _Base;
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,
484  typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
487  _Base_local_iterator, unordered_multiset> 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 
510  : _Base(__x) { }
511 
512  unordered_multiset(const _Base& __x)
513  : _Base(__x) { }
514 
516  : _Base(std::move(__x)) { }
517 
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 
528  operator=(const unordered_multiset& __x)
529  {
530  *static_cast<_Base*>(this) = __x;
531  this->_M_invalidate_all();
532  return *this;
533  }
534 
536  operator=(unordered_multiset&& __x)
537  {
538  // NB: DR 1204.
539  // NB: DR 675.
540  clear();
541  swap(__x);
542  return *this;
543  }
544 
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 
572  begin() const noexcept
573  { return const_iterator(_Base::begin(), this); }
574 
575  iterator
576  end() noexcept
577  { return iterator(_Base::end(), this); }
578 
580  end() const noexcept
581  { return const_iterator(_Base::end(), this); }
582 
584  cbegin() const noexcept
585  { return const_iterator(_Base::begin(), this); }
586 
588  cend() const noexcept
589  { return const_iterator(_Base::end(), this); }
590 
591  // local versions
593  begin(size_type __b)
594  { return local_iterator(_Base::begin(__b), __b, this); }
595 
597  end(size_type __b)
598  { return local_iterator(_Base::end(__b), __b, this); }
599 
601  begin(size_type __b) const
602  { return const_local_iterator(_Base::begin(__b), __b, this); }
603 
605  end(size_type __b) const
606  { return const_local_iterator(_Base::end(__b), __b, this); }
607 
609  cbegin(size_type __b) const
610  { return const_local_iterator(_Base::cbegin(__b), __b, this); }
611 
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
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 
701  find(const key_type& __key) const
702  { return const_iterator(_Base::find(__key), this); }
703 
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 
714  equal_range(const key_type& __key) const
715  {
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);
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);
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);
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);
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);
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
835  { __x.swap(__y); }
836 
837  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
838  inline bool
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