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