1// Debugging unordered_map/unordered_multimap 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_map
27 *  This file is a GNU debug extension to the Standard C++ Library.
28 */
29
30#ifndef _GLIBCXX_DEBUG_UNORDERED_MAP
31#define _GLIBCXX_DEBUG_UNORDERED_MAP 1
32
33#ifndef __GXX_EXPERIMENTAL_CXX0X__
34# include <bits/c++0x_warning.h>
35#else
36# include <unordered_map>
37
38#include <debug/safe_unordered_container.h>
39#include <debug/safe_iterator.h>
40#include <debug/safe_local_iterator.h>
41
42namespace std _GLIBCXX_VISIBILITY(default)
43{
44namespace __debug
45{
46  /// Class std::unordered_map with safety/checking/debug instrumentation.
47  template<typename _Key, typename _Tp,
48	   typename _Hash = std::hash<_Key>,
49	   typename _Pred = std::equal_to<_Key>,
50	   typename _Alloc = std::allocator<_Key> >
51    class unordered_map
52    : public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>,
53      public __gnu_debug::_Safe_unordered_container<unordered_map<_Key, _Tp,
54							_Hash, _Pred, _Alloc> >
55    {
56      typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash,
57					    _Pred, _Alloc> _Base;
58      typedef __gnu_debug::_Safe_unordered_container<unordered_map> _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_map> iterator;
75      typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
76					  unordered_map> const_iterator;
77      typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator,
78					  unordered_map> local_iterator;
79      typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator,
80					  unordered_map> const_local_iterator;
81
82      explicit
83      unordered_map(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_map(_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_map(const unordered_map& __x)
101      : _Base(__x) { }
102
103      unordered_map(const _Base& __x)
104      : _Base(__x) { }
105
106      unordered_map(unordered_map&& __x)
107      : _Base(std::move(__x)) { }
108
109      unordered_map(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_map() noexcept { }
117
118      unordered_map&
119      operator=(const unordered_map& __x)
120      {
121	*static_cast<_Base*>(this) = __x;
122	this->_M_invalidate_all();
123	return *this;
124      }
125
126      unordered_map&
127      operator=(unordered_map&& __x)
128      {
129   	// NB: DR 1204.
130	// NB: DR 675.
131	clear();
132	swap(__x);
133	return *this;
134      }
135
136      unordered_map&
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_map& __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	std::pair<_Base_iterator, bool> __res = _Base::insert(__obj);
235	_M_check_rehashed(__bucket_count);
236	return std::make_pair(iterator(__res.first, this), __res.second);
237      }
238
239      iterator
240      insert(const_iterator __hint, const value_type& __obj)
241      {
242	__glibcxx_check_insert(__hint);
243	size_type __bucket_count = this->bucket_count();
244	_Base_iterator __it = _Base::insert(__hint.base(), __obj);
245	_M_check_rehashed(__bucket_count);
246	return iterator(__it, this);
247      }
248
249      template<typename _Pair, typename = typename
250	       std::enable_if<std::is_constructible<value_type,
251						    _Pair&&>::value>::type>
252	std::pair<iterator, bool>
253	insert(_Pair&& __obj)
254	{
255	  size_type __bucket_count = this->bucket_count();
256	  std::pair<_Base_iterator, bool> __res =
257	    _Base::insert(std::forward<_Pair>(__obj));
258	  _M_check_rehashed(__bucket_count);
259	  return std::make_pair(iterator(__res.first, this), __res.second);
260	}
261
262      template<typename _Pair, typename = typename
263	       std::enable_if<std::is_constructible<value_type,
264						    _Pair&&>::value>::type>
265	iterator
266	insert(const_iterator __hint, _Pair&& __obj)
267	{
268	  __glibcxx_check_insert(__hint);
269	  size_type __bucket_count = this->bucket_count();
270	  _Base_iterator __it =
271	    _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
272	  _M_check_rehashed(__bucket_count);
273	  return iterator(__it, this);
274	}
275
276      void
277      insert(std::initializer_list<value_type> __l)
278      {
279	size_type __bucket_count = this->bucket_count();
280	_Base::insert(__l);
281	_M_check_rehashed(__bucket_count);
282      }
283
284      template<typename _InputIterator>
285	void
286	insert(_InputIterator __first, _InputIterator __last)
287	{
288	  __glibcxx_check_valid_range(__first, __last);
289	  size_type __bucket_count = this->bucket_count();
290	  _Base::insert(__gnu_debug::__base(__first),
291			__gnu_debug::__base(__last));
292	  _M_check_rehashed(__bucket_count);
293	}
294
295      iterator
296      find(const key_type& __key)
297      { return iterator(_Base::find(__key), this); }
298
299      const_iterator
300      find(const key_type& __key) const
301      { return const_iterator(_Base::find(__key), this); }
302
303      std::pair<iterator, iterator>
304      equal_range(const key_type& __key)
305      {
306	std::pair<_Base_iterator, _Base_iterator> __res =
307	  _Base::equal_range(__key);
308	return std::make_pair(iterator(__res.first, this),
309			      iterator(__res.second, this));
310      }
311
312      std::pair<const_iterator, const_iterator>
313      equal_range(const key_type& __key) const
314      {
315	std::pair<_Base_const_iterator, _Base_const_iterator> __res =
316	  _Base::equal_range(__key);
317	return std::make_pair(const_iterator(__res.first, this),
318			      const_iterator(__res.second, this));
319      }
320
321      size_type
322      erase(const key_type& __key)
323      {
324	size_type __ret(0);
325	_Base_iterator __victim(_Base::find(__key));
326	if (__victim != _Base::end())
327	  {
328	    this->_M_invalidate_if([__victim](_Base_const_iterator __it)
329			    { return __it == __victim; });
330	    _Base_local_iterator __local_victim = _S_to_local(__victim);
331	    this->_M_invalidate_local_if(
332			    [__local_victim](_Base_const_local_iterator __it)
333			    { return __it == __local_victim; });
334	    size_type __bucket_count = this->bucket_count();
335	    _Base::erase(__victim);
336	    _M_check_rehashed(__bucket_count);
337	    __ret = 1;
338	  }
339	return __ret;
340      }
341
342      iterator
343      erase(const_iterator __it)
344      {
345	__glibcxx_check_erase(__it);
346	_Base_const_iterator __victim = __it.base();
347	this->_M_invalidate_if([__victim](_Base_const_iterator __it)
348			{ return __it == __victim; });
349	_Base_const_local_iterator __local_victim = _S_to_local(__victim);
350	this->_M_invalidate_local_if(
351			[__local_victim](_Base_const_local_iterator __it)
352			{ return __it == __local_victim; });
353	size_type __bucket_count = this->bucket_count();
354	_Base_iterator __next = _Base::erase(__it.base());
355	_M_check_rehashed(__bucket_count);
356	return iterator(__next, this);
357      }
358
359      iterator
360      erase(iterator __it)
361      { return erase(const_iterator(__it)); }
362
363      iterator
364      erase(const_iterator __first, const_iterator __last)
365      {
366	__glibcxx_check_erase_range(__first, __last);
367	for (_Base_const_iterator __tmp = __first.base();
368	     __tmp != __last.base(); ++__tmp)
369	  {
370	    _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
371				  _M_message(__gnu_debug::__msg_valid_range)
372				  ._M_iterator(__first, "first")
373				  ._M_iterator(__last, "last"));
374	    this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
375			    { return __it == __tmp; });
376	    _Base_const_local_iterator __local_tmp = _S_to_local(__tmp);
377	    this->_M_invalidate_local_if(
378			    [__local_tmp](_Base_const_local_iterator __it)
379			    { return __it == __local_tmp; });
380	  }
381	size_type __bucket_count = this->bucket_count();
382	_Base_iterator __next = _Base::erase(__first.base(), __last.base());
383	_M_check_rehashed(__bucket_count);
384	return iterator(__next, this);
385      }
386
387      _Base&
388      _M_base() noexcept       { return *this; }
389
390      const _Base&
391      _M_base() const noexcept { return *this; }
392
393    private:
394      void
395      _M_invalidate_locals()
396      {
397	_Base_local_iterator __local_end = _Base::end(0);
398	this->_M_invalidate_local_if(
399			[__local_end](_Base_const_local_iterator __it)
400			{ return __it != __local_end; });
401      }
402
403      void
404      _M_invalidate_all()
405      {
406	_Base_iterator __end = _Base::end();
407	this->_M_invalidate_if([__end](_Base_const_iterator __it)
408			{ return __it != __end; });
409	_M_invalidate_locals();
410      }
411
412      void
413      _M_check_rehashed(size_type __prev_count)
414      {
415	if (__prev_count != this->bucket_count())
416	  _M_invalidate_locals();
417      }
418
419      static _Base_local_iterator
420      _S_to_local(_Base_iterator __it)
421      {
422        // The returned local iterator will not be incremented so we don't
423	// need to compute __it's node bucket
424	return _Base_local_iterator(__it._M_cur, 0, 0);
425      }
426
427      static _Base_const_local_iterator
428      _S_to_local(_Base_const_iterator __it)
429      {
430        // The returned local iterator will not be incremented so we don't
431	// need to compute __it's node bucket
432	return _Base_const_local_iterator(__it._M_cur, 0, 0);
433      }
434    };
435
436  template<typename _Key, typename _Tp, typename _Hash,
437	   typename _Pred, typename _Alloc>
438    inline void
439    swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
440	 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
441    { __x.swap(__y); }
442
443  template<typename _Key, typename _Tp, typename _Hash,
444	   typename _Pred, typename _Alloc>
445    inline bool
446    operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
447	       const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
448    { return __x._M_equal(__y); }
449
450  template<typename _Key, typename _Tp, typename _Hash,
451	   typename _Pred, typename _Alloc>
452    inline bool
453    operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
454	       const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
455    { return !(__x == __y); }
456
457
458  /// Class std::unordered_multimap with safety/checking/debug instrumentation.
459  template<typename _Key, typename _Tp,
460	   typename _Hash = std::hash<_Key>,
461	   typename _Pred = std::equal_to<_Key>,
462	   typename _Alloc = std::allocator<_Key> >
463    class unordered_multimap
464    : public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
465						_Pred, _Alloc>,
466      public __gnu_debug::_Safe_unordered_container<unordered_multimap<_Key,
467						_Tp, _Hash, _Pred, _Alloc> >
468    {
469      typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
470						 _Pred, _Alloc> _Base;
471      typedef __gnu_debug::_Safe_unordered_container<unordered_multimap>
472	_Safe_base;
473      typedef typename _Base::const_iterator _Base_const_iterator;
474      typedef typename _Base::iterator _Base_iterator;
475      typedef typename _Base::const_local_iterator _Base_const_local_iterator;
476      typedef typename _Base::local_iterator _Base_local_iterator;
477
478    public:
479      typedef typename _Base::size_type       size_type;
480      typedef typename _Base::hasher          hasher;
481      typedef typename _Base::key_equal       key_equal;
482      typedef typename _Base::allocator_type  allocator_type;
483
484      typedef typename _Base::key_type        key_type;
485      typedef typename _Base::value_type      value_type;
486
487      typedef __gnu_debug::_Safe_iterator<_Base_iterator,
488					  unordered_multimap> iterator;
489      typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
490					  unordered_multimap> const_iterator;
491      typedef __gnu_debug::_Safe_local_iterator<
492	_Base_local_iterator, unordered_multimap> local_iterator;
493      typedef __gnu_debug::_Safe_local_iterator<
494	_Base_const_local_iterator, unordered_multimap> const_local_iterator;
495
496      explicit
497      unordered_multimap(size_type __n = 10,
498			 const hasher& __hf = hasher(),
499			 const key_equal& __eql = key_equal(),
500			 const allocator_type& __a = allocator_type())
501      : _Base(__n, __hf, __eql, __a) { }
502
503      template<typename _InputIterator>
504	unordered_multimap(_InputIterator __first, _InputIterator __last,
505			   size_type __n = 0,
506			   const hasher& __hf = hasher(),
507			   const key_equal& __eql = key_equal(),
508			   const allocator_type& __a = allocator_type())
509	: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
510								     __last)),
511		__gnu_debug::__base(__last), __n,
512		__hf, __eql, __a) { }
513
514      unordered_multimap(const unordered_multimap& __x)
515      : _Base(__x) { }
516
517      unordered_multimap(const _Base& __x)
518      : _Base(__x) { }
519
520      unordered_multimap(unordered_multimap&& __x)
521      : _Base(std::move(__x)) { }
522
523      unordered_multimap(initializer_list<value_type> __l,
524			 size_type __n = 0,
525			 const hasher& __hf = hasher(),
526			 const key_equal& __eql = key_equal(),
527			 const allocator_type& __a = allocator_type())
528      : _Base(__l, __n, __hf, __eql, __a) { }
529
530      ~unordered_multimap() noexcept { }
531
532      unordered_multimap&
533      operator=(const unordered_multimap& __x)
534      {
535	*static_cast<_Base*>(this) = __x;
536	this->_M_invalidate_all();
537	return *this;
538      }
539
540      unordered_multimap&
541      operator=(unordered_multimap&& __x)
542      {
543	// NB: DR 1204.
544	// NB: DR 675.
545	clear();
546	swap(__x);
547	return *this;
548      }
549
550      unordered_multimap&
551      operator=(initializer_list<value_type> __l)
552      {
553	this->clear();
554	this->insert(__l);
555	return *this;
556      }
557
558      void
559      swap(unordered_multimap& __x)
560      {
561	_Base::swap(__x);
562	_Safe_base::_M_swap(__x);
563      }
564
565      void
566      clear() noexcept
567      {
568	_Base::clear();
569	this->_M_invalidate_all();
570      }
571
572      iterator
573      begin() noexcept
574      { return iterator(_Base::begin(), this); }
575
576      const_iterator
577      begin() const noexcept
578      { return const_iterator(_Base::begin(), this); }
579
580      iterator
581      end() noexcept
582      { return iterator(_Base::end(), this); }
583
584      const_iterator
585      end() const noexcept
586      { return const_iterator(_Base::end(), this); }
587
588      const_iterator
589      cbegin() const noexcept
590      { return const_iterator(_Base::begin(), this); }
591
592      const_iterator
593      cend() const noexcept
594      { return const_iterator(_Base::end(), this); }
595
596      // local versions
597      local_iterator
598      begin(size_type __b)
599      { return local_iterator(_Base::begin(__b), __b, this); }
600
601      local_iterator
602      end(size_type __b)
603      { return local_iterator(_Base::end(__b), __b, this); }
604
605      const_local_iterator
606      begin(size_type __b) const
607      { return const_local_iterator(_Base::begin(__b), __b, this); }
608
609      const_local_iterator
610      end(size_type __b) const
611      { return const_local_iterator(_Base::end(__b), __b, this); }
612
613      const_local_iterator
614      cbegin(size_type __b) const
615      { return const_local_iterator(_Base::cbegin(__b), __b, this); }
616
617      const_local_iterator
618      cend(size_type __b) const
619      { return const_local_iterator(_Base::cend(__b), __b, this); }
620
621      template<typename... _Args>
622	iterator
623	emplace(_Args&&... __args)
624	{
625	  size_type __bucket_count = this->bucket_count();
626	  _Base_iterator __it
627	    = _Base::emplace(std::forward<_Args>(__args)...);
628	  _M_check_rehashed(__bucket_count);
629	  return iterator(__it, this);
630	}
631
632      template<typename... _Args>
633	iterator
634	emplace_hint(const_iterator __hint, _Args&&... __args)
635	{
636	  __glibcxx_check_insert(__hint);
637	  size_type __bucket_count = this->bucket_count();
638	  _Base_iterator __it = _Base::emplace_hint(__hint.base(),
639					std::forward<_Args>(__args)...);
640	  _M_check_rehashed(__bucket_count);
641	  return iterator(__it, this);
642	}
643
644      iterator
645      insert(const value_type& __obj)
646      {
647	size_type __bucket_count = this->bucket_count();
648	_Base_iterator __it = _Base::insert(__obj);
649	_M_check_rehashed(__bucket_count);
650	return iterator(__it, this);
651      }
652
653      iterator
654      insert(const_iterator __hint, const value_type& __obj)
655      {
656	__glibcxx_check_insert(__hint);
657	size_type __bucket_count = this->bucket_count();
658	_Base_iterator __it = _Base::insert(__hint.base(), __obj);
659	_M_check_rehashed(__bucket_count);
660	return iterator(__it, this);
661      }
662
663      template<typename _Pair, typename = typename
664	       std::enable_if<std::is_constructible<value_type,
665						    _Pair&&>::value>::type>
666	iterator
667	insert(_Pair&& __obj)
668	{
669	  size_type __bucket_count = this->bucket_count();
670	  _Base_iterator __it = _Base::insert(std::forward<_Pair>(__obj));
671	  _M_check_rehashed(__bucket_count);
672	  return iterator(__it, this);
673	}
674
675      template<typename _Pair, typename = typename
676	       std::enable_if<std::is_constructible<value_type,
677						    _Pair&&>::value>::type>
678	iterator
679	insert(const_iterator __hint, _Pair&& __obj)
680	{
681	  __glibcxx_check_insert(__hint);
682	  size_type __bucket_count = this->bucket_count();
683	  _Base_iterator __it =
684	    _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
685	  _M_check_rehashed(__bucket_count);
686	  return iterator(__it, this);
687	}
688
689      void
690      insert(std::initializer_list<value_type> __l)
691      { _Base::insert(__l); }
692
693      template<typename _InputIterator>
694	void
695	insert(_InputIterator __first, _InputIterator __last)
696	{
697	  __glibcxx_check_valid_range(__first, __last);
698	  size_type __bucket_count = this->bucket_count();
699	  _Base::insert(__gnu_debug::__base(__first),
700			__gnu_debug::__base(__last));
701	  _M_check_rehashed(__bucket_count);
702	}
703
704      iterator
705      find(const key_type& __key)
706      { return iterator(_Base::find(__key), this); }
707
708      const_iterator
709      find(const key_type& __key) const
710      { return const_iterator(_Base::find(__key), this); }
711
712      std::pair<iterator, iterator>
713      equal_range(const key_type& __key)
714      {
715	std::pair<_Base_iterator, _Base_iterator> __res =
716	  _Base::equal_range(__key);
717	return std::make_pair(iterator(__res.first, this),
718			      iterator(__res.second, this));
719      }
720
721      std::pair<const_iterator, const_iterator>
722      equal_range(const key_type& __key) const
723      {
724	std::pair<_Base_const_iterator, _Base_const_iterator> __res =
725	  _Base::equal_range(__key);
726	return std::make_pair(const_iterator(__res.first, this),
727			      const_iterator(__res.second, this));
728      }
729
730      size_type
731      erase(const key_type& __key)
732      {
733	size_type __ret(0);
734	size_type __bucket_count = this->bucket_count();
735	std::pair<_Base_iterator, _Base_iterator> __pair =
736	  _Base::equal_range(__key);
737	for (_Base_iterator __victim = __pair.first; __victim != __pair.second;)
738	  {
739	    this->_M_invalidate_if([__victim](_Base_const_iterator __it)
740			    { return __it == __victim; });
741	    _Base_local_iterator __local_victim = _S_to_local(__victim);
742	    this->_M_invalidate_local_if(
743			    [__local_victim](_Base_const_local_iterator __it)
744			    { return __it == __local_victim; });
745	    _Base::erase(__victim++);
746	    ++__ret;
747	  }
748	_M_check_rehashed(__bucket_count);
749	return __ret;
750      }
751
752      iterator
753      erase(const_iterator __it)
754      {
755	__glibcxx_check_erase(__it);
756	_Base_const_iterator __victim = __it.base();
757	this->_M_invalidate_if([__victim](_Base_const_iterator __it)
758			{ return __it == __victim; });
759	_Base_const_local_iterator __local_victim = _S_to_local(__victim);
760	this->_M_invalidate_local_if(
761			[__local_victim](_Base_const_local_iterator __it)
762			{ return __it == __local_victim; });
763	size_type __bucket_count = this->bucket_count();
764	_Base_iterator __next = _Base::erase(__it.base());
765	_M_check_rehashed(__bucket_count);
766	return iterator(__next, this);
767      }
768
769      iterator
770      erase(iterator __it)
771      { return erase(const_iterator(__it)); }
772
773      iterator
774      erase(const_iterator __first, const_iterator __last)
775      {
776	__glibcxx_check_erase_range(__first, __last);
777	for (_Base_const_iterator __tmp = __first.base();
778	     __tmp != __last.base(); ++__tmp)
779	  {
780	    _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
781				  _M_message(__gnu_debug::__msg_valid_range)
782				  ._M_iterator(__first, "first")
783				  ._M_iterator(__last, "last"));
784	    this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
785			    { return __it == __tmp; });
786	    _Base_const_local_iterator __local_tmp = _S_to_local(__tmp);
787	    this->_M_invalidate_local_if(
788			    [__local_tmp](_Base_const_local_iterator __it)
789			    { return __it == __local_tmp; });
790	  }
791	size_type __bucket_count = this->bucket_count();
792	_Base_iterator __next = _Base::erase(__first.base(), __last.base());
793	_M_check_rehashed(__bucket_count);
794	return iterator(__next, this);
795      }
796
797      _Base&
798      _M_base() noexcept       { return *this; }
799
800      const _Base&
801      _M_base() const noexcept { return *this; }
802
803    private:
804      void
805      _M_invalidate_locals()
806      {
807	_Base_local_iterator __local_end = _Base::end(0);
808	this->_M_invalidate_local_if(
809			[__local_end](_Base_const_local_iterator __it)
810			{ return __it != __local_end; });
811      }
812
813      void
814      _M_invalidate_all()
815      {
816	_Base_iterator __end = _Base::end();
817	this->_M_invalidate_if([__end](_Base_const_iterator __it)
818			{ return __it != __end; });
819	_M_invalidate_locals();
820      }
821
822      void
823      _M_check_rehashed(size_type __prev_count)
824      {
825	if (__prev_count != this->bucket_count())
826	  _M_invalidate_locals();
827      }
828
829      static _Base_local_iterator
830      _S_to_local(_Base_iterator __it)
831      {
832        // The returned local iterator will not be incremented so we don't
833	// need to compute __it's node bucket
834	return _Base_local_iterator(__it._M_cur, 0, 0);
835      }
836
837      static _Base_const_local_iterator
838      _S_to_local(_Base_const_iterator __it)
839      {
840        // The returned local iterator will not be incremented so we don't
841	// need to compute __it's node bucket
842	return _Base_const_local_iterator(__it._M_cur, 0, 0);
843      }
844    };
845
846  template<typename _Key, typename _Tp, typename _Hash,
847	   typename _Pred, typename _Alloc>
848    inline void
849    swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
850	 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
851    { __x.swap(__y); }
852
853  template<typename _Key, typename _Tp, typename _Hash,
854	   typename _Pred, typename _Alloc>
855    inline bool
856    operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
857	       const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
858    { return __x._M_equal(__y); }
859
860  template<typename _Key, typename _Tp, typename _Hash,
861	   typename _Pred, typename _Alloc>
862    inline bool
863    operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
864	       const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
865    { return !(__x == __y); }
866
867} // namespace __debug
868} // namespace std
869
870#endif // __GXX_EXPERIMENTAL_CXX0X__
871
872#endif
873