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