libstdc++

debug/unordered_map

Go to the documentation of this file.
00001 // Debugging unordered_map/unordered_multimap 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_map
00027  *  This file is a GNU debug extension to the Standard C++ Library.
00028  */
00029 
00030 #ifndef _GLIBCXX_DEBUG_UNORDERED_MAP
00031 #define _GLIBCXX_DEBUG_UNORDERED_MAP 1
00032 
00033 #ifndef __GXX_EXPERIMENTAL_CXX0X__
00034 # include <bits/c++0x_warning.h>
00035 #else
00036 # include <unordered_map>
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_map with safety/checking/debug instrumentation.
00047   template<typename _Key, typename _Tp,
00048        typename _Hash = std::hash<_Key>,
00049        typename _Pred = std::equal_to<_Key>,
00050        typename _Alloc = std::allocator<_Key> >
00051     class unordered_map
00052     : public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>,
00053       public __gnu_debug::_Safe_unordered_container<unordered_map<_Key, _Tp,
00054                             _Hash, _Pred, _Alloc> >
00055     {
00056       typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash,
00057                         _Pred, _Alloc> _Base;
00058       typedef __gnu_debug::_Safe_unordered_container<unordered_map> _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_map> iterator;
00075       typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
00076                       unordered_map> const_iterator;
00077       typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator,
00078                       unordered_map> local_iterator;
00079       typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator,
00080                       unordered_map> const_local_iterator;
00081 
00082       explicit
00083       unordered_map(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_map(_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_map(const unordered_map& __x) = default;
00101 
00102       unordered_map(const _Base& __x)
00103       : _Base(__x) { }
00104 
00105       unordered_map(unordered_map&& __x) = default;
00106 
00107       unordered_map(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_map() noexcept { }
00115 
00116       unordered_map&
00117       operator=(const unordered_map& __x)
00118       {
00119     *static_cast<_Base*>(this) = __x;
00120     this->_M_invalidate_all();
00121     return *this;
00122       }
00123 
00124       unordered_map&
00125       operator=(unordered_map&& __x)
00126       {
00127     // NB: DR 1204.
00128     // NB: DR 675.
00129     clear();
00130     swap(__x);
00131     return *this;
00132       }
00133 
00134       unordered_map&
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_map& __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     std::pair<_Base_iterator, bool> __res = _Base::insert(__obj);
00233     _M_check_rehashed(__bucket_count);
00234     return std::make_pair(iterator(__res.first, this), __res.second);
00235       }
00236 
00237       iterator
00238       insert(const_iterator __hint, const value_type& __obj)
00239       {
00240     __glibcxx_check_insert(__hint);
00241     size_type __bucket_count = this->bucket_count();
00242     _Base_iterator __it = _Base::insert(__hint.base(), __obj); 
00243     _M_check_rehashed(__bucket_count);
00244     return iterator(__it, this);
00245       }
00246 
00247       template<typename _Pair, typename = typename
00248            std::enable_if<std::is_constructible<value_type,
00249                             _Pair&&>::value>::type>
00250     std::pair<iterator, bool>
00251     insert(_Pair&& __obj)
00252     {
00253       size_type __bucket_count = this->bucket_count();
00254       std::pair<_Base_iterator, bool> __res =
00255         _Base::insert(std::forward<_Pair>(__obj));
00256       _M_check_rehashed(__bucket_count);
00257       return std::make_pair(iterator(__res.first, this), __res.second);
00258     }
00259 
00260       template<typename _Pair, typename = typename
00261            std::enable_if<std::is_constructible<value_type,
00262                             _Pair&&>::value>::type>
00263     iterator
00264     insert(const_iterator __hint, _Pair&& __obj)
00265     {
00266       __glibcxx_check_insert(__hint);
00267       size_type __bucket_count = this->bucket_count();
00268       _Base_iterator __it =
00269         _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
00270       _M_check_rehashed(__bucket_count);
00271       return iterator(__it, this);
00272     }
00273 
00274       void
00275       insert(std::initializer_list<value_type> __l)
00276       {
00277     size_type __bucket_count = this->bucket_count();
00278     _Base::insert(__l);
00279     _M_check_rehashed(__bucket_count);
00280       }
00281 
00282       template<typename _InputIterator>
00283     void
00284     insert(_InputIterator __first, _InputIterator __last)
00285     {
00286       __glibcxx_check_valid_range(__first, __last);
00287       size_type __bucket_count = this->bucket_count();
00288       _Base::insert(__gnu_debug::__base(__first),
00289             __gnu_debug::__base(__last));
00290       _M_check_rehashed(__bucket_count);
00291     }
00292 
00293       iterator
00294       find(const key_type& __key)
00295       { return iterator(_Base::find(__key), this); }
00296 
00297       const_iterator
00298       find(const key_type& __key) const
00299       { return const_iterator(_Base::find(__key), this); }
00300 
00301       std::pair<iterator, iterator>
00302       equal_range(const key_type& __key)
00303       {
00304     std::pair<_Base_iterator, _Base_iterator> __res =
00305       _Base::equal_range(__key);
00306     return std::make_pair(iterator(__res.first, this),
00307                   iterator(__res.second, this));
00308       }
00309 
00310       std::pair<const_iterator, const_iterator>
00311       equal_range(const key_type& __key) const
00312       {
00313     std::pair<_Base_const_iterator, _Base_const_iterator> __res =
00314       _Base::equal_range(__key);
00315     return std::make_pair(const_iterator(__res.first, this),
00316                   const_iterator(__res.second, this));
00317       }
00318 
00319       size_type
00320       erase(const key_type& __key)
00321       {
00322     size_type __ret(0);
00323     _Base_iterator __victim(_Base::find(__key));
00324     if (__victim != _Base::end())
00325       {
00326         this->_M_invalidate_if([__victim](_Base_const_iterator __it)
00327                 { return __it == __victim; });
00328         _Base_local_iterator __local_victim = _S_to_local(__victim);
00329         this->_M_invalidate_local_if(
00330                 [__local_victim](_Base_const_local_iterator __it)
00331                 { return __it == __local_victim; });
00332         size_type __bucket_count = this->bucket_count();
00333         _Base::erase(__victim);
00334         _M_check_rehashed(__bucket_count);
00335         __ret = 1;
00336       }
00337     return __ret;
00338       }
00339 
00340       iterator
00341       erase(const_iterator __it)
00342       {
00343     __glibcxx_check_erase(__it);
00344     _Base_const_iterator __victim = __it.base();
00345     this->_M_invalidate_if([__victim](_Base_const_iterator __it)
00346             { return __it == __victim; });
00347     _Base_const_local_iterator __local_victim = _S_to_local(__victim);
00348     this->_M_invalidate_local_if(
00349             [__local_victim](_Base_const_local_iterator __it)
00350             { return __it == __local_victim; });
00351     size_type __bucket_count = this->bucket_count();
00352     _Base_iterator __next = _Base::erase(__it.base()); 
00353     _M_check_rehashed(__bucket_count);
00354     return iterator(__next, this);
00355       }
00356 
00357       iterator
00358       erase(iterator __it)
00359       { return erase(const_iterator(__it)); }
00360 
00361       iterator
00362       erase(const_iterator __first, const_iterator __last)
00363       {
00364     __glibcxx_check_erase_range(__first, __last);
00365     for (_Base_const_iterator __tmp = __first.base();
00366          __tmp != __last.base(); ++__tmp)
00367       {
00368         _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
00369                   _M_message(__gnu_debug::__msg_valid_range)
00370                   ._M_iterator(__first, "first")
00371                   ._M_iterator(__last, "last"));
00372         this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
00373                 { return __it == __tmp; });
00374         _Base_const_local_iterator __local_tmp = _S_to_local(__tmp);
00375         this->_M_invalidate_local_if(
00376                 [__local_tmp](_Base_const_local_iterator __it)
00377                 { return __it == __local_tmp; });
00378       }
00379     size_type __bucket_count = this->bucket_count();
00380     _Base_iterator __next = _Base::erase(__first.base(), __last.base());
00381     _M_check_rehashed(__bucket_count);
00382     return iterator(__next, this);
00383       }
00384 
00385       _Base&
00386       _M_base() noexcept       { return *this; }
00387 
00388       const _Base&
00389       _M_base() const noexcept { return *this; }
00390 
00391     private:
00392       void
00393       _M_invalidate_locals()
00394       {
00395     _Base_local_iterator __local_end = _Base::end(0);
00396     this->_M_invalidate_local_if(
00397             [__local_end](_Base_const_local_iterator __it)
00398             { return __it != __local_end; });
00399       }
00400 
00401       void
00402       _M_invalidate_all()
00403       {
00404     _Base_iterator __end = _Base::end();
00405     this->_M_invalidate_if([__end](_Base_const_iterator __it)
00406             { return __it != __end; });
00407     _M_invalidate_locals();
00408       }
00409 
00410       void
00411       _M_check_rehashed(size_type __prev_count)
00412       {
00413     if (__prev_count != this->bucket_count())
00414       _M_invalidate_locals();
00415       }
00416 
00417       static _Base_local_iterator
00418       _S_to_local(_Base_iterator __it)
00419       {
00420         // The returned local iterator will not be incremented so we don't
00421     // need to compute __it's node bucket
00422     return _Base_local_iterator(__it._M_cur, 0, 0);
00423       }
00424 
00425       static _Base_const_local_iterator
00426       _S_to_local(_Base_const_iterator __it)
00427       {
00428         // The returned local iterator will not be incremented so we don't
00429     // need to compute __it's node bucket
00430     return _Base_const_local_iterator(__it._M_cur, 0, 0);
00431       }
00432     };
00433 
00434   template<typename _Key, typename _Tp, typename _Hash,
00435        typename _Pred, typename _Alloc>
00436     inline void
00437     swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
00438      unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
00439     { __x.swap(__y); }
00440 
00441   template<typename _Key, typename _Tp, typename _Hash,
00442        typename _Pred, typename _Alloc>
00443     inline bool
00444     operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
00445            const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
00446     { return __x._M_equal(__y); }
00447 
00448   template<typename _Key, typename _Tp, typename _Hash,
00449        typename _Pred, typename _Alloc>
00450     inline bool
00451     operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
00452            const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
00453     { return !(__x == __y); }
00454 
00455 
00456   /// Class std::unordered_multimap with safety/checking/debug instrumentation.
00457   template<typename _Key, typename _Tp,
00458        typename _Hash = std::hash<_Key>,
00459        typename _Pred = std::equal_to<_Key>,
00460        typename _Alloc = std::allocator<_Key> >
00461     class unordered_multimap
00462     : public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
00463                         _Pred, _Alloc>,
00464       public __gnu_debug::_Safe_unordered_container<unordered_multimap<_Key,
00465                         _Tp, _Hash, _Pred, _Alloc> >
00466     {
00467       typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
00468                          _Pred, _Alloc> _Base;
00469       typedef __gnu_debug::_Safe_unordered_container<unordered_multimap>
00470     _Safe_base;
00471       typedef typename _Base::const_iterator _Base_const_iterator;
00472       typedef typename _Base::iterator _Base_iterator;
00473       typedef typename _Base::const_local_iterator _Base_const_local_iterator;
00474       typedef typename _Base::local_iterator _Base_local_iterator;
00475 
00476     public:
00477       typedef typename _Base::size_type       size_type;
00478       typedef typename _Base::hasher          hasher;
00479       typedef typename _Base::key_equal       key_equal;
00480       typedef typename _Base::allocator_type  allocator_type;
00481 
00482       typedef typename _Base::key_type        key_type;
00483       typedef typename _Base::value_type      value_type;
00484 
00485       typedef __gnu_debug::_Safe_iterator<_Base_iterator,
00486                       unordered_multimap> iterator;
00487       typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
00488                       unordered_multimap> const_iterator;
00489       typedef __gnu_debug::_Safe_local_iterator<
00490     _Base_local_iterator, unordered_multimap> local_iterator;
00491       typedef __gnu_debug::_Safe_local_iterator<
00492     _Base_const_local_iterator, unordered_multimap> const_local_iterator;
00493 
00494       explicit
00495       unordered_multimap(size_type __n = 10,
00496              const hasher& __hf = hasher(),
00497              const key_equal& __eql = key_equal(),
00498              const allocator_type& __a = allocator_type())
00499       : _Base(__n, __hf, __eql, __a) { }
00500 
00501       template<typename _InputIterator>
00502     unordered_multimap(_InputIterator __first, _InputIterator __last, 
00503                size_type __n = 0,
00504                const hasher& __hf = hasher(), 
00505                const key_equal& __eql = key_equal(), 
00506                const allocator_type& __a = allocator_type())
00507     : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
00508                                      __last)),
00509         __gnu_debug::__base(__last), __n,
00510         __hf, __eql, __a) { }
00511 
00512       unordered_multimap(const unordered_multimap& __x) = default;
00513 
00514       unordered_multimap(const _Base& __x) 
00515       : _Base(__x) { }
00516 
00517       unordered_multimap(unordered_multimap&& __x) = default;
00518 
00519       unordered_multimap(initializer_list<value_type> __l,
00520              size_type __n = 0,
00521              const hasher& __hf = hasher(),
00522              const key_equal& __eql = key_equal(),
00523              const allocator_type& __a = allocator_type())
00524       : _Base(__l, __n, __hf, __eql, __a) { }
00525 
00526       ~unordered_multimap() noexcept { }
00527 
00528       unordered_multimap&
00529       operator=(const unordered_multimap& __x)
00530       {
00531     *static_cast<_Base*>(this) = __x;
00532     this->_M_invalidate_all();
00533     return *this;
00534       }
00535 
00536       unordered_multimap&
00537       operator=(unordered_multimap&& __x)
00538       {
00539     // NB: DR 1204.
00540     // NB: DR 675.
00541     clear();
00542     swap(__x);
00543     return *this;
00544       }
00545 
00546       unordered_multimap&
00547       operator=(initializer_list<value_type> __l)
00548       {
00549     this->clear();
00550     this->insert(__l);
00551     return *this;
00552       }
00553 
00554       void
00555       swap(unordered_multimap& __x)
00556       {
00557     _Base::swap(__x);
00558     _Safe_base::_M_swap(__x);
00559       }
00560 
00561       void
00562       clear() noexcept
00563       {
00564     _Base::clear();
00565     this->_M_invalidate_all();
00566       }
00567 
00568       iterator 
00569       begin() noexcept
00570       { return iterator(_Base::begin(), this); }
00571 
00572       const_iterator
00573       begin() const noexcept
00574       { return const_iterator(_Base::begin(), this); }
00575 
00576       iterator
00577       end() noexcept
00578       { return iterator(_Base::end(), this); }
00579 
00580       const_iterator
00581       end() const noexcept
00582       { return const_iterator(_Base::end(), this); }
00583 
00584       const_iterator
00585       cbegin() const noexcept
00586       { return const_iterator(_Base::begin(), this); }
00587 
00588       const_iterator
00589       cend() const noexcept
00590       { return const_iterator(_Base::end(), this); }
00591 
00592       // local versions
00593       local_iterator
00594       begin(size_type __b)
00595       { return local_iterator(_Base::begin(__b), __b, this); }
00596 
00597       local_iterator
00598       end(size_type __b)
00599       { return local_iterator(_Base::end(__b), __b, this); }
00600 
00601       const_local_iterator
00602       begin(size_type __b) const
00603       { return const_local_iterator(_Base::begin(__b), __b, this); }
00604 
00605       const_local_iterator
00606       end(size_type __b) const
00607       { return const_local_iterator(_Base::end(__b), __b, this); }
00608 
00609       const_local_iterator
00610       cbegin(size_type __b) const
00611       { return const_local_iterator(_Base::cbegin(__b), __b, this); }
00612 
00613       const_local_iterator
00614       cend(size_type __b) const
00615       { return const_local_iterator(_Base::cend(__b), __b, this); }
00616 
00617       template<typename... _Args>
00618     iterator
00619     emplace(_Args&&... __args)
00620     {
00621       size_type __bucket_count = this->bucket_count();
00622       _Base_iterator __it
00623         = _Base::emplace(std::forward<_Args>(__args)...);
00624       _M_check_rehashed(__bucket_count);
00625       return iterator(__it, this);
00626     }
00627 
00628       template<typename... _Args>
00629     iterator
00630     emplace_hint(const_iterator __hint, _Args&&... __args)
00631     {
00632       __glibcxx_check_insert(__hint);
00633       size_type __bucket_count = this->bucket_count();
00634       _Base_iterator __it = _Base::emplace_hint(__hint.base(),
00635                     std::forward<_Args>(__args)...);
00636       _M_check_rehashed(__bucket_count);
00637       return iterator(__it, this);
00638     }
00639 
00640       iterator
00641       insert(const value_type& __obj)
00642       {
00643     size_type __bucket_count = this->bucket_count();
00644     _Base_iterator __it = _Base::insert(__obj);
00645     _M_check_rehashed(__bucket_count);
00646     return iterator(__it, this);
00647       }
00648 
00649       iterator
00650       insert(const_iterator __hint, const value_type& __obj)
00651       {
00652     __glibcxx_check_insert(__hint);
00653     size_type __bucket_count = this->bucket_count();
00654     _Base_iterator __it = _Base::insert(__hint.base(), __obj);
00655     _M_check_rehashed(__bucket_count);
00656     return iterator(__it, this);
00657       }
00658 
00659       template<typename _Pair, typename = typename
00660            std::enable_if<std::is_constructible<value_type,
00661                             _Pair&&>::value>::type>
00662     iterator
00663     insert(_Pair&& __obj)
00664     {
00665       size_type __bucket_count = this->bucket_count();
00666       _Base_iterator __it = _Base::insert(std::forward<_Pair>(__obj));
00667       _M_check_rehashed(__bucket_count);
00668       return iterator(__it, this);
00669     }
00670 
00671       template<typename _Pair, typename = typename
00672            std::enable_if<std::is_constructible<value_type,
00673                             _Pair&&>::value>::type>
00674     iterator
00675     insert(const_iterator __hint, _Pair&& __obj)
00676     {
00677       __glibcxx_check_insert(__hint);
00678       size_type __bucket_count = this->bucket_count();
00679       _Base_iterator __it =
00680         _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
00681       _M_check_rehashed(__bucket_count);
00682       return iterator(__it, this);
00683     }
00684 
00685       void
00686       insert(std::initializer_list<value_type> __l)
00687       { _Base::insert(__l); }
00688 
00689       template<typename _InputIterator>
00690     void
00691     insert(_InputIterator __first, _InputIterator __last)
00692     {
00693       __glibcxx_check_valid_range(__first, __last);
00694       size_type __bucket_count = this->bucket_count();
00695       _Base::insert(__gnu_debug::__base(__first),
00696             __gnu_debug::__base(__last));
00697       _M_check_rehashed(__bucket_count);
00698     }
00699 
00700       iterator
00701       find(const key_type& __key)
00702       { return iterator(_Base::find(__key), this); }
00703 
00704       const_iterator
00705       find(const key_type& __key) const
00706       { return const_iterator(_Base::find(__key), this); }
00707 
00708       std::pair<iterator, iterator>
00709       equal_range(const key_type& __key)
00710       {
00711     std::pair<_Base_iterator, _Base_iterator> __res =
00712       _Base::equal_range(__key);
00713     return std::make_pair(iterator(__res.first, this),
00714                   iterator(__res.second, this));
00715       }
00716 
00717       std::pair<const_iterator, const_iterator>
00718       equal_range(const key_type& __key) const
00719       {
00720     std::pair<_Base_const_iterator, _Base_const_iterator> __res =
00721       _Base::equal_range(__key);
00722     return std::make_pair(const_iterator(__res.first, this),
00723                   const_iterator(__res.second, this));
00724       }
00725 
00726       size_type
00727       erase(const key_type& __key)
00728       {
00729     size_type __ret(0);
00730     size_type __bucket_count = this->bucket_count();
00731     std::pair<_Base_iterator, _Base_iterator> __pair =
00732       _Base::equal_range(__key);
00733     for (_Base_iterator __victim = __pair.first; __victim != __pair.second;)
00734       {
00735         this->_M_invalidate_if([__victim](_Base_const_iterator __it)
00736                 { return __it == __victim; });
00737         _Base_local_iterator __local_victim = _S_to_local(__victim);
00738         this->_M_invalidate_local_if(
00739                 [__local_victim](_Base_const_local_iterator __it)
00740                 { return __it == __local_victim; });
00741         _Base::erase(__victim++);
00742         ++__ret;
00743       }
00744     _M_check_rehashed(__bucket_count);
00745     return __ret;
00746       }
00747 
00748       iterator
00749       erase(const_iterator __it)
00750       {
00751     __glibcxx_check_erase(__it);
00752     _Base_const_iterator __victim = __it.base();
00753     this->_M_invalidate_if([__victim](_Base_const_iterator __it)
00754             { return __it == __victim; });
00755     _Base_const_local_iterator __local_victim = _S_to_local(__victim);
00756     this->_M_invalidate_local_if(
00757             [__local_victim](_Base_const_local_iterator __it)
00758             { return __it == __local_victim; });
00759     size_type __bucket_count = this->bucket_count();
00760     _Base_iterator __next = _Base::erase(__it.base());
00761     _M_check_rehashed(__bucket_count);
00762     return iterator(__next, this);
00763       }
00764 
00765       iterator
00766       erase(iterator __it)
00767       { return erase(const_iterator(__it)); }
00768 
00769       iterator
00770       erase(const_iterator __first, const_iterator __last)
00771       {
00772     __glibcxx_check_erase_range(__first, __last);
00773     for (_Base_const_iterator __tmp = __first.base();
00774          __tmp != __last.base(); ++__tmp)
00775       {
00776         _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
00777                   _M_message(__gnu_debug::__msg_valid_range)
00778                   ._M_iterator(__first, "first")
00779                   ._M_iterator(__last, "last"));
00780         this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
00781                 { return __it == __tmp; });
00782         _Base_const_local_iterator __local_tmp = _S_to_local(__tmp);
00783         this->_M_invalidate_local_if(
00784                 [__local_tmp](_Base_const_local_iterator __it)
00785                 { return __it == __local_tmp; });
00786       }
00787     size_type __bucket_count = this->bucket_count();
00788     _Base_iterator __next = _Base::erase(__first.base(), __last.base());
00789     _M_check_rehashed(__bucket_count);
00790     return iterator(__next, this);
00791       }
00792 
00793       _Base&
00794       _M_base() noexcept       { return *this; }
00795 
00796       const _Base&
00797       _M_base() const noexcept { return *this; }
00798 
00799     private:
00800       void
00801       _M_invalidate_locals()
00802       {
00803     _Base_local_iterator __local_end = _Base::end(0);
00804     this->_M_invalidate_local_if(
00805             [__local_end](_Base_const_local_iterator __it)
00806             { return __it != __local_end; });
00807       }
00808 
00809       void
00810       _M_invalidate_all()
00811       {
00812     _Base_iterator __end = _Base::end();
00813     this->_M_invalidate_if([__end](_Base_const_iterator __it)
00814             { return __it != __end; });
00815     _M_invalidate_locals();
00816       }
00817 
00818       void
00819       _M_check_rehashed(size_type __prev_count)
00820       {
00821     if (__prev_count != this->bucket_count())
00822       _M_invalidate_locals();
00823       }
00824 
00825       static _Base_local_iterator
00826       _S_to_local(_Base_iterator __it)
00827       {
00828         // The returned local iterator will not be incremented so we don't
00829     // need to compute __it's node bucket
00830     return _Base_local_iterator(__it._M_cur, 0, 0);
00831       }
00832 
00833       static _Base_const_local_iterator
00834       _S_to_local(_Base_const_iterator __it)
00835       {
00836         // The returned local iterator will not be incremented so we don't
00837     // need to compute __it's node bucket
00838     return _Base_const_local_iterator(__it._M_cur, 0, 0);
00839       }
00840     };
00841 
00842   template<typename _Key, typename _Tp, typename _Hash,
00843        typename _Pred, typename _Alloc>
00844     inline void
00845     swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
00846      unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
00847     { __x.swap(__y); }
00848 
00849   template<typename _Key, typename _Tp, typename _Hash,
00850        typename _Pred, typename _Alloc>
00851     inline bool
00852     operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
00853            const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
00854     { return __x._M_equal(__y); }
00855 
00856   template<typename _Key, typename _Tp, typename _Hash,
00857        typename _Pred, typename _Alloc>
00858     inline bool
00859     operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
00860            const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
00861     { return !(__x == __y); }
00862 
00863 } // namespace __debug
00864 } // namespace std
00865 
00866 #endif // __GXX_EXPERIMENTAL_CXX0X__
00867 
00868 #endif