libstdc++

unordered_map

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