libstdc++
debug/unordered_set
Go to the documentation of this file.
00001 // Debugging unordered_set/unordered_multiset implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013
00004 // Free Software Foundation, Inc.
00005 //
00006 // This file is part of the GNU ISO C++ Library.  This library is free
00007 // software; you can redistribute it and/or modify it under the
00008 // terms of the GNU General Public License as published by the
00009 // Free Software Foundation; either version 3, or (at your option)
00010 // any later version.
00011 
00012 // This library is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 
00017 // Under Section 7 of GPL version 3, you are granted additional
00018 // permissions described in the GCC Runtime Library Exception, version
00019 // 3.1, as published by the Free Software Foundation.
00020 
00021 // You should have received a copy of the GNU General Public License and
00022 // a copy of the GCC Runtime Library Exception along with this program;
00023 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00024 // <http://www.gnu.org/licenses/>.
00025 
00026 /** @file debug/unordered_set
00027  *  This file is a GNU debug extension to the Standard C++ Library.
00028  */
00029 
00030 #ifndef _GLIBCXX_DEBUG_UNORDERED_SET
00031 #define _GLIBCXX_DEBUG_UNORDERED_SET 1
00032 
00033 #ifndef __GXX_EXPERIMENTAL_CXX0X__
00034 # include <bits/c++0x_warning.h>
00035 #else
00036 # include <unordered_set>
00037 
00038 #include <debug/safe_unordered_container.h>
00039 #include <debug/safe_iterator.h>
00040 #include <debug/safe_local_iterator.h>
00041 
00042 namespace std _GLIBCXX_VISIBILITY(default)
00043 {
00044 namespace __debug
00045 {
00046   /// Class std::unordered_set with safety/checking/debug instrumentation.
00047   template<typename _Value,
00048        typename _Hash = std::hash<_Value>,
00049        typename _Pred = std::equal_to<_Value>,
00050        typename _Alloc = std::allocator<_Value> >
00051     class unordered_set
00052     : public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc>,
00053       public __gnu_debug::_Safe_unordered_container<unordered_set<_Value, _Hash,
00054                                _Pred, _Alloc> >
00055     {
00056       typedef _GLIBCXX_STD_C::unordered_set<_Value, _Hash,
00057                         _Pred, _Alloc> _Base;
00058       typedef __gnu_debug::_Safe_unordered_container<unordered_set> _Safe_base;
00059       typedef typename _Base::const_iterator _Base_const_iterator;
00060       typedef typename _Base::iterator _Base_iterator;
00061       typedef typename _Base::const_local_iterator _Base_const_local_iterator;
00062       typedef typename _Base::local_iterator _Base_local_iterator;
00063 
00064     public:
00065       typedef typename _Base::size_type       size_type;
00066       typedef typename _Base::hasher          hasher;
00067       typedef typename _Base::key_equal       key_equal;
00068       typedef typename _Base::allocator_type  allocator_type;
00069 
00070       typedef typename _Base::key_type        key_type;
00071       typedef typename _Base::value_type      value_type;
00072 
00073       typedef __gnu_debug::_Safe_iterator<_Base_iterator,
00074                       unordered_set> iterator;
00075       typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
00076                       unordered_set> const_iterator;
00077       typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator,
00078                       unordered_set> local_iterator;
00079       typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator,
00080                       unordered_set> const_local_iterator;
00081 
00082       explicit
00083       unordered_set(size_type __n = 10,
00084             const hasher& __hf = hasher(),
00085             const key_equal& __eql = key_equal(),
00086             const allocator_type& __a = allocator_type())
00087       : _Base(__n, __hf, __eql, __a) { }
00088 
00089       template<typename _InputIterator>
00090         unordered_set(_InputIterator __first, _InputIterator __last, 
00091               size_type __n = 0,
00092               const hasher& __hf = hasher(), 
00093               const key_equal& __eql = key_equal(), 
00094               const allocator_type& __a = allocator_type())
00095     : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
00096                                      __last)),
00097         __gnu_debug::__base(__last), __n,
00098         __hf, __eql, __a) { }
00099 
00100       unordered_set(const unordered_set& __x) = default;
00101 
00102       unordered_set(const _Base& __x) 
00103       : _Base(__x) { }
00104 
00105       unordered_set(unordered_set&& __x) = default;
00106 
00107       unordered_set(initializer_list<value_type> __l,
00108             size_type __n = 0,
00109             const hasher& __hf = hasher(),
00110             const key_equal& __eql = key_equal(),
00111             const allocator_type& __a = allocator_type())
00112       : _Base(__l, __n, __hf, __eql, __a) { }
00113 
00114       ~unordered_set() noexcept { }
00115 
00116       unordered_set&
00117       operator=(const unordered_set& __x)
00118       {
00119     *static_cast<_Base*>(this) = __x;
00120     this->_M_invalidate_all();
00121     return *this;
00122       }
00123 
00124       unordered_set&
00125       operator=(unordered_set&& __x)
00126       {
00127     // NB: DR 1204.
00128     // NB: DR 675.
00129     clear();
00130     swap(__x);
00131     return *this;
00132       }
00133 
00134       unordered_set&
00135       operator=(initializer_list<value_type> __l)
00136       {
00137     this->clear();
00138     this->insert(__l);
00139     return *this;
00140       }
00141 
00142       void
00143       swap(unordered_set& __x)
00144       {
00145     _Base::swap(__x);
00146     _Safe_base::_M_swap(__x);
00147       }
00148 
00149       void
00150       clear() noexcept
00151       {
00152     _Base::clear();
00153     this->_M_invalidate_all();
00154       }
00155 
00156       iterator 
00157       begin() noexcept
00158       { return iterator(_Base::begin(), this); }
00159 
00160       const_iterator
00161       begin() const noexcept
00162       { return const_iterator(_Base::begin(), this); }
00163 
00164       iterator
00165       end() noexcept
00166       { return iterator(_Base::end(), this); }
00167 
00168       const_iterator
00169       end() const noexcept
00170       { return const_iterator(_Base::end(), this); }
00171 
00172       const_iterator
00173       cbegin() const noexcept
00174       { return const_iterator(_Base::begin(), this); }
00175 
00176       const_iterator
00177       cend() const noexcept
00178       { return const_iterator(_Base::end(), this); }
00179 
00180       // local versions
00181       local_iterator
00182       begin(size_type __b)
00183       { return local_iterator(_Base::begin(__b), __b, this); }
00184 
00185       local_iterator
00186       end(size_type __b)
00187       { return local_iterator(_Base::end(__b), __b, this); }
00188 
00189       const_local_iterator
00190       begin(size_type __b) const
00191       { return const_local_iterator(_Base::begin(__b), __b, this); }
00192 
00193       const_local_iterator
00194       end(size_type __b) const
00195       { return const_local_iterator(_Base::end(__b), __b, this); }
00196 
00197       const_local_iterator
00198       cbegin(size_type __b) const
00199       { return const_local_iterator(_Base::cbegin(__b), __b, this); }
00200 
00201       const_local_iterator
00202       cend(size_type __b) const
00203       { return const_local_iterator(_Base::cend(__b), __b, this); }
00204 
00205       template<typename... _Args>
00206     std::pair<iterator, bool>
00207     emplace(_Args&&... __args)
00208     {
00209       size_type __bucket_count = this->bucket_count();
00210       std::pair<_Base_iterator, bool> __res
00211         = _Base::emplace(std::forward<_Args>(__args)...);
00212       _M_check_rehashed(__bucket_count);
00213       return std::make_pair(iterator(__res.first, this), __res.second);
00214     }
00215 
00216       template<typename... _Args>
00217     iterator
00218     emplace_hint(const_iterator __hint, _Args&&... __args)
00219     {
00220       __glibcxx_check_insert(__hint);
00221       size_type __bucket_count = this->bucket_count();
00222       _Base_iterator __it = _Base::emplace_hint(__hint.base(),
00223                     std::forward<_Args>(__args)...);
00224       _M_check_rehashed(__bucket_count);
00225       return iterator(__it, this);
00226     }
00227 
00228       std::pair<iterator, bool>
00229       insert(const value_type& __obj)
00230       {
00231     size_type __bucket_count = this->bucket_count();
00232     typedef std::pair<_Base_iterator, bool> __pair_type;
00233       __pair_type __res = _Base::insert(__obj);
00234     _M_check_rehashed(__bucket_count);
00235     return std::make_pair(iterator(__res.first, this), __res.second);
00236       }
00237 
00238       iterator
00239       insert(const_iterator __hint, const value_type& __obj)
00240       {
00241     __glibcxx_check_insert(__hint);
00242     size_type __bucket_count = this->bucket_count();
00243     _Base_iterator __it = _Base::insert(__hint.base(), __obj);
00244     _M_check_rehashed(__bucket_count);
00245     return iterator(__it, this);
00246       }
00247 
00248       std::pair<iterator, bool>
00249       insert(value_type&& __obj)
00250       {
00251     size_type __bucket_count = this->bucket_count();
00252     typedef std::pair<typename _Base::iterator, bool> __pair_type;
00253       __pair_type __res = _Base::insert(std::move(__obj));
00254     _M_check_rehashed(__bucket_count);
00255     return std::make_pair(iterator(__res.first, this), __res.second);
00256       }
00257 
00258       iterator
00259       insert(const_iterator __hint, value_type&& __obj)
00260       {
00261     __glibcxx_check_insert(__hint);
00262     size_type __bucket_count = this->bucket_count();
00263     _Base_iterator __it = _Base::insert(__hint.base(), std::move(__obj));
00264     _M_check_rehashed(__bucket_count);
00265     return iterator(__it, this);
00266       }
00267 
00268       void
00269       insert(std::initializer_list<value_type> __l)
00270       {
00271     size_type __bucket_count = this->bucket_count();
00272     _Base::insert(__l);
00273     _M_check_rehashed(__bucket_count);
00274       }
00275 
00276       template<typename _InputIterator>
00277     void
00278     insert(_InputIterator __first, _InputIterator __last)
00279     {
00280       __glibcxx_check_valid_range(__first, __last);
00281       size_type __bucket_count = this->bucket_count();
00282       _Base::insert(__gnu_debug::__base(__first),
00283             __gnu_debug::__base(__last));
00284       _M_check_rehashed(__bucket_count);
00285     }
00286 
00287       iterator
00288       find(const key_type& __key)
00289       { return iterator(_Base::find(__key), this); }
00290 
00291       const_iterator
00292       find(const key_type& __key) const
00293       { return const_iterator(_Base::find(__key), this); }
00294 
00295       std::pair<iterator, iterator>
00296       equal_range(const key_type& __key)
00297       {
00298     typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
00299     __pair_type __res = _Base::equal_range(__key);
00300     return std::make_pair(iterator(__res.first, this),
00301                   iterator(__res.second, this));
00302       }
00303 
00304       std::pair<const_iterator, const_iterator>
00305       equal_range(const key_type& __key) const
00306       {
00307     std::pair<_Base_const_iterator, _Base_const_iterator>
00308       __res = _Base::equal_range(__key);
00309     return std::make_pair(const_iterator(__res.first, this),
00310                   const_iterator(__res.second, this));
00311       }
00312 
00313       size_type
00314       erase(const key_type& __key)
00315       {
00316     size_type __ret(0);
00317     _Base_iterator __victim(_Base::find(__key));
00318     if (__victim != _Base::end())
00319       {
00320         this->_M_invalidate_if(
00321                 [__victim](_Base_const_iterator __it)
00322                 { return __it == __victim; });
00323         _Base_local_iterator __local_victim = _S_to_local(__victim);
00324         this->_M_invalidate_local_if(
00325                 [__local_victim](_Base_const_local_iterator __it)
00326                 { return __it == __local_victim; });
00327         size_type __bucket_count = this->bucket_count();
00328         _Base::erase(__victim);
00329         _M_check_rehashed(__bucket_count);
00330         __ret = 1;
00331       }
00332     return __ret;
00333       }
00334 
00335       iterator
00336       erase(const_iterator __it)
00337       {
00338     __glibcxx_check_erase(__it);
00339     _Base_const_iterator __victim = __it.base();
00340     this->_M_invalidate_if(
00341             [__victim](_Base_const_iterator __it)
00342             { return __it == __victim; });
00343     _Base_const_local_iterator __local_victim = _S_to_local(__victim);
00344     this->_M_invalidate_local_if(
00345             [__local_victim](_Base_const_local_iterator __it)
00346             { return __it == __local_victim; });
00347     size_type __bucket_count = this->bucket_count();
00348     _Base_iterator __next = _Base::erase(__it.base());
00349     _M_check_rehashed(__bucket_count);
00350     return iterator(__next, this);
00351       }
00352 
00353       iterator
00354       erase(iterator __it)
00355       { return erase(const_iterator(__it)); }
00356 
00357       iterator
00358       erase(const_iterator __first, const_iterator __last)
00359       {
00360     __glibcxx_check_erase_range(__first, __last);
00361     for (_Base_const_iterator __tmp = __first.base();
00362          __tmp != __last.base(); ++__tmp)
00363       {
00364         _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
00365                   _M_message(__gnu_debug::__msg_valid_range)
00366                   ._M_iterator(__first, "first")
00367                   ._M_iterator(__last, "last"));
00368         this->_M_invalidate_if(
00369                 [__tmp](_Base_const_iterator __it)
00370                 { return __it == __tmp; });
00371         _Base_const_local_iterator __local_tmp = _S_to_local(__tmp);
00372         this->_M_invalidate_local_if(
00373                 [__local_tmp](_Base_const_local_iterator __it)
00374                 { return __it == __local_tmp; });
00375       }
00376     size_type __bucket_count = this->bucket_count();
00377     _Base_iterator __next = _Base::erase(__first.base(),
00378                          __last.base());
00379     _M_check_rehashed(__bucket_count);
00380     return iterator(__next, this);
00381       }
00382 
00383       _Base&
00384       _M_base() noexcept       { return *this; }
00385 
00386       const _Base&
00387       _M_base() const noexcept { return *this; }
00388 
00389     private:
00390       void
00391       _M_invalidate_locals()
00392       {
00393     _Base_local_iterator __local_end = _Base::end(0);
00394     this->_M_invalidate_local_if(
00395             [__local_end](_Base_const_local_iterator __it)
00396             { return __it != __local_end; });
00397       }
00398 
00399       void
00400       _M_invalidate_all()
00401       {
00402     _Base_iterator __end = _Base::end();
00403     this->_M_invalidate_if(
00404             [__end](_Base_const_iterator __it)
00405             { return __it != __end; });
00406     _M_invalidate_locals();
00407       }
00408 
00409       void
00410       _M_check_rehashed(size_type __prev_count)
00411       {
00412     if (__prev_count != this->bucket_count())
00413       _M_invalidate_locals();
00414       }
00415 
00416       static _Base_local_iterator
00417       _S_to_local(_Base_iterator __it)
00418       {
00419         // The returned local iterator will not be incremented so we don't
00420     // need to compute __it's node bucket
00421     return _Base_local_iterator(__it._M_cur, 0, 0);
00422       }
00423 
00424       static _Base_const_local_iterator
00425       _S_to_local(_Base_const_iterator __it)
00426       {
00427         // The returned local iterator will not be incremented so we don't
00428     // need to compute __it's node bucket
00429     return _Base_const_local_iterator(__it._M_cur, 0, 0);
00430       }
00431     };
00432 
00433   template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
00434     inline void
00435     swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
00436      unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
00437     { __x.swap(__y); }
00438 
00439   template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
00440     inline bool
00441     operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
00442            const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
00443     { return __x._M_equal(__y); }
00444 
00445   template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
00446     inline bool
00447     operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
00448            const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
00449     { return !(__x == __y); }
00450 
00451 
00452   /// Class std::unordered_multiset with safety/checking/debug instrumentation.
00453   template<typename _Value,
00454        typename _Hash = std::hash<_Value>,
00455        typename _Pred = std::equal_to<_Value>,
00456        typename _Alloc = std::allocator<_Value> >
00457     class unordered_multiset
00458     : public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc>,
00459       public __gnu_debug::_Safe_unordered_container<
00460         unordered_multiset<_Value, _Hash, _Pred, _Alloc> >
00461     {
00462       typedef _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash,
00463                          _Pred, _Alloc> _Base;
00464       typedef __gnu_debug::_Safe_unordered_container<unordered_multiset>
00465         _Safe_base;
00466       typedef typename _Base::const_iterator _Base_const_iterator;
00467       typedef typename _Base::iterator _Base_iterator;
00468       typedef typename _Base::const_local_iterator _Base_const_local_iterator;
00469       typedef typename _Base::local_iterator _Base_local_iterator;
00470 
00471     public:
00472       typedef typename _Base::size_type       size_type;
00473       typedef typename _Base::hasher          hasher;
00474       typedef typename _Base::key_equal       key_equal;
00475       typedef typename _Base::allocator_type  allocator_type;
00476 
00477       typedef typename _Base::key_type        key_type;
00478       typedef typename _Base::value_type      value_type;
00479 
00480       typedef __gnu_debug::_Safe_iterator<_Base_iterator,
00481                       unordered_multiset> iterator;
00482       typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
00483                       unordered_multiset> const_iterator;
00484       typedef __gnu_debug::_Safe_local_iterator<
00485     _Base_local_iterator, unordered_multiset> local_iterator;
00486       typedef __gnu_debug::_Safe_local_iterator<
00487     _Base_const_local_iterator, unordered_multiset> const_local_iterator;
00488 
00489       explicit
00490       unordered_multiset(size_type __n = 10,
00491              const hasher& __hf = hasher(),
00492              const key_equal& __eql = key_equal(),
00493              const allocator_type& __a = allocator_type())
00494       : _Base(__n, __hf, __eql, __a) { }
00495 
00496       template<typename _InputIterator>
00497         unordered_multiset(_InputIterator __first, _InputIterator __last, 
00498                size_type __n = 0,
00499                const hasher& __hf = hasher(), 
00500                const key_equal& __eql = key_equal(), 
00501                const allocator_type& __a = allocator_type())
00502     : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
00503                                      __last)),
00504         __gnu_debug::__base(__last), __n,
00505         __hf, __eql, __a) { }
00506 
00507       unordered_multiset(const unordered_multiset& __x) = default;
00508 
00509       unordered_multiset(const _Base& __x) 
00510       : _Base(__x) { }
00511 
00512       unordered_multiset(unordered_multiset&& __x) = default;
00513 
00514       unordered_multiset(initializer_list<value_type> __l,
00515              size_type __n = 0,
00516              const hasher& __hf = hasher(),
00517              const key_equal& __eql = key_equal(),
00518              const allocator_type& __a = allocator_type())
00519       : _Base(__l, __n, __hf, __eql, __a) { }
00520 
00521       ~unordered_multiset() noexcept { }
00522 
00523       unordered_multiset&
00524       operator=(const unordered_multiset& __x)
00525       {
00526     *static_cast<_Base*>(this) = __x;
00527     this->_M_invalidate_all();
00528     return *this;
00529       }
00530 
00531       unordered_multiset&
00532       operator=(unordered_multiset&& __x)
00533       {
00534     // NB: DR 1204.
00535         // NB: DR 675.
00536     clear();
00537     swap(__x);
00538     return *this;
00539       }
00540 
00541       unordered_multiset&
00542       operator=(initializer_list<value_type> __l)
00543       {
00544     this->clear();
00545     this->insert(__l);
00546     return *this;
00547       }
00548 
00549       void
00550       swap(unordered_multiset& __x)
00551       {
00552     _Base::swap(__x);
00553     _Safe_base::_M_swap(__x);
00554       }
00555 
00556       void
00557       clear() noexcept
00558       {
00559     _Base::clear();
00560     this->_M_invalidate_all();
00561       }
00562 
00563       iterator
00564       begin() noexcept
00565       { return iterator(_Base::begin(), this); }
00566 
00567       const_iterator
00568       begin() const noexcept
00569       { return const_iterator(_Base::begin(), this); }
00570 
00571       iterator
00572       end() noexcept
00573       { return iterator(_Base::end(), this); }
00574 
00575       const_iterator
00576       end() const noexcept
00577       { return const_iterator(_Base::end(), this); }
00578 
00579       const_iterator
00580       cbegin() const noexcept
00581       { return const_iterator(_Base::begin(), this); }
00582 
00583       const_iterator
00584       cend() const noexcept
00585       { return const_iterator(_Base::end(), this); }
00586 
00587       // local versions
00588       local_iterator
00589       begin(size_type __b)
00590       { return local_iterator(_Base::begin(__b), __b, this); }
00591 
00592       local_iterator
00593       end(size_type __b)
00594       { return local_iterator(_Base::end(__b), __b, this); }
00595 
00596       const_local_iterator
00597       begin(size_type __b) const
00598       { return const_local_iterator(_Base::begin(__b), __b, this); }
00599 
00600       const_local_iterator
00601       end(size_type __b) const
00602       { return const_local_iterator(_Base::end(__b), __b, this); }
00603 
00604       const_local_iterator
00605       cbegin(size_type __b) const
00606       { return const_local_iterator(_Base::cbegin(__b), __b, this); }
00607 
00608       const_local_iterator
00609       cend(size_type __b) const
00610       { return const_local_iterator(_Base::cend(__b), __b, this); }
00611 
00612       template<typename... _Args>
00613     iterator
00614     emplace(_Args&&... __args)
00615     {
00616       size_type __bucket_count = this->bucket_count();
00617       _Base_iterator __it
00618         = _Base::emplace(std::forward<_Args>(__args)...);
00619       _M_check_rehashed(__bucket_count);
00620       return iterator(__it, this);
00621     }
00622 
00623       template<typename... _Args>
00624     iterator
00625     emplace_hint(const_iterator __hint, _Args&&... __args)
00626     {
00627       __glibcxx_check_insert(__hint);
00628       size_type __bucket_count = this->bucket_count();
00629       _Base_iterator __it = _Base::emplace_hint(__hint.base(),
00630                     std::forward<_Args>(__args)...);
00631       _M_check_rehashed(__bucket_count);
00632       return iterator(__it, this);
00633     }
00634 
00635       iterator
00636       insert(const value_type& __obj)
00637       {
00638     size_type __bucket_count = this->bucket_count();
00639     _Base_iterator __it = _Base::insert(__obj);
00640     _M_check_rehashed(__bucket_count);
00641     return iterator(__it, this);
00642       }
00643 
00644       iterator
00645       insert(const_iterator __hint, const value_type& __obj)
00646       {
00647     __glibcxx_check_insert(__hint);
00648     size_type __bucket_count = this->bucket_count();
00649     _Base_iterator __it = _Base::insert(__hint.base(), __obj); 
00650     _M_check_rehashed(__bucket_count);
00651     return iterator(__it, this);
00652       }
00653 
00654       iterator
00655       insert(value_type&& __obj)
00656       {
00657     size_type __bucket_count = this->bucket_count();
00658     _Base_iterator __it = _Base::insert(std::move(__obj)); 
00659     _M_check_rehashed(__bucket_count);
00660     return iterator(__it, this);
00661       }
00662 
00663       iterator
00664       insert(const_iterator __hint, value_type&& __obj)
00665       {
00666     __glibcxx_check_insert(__hint);
00667     size_type __bucket_count = this->bucket_count();
00668     _Base_iterator __it = _Base::insert(__hint.base(), std::move(__obj)); 
00669     _M_check_rehashed(__bucket_count);
00670     return iterator(__it, this);
00671       }
00672 
00673       void
00674       insert(std::initializer_list<value_type> __l)
00675       {
00676     size_type __bucket_count = this->bucket_count();
00677     _Base::insert(__l);
00678     _M_check_rehashed(__bucket_count);
00679       }
00680 
00681       template<typename _InputIterator>
00682     void
00683     insert(_InputIterator __first, _InputIterator __last)
00684     {
00685       __glibcxx_check_valid_range(__first, __last);
00686       size_type __bucket_count = this->bucket_count();
00687       _Base::insert(__gnu_debug::__base(__first),
00688             __gnu_debug::__base(__last));
00689       _M_check_rehashed(__bucket_count);
00690     }
00691 
00692       iterator
00693       find(const key_type& __key)
00694       { return iterator(_Base::find(__key), this); }
00695 
00696       const_iterator
00697       find(const key_type& __key) const
00698       { return const_iterator(_Base::find(__key), this); }
00699 
00700       std::pair<iterator, iterator>
00701       equal_range(const key_type& __key)
00702       {
00703     typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
00704     __pair_type __res = _Base::equal_range(__key);
00705     return std::make_pair(iterator(__res.first, this),
00706                   iterator(__res.second, this));
00707       }
00708 
00709       std::pair<const_iterator, const_iterator>
00710       equal_range(const key_type& __key) const
00711       {
00712     std::pair<_Base_const_iterator, _Base_const_iterator>
00713       __res = _Base::equal_range(__key);
00714     return std::make_pair(const_iterator(__res.first, this),
00715                   const_iterator(__res.second, this));
00716       }
00717 
00718       size_type
00719       erase(const key_type& __key)
00720       {
00721     size_type __ret(0);
00722     std::pair<_Base_iterator, _Base_iterator> __pair =
00723       _Base::equal_range(__key);
00724     for (_Base_iterator __victim = __pair.first; __victim != __pair.second;)
00725       {
00726         this->_M_invalidate_if([__victim](_Base_const_iterator __it)
00727                 { return __it == __victim; });
00728         _Base_local_iterator __local_victim = _S_to_local(__victim);
00729         this->_M_invalidate_local_if(
00730                 [__local_victim](_Base_const_local_iterator __it)
00731                 { return __it == __local_victim; });
00732         _Base::erase(__victim++);
00733         ++__ret;
00734       }
00735     return __ret;
00736       }
00737 
00738       iterator
00739       erase(const_iterator __it)
00740       {
00741     __glibcxx_check_erase(__it);
00742     _Base_const_iterator __victim = __it.base();
00743     this->_M_invalidate_if([__victim](_Base_const_iterator __it)
00744             { return __it == __victim; });
00745     _Base_const_local_iterator __local_victim = _S_to_local(__victim);
00746     this->_M_invalidate_local_if(
00747             [__local_victim](_Base_const_local_iterator __it)
00748             { return __it == __local_victim; });
00749     return iterator(_Base::erase(__it.base()), this);
00750       }
00751 
00752       iterator
00753       erase(iterator __it)
00754       { return erase(const_iterator(__it)); }
00755 
00756       iterator
00757       erase(const_iterator __first, const_iterator __last)
00758       {
00759     __glibcxx_check_erase_range(__first, __last);
00760     for (_Base_const_iterator __tmp = __first.base();
00761          __tmp != __last.base(); ++__tmp)
00762       {
00763         _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
00764                   _M_message(__gnu_debug::__msg_valid_range)
00765                   ._M_iterator(__first, "first")
00766                   ._M_iterator(__last, "last"));
00767         this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
00768                 { return __it == __tmp; });
00769         _Base_const_local_iterator __local_tmp = _S_to_local(__tmp);
00770         this->_M_invalidate_local_if(
00771                 [__local_tmp](_Base_const_local_iterator __it)
00772                 { return __it == __local_tmp; });
00773       }
00774     return iterator(_Base::erase(__first.base(),
00775                      __last.base()), this);
00776       }
00777 
00778       _Base&
00779       _M_base() noexcept       { return *this; }
00780 
00781       const _Base&
00782       _M_base() const noexcept { return *this; }
00783 
00784     private:
00785       void
00786       _M_invalidate_locals()
00787       {
00788     _Base_local_iterator __local_end = _Base::end(0);
00789     this->_M_invalidate_local_if(
00790             [__local_end](_Base_const_local_iterator __it)
00791             { return __it != __local_end; });
00792       }
00793 
00794       void
00795       _M_invalidate_all()
00796       {
00797     _Base_iterator __end = _Base::end();
00798     this->_M_invalidate_if([__end](_Base_const_iterator __it)
00799             { return __it != __end; });
00800     _M_invalidate_locals();
00801       }
00802 
00803       void
00804       _M_check_rehashed(size_type __prev_count)
00805       {
00806     if (__prev_count != this->bucket_count())
00807       _M_invalidate_locals();
00808       }
00809 
00810       static _Base_local_iterator
00811       _S_to_local(_Base_iterator __it)
00812       {
00813         // The returned local iterator will not be incremented so we don't
00814     // need to compute __it's node bucket
00815     return _Base_local_iterator(__it._M_cur, 0, 0);
00816       }
00817 
00818       static _Base_const_local_iterator
00819       _S_to_local(_Base_const_iterator __it)
00820       {
00821         // The returned local iterator will not be incremented so we don't
00822     // need to compute __it's node bucket
00823     return _Base_const_local_iterator(__it._M_cur, 0, 0);
00824       }
00825     };
00826 
00827   template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
00828     inline void
00829     swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
00830      unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
00831     { __x.swap(__y); }
00832 
00833   template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
00834     inline bool
00835     operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
00836            const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
00837     { return __x._M_equal(__y); }
00838 
00839   template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
00840     inline bool
00841     operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
00842            const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
00843     { return !(__x == __y); }
00844 
00845 } // namespace __debug
00846 } // namespace std
00847 
00848 #endif // __GXX_EXPERIMENTAL_CXX0X__
00849 
00850 #endif