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