1 // Debugging unordered_map/unordered_multimap implementation -*- C++ -*-
 
    3 // Copyright (C) 2003-2014 Free Software Foundation, Inc.
 
    5 // This file is part of the GNU ISO C++ Library.  This library is free
 
    6 // software; you can redistribute it and/or modify it under the
 
    7 // terms of the GNU General Public License as published by the
 
    8 // Free Software Foundation; either version 3, or (at your option)
 
   11 // This library is distributed in the hope that it will be useful,
 
   12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 
   13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
   14 // GNU General Public License for more details.
 
   16 // Under Section 7 of GPL version 3, you are granted additional
 
   17 // permissions described in the GCC Runtime Library Exception, version
 
   18 // 3.1, as published by the Free Software Foundation.
 
   20 // You should have received a copy of the GNU General Public License and
 
   21 // a copy of the GCC Runtime Library Exception along with this program;
 
   22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
   23 // <http://www.gnu.org/licenses/>.
 
   25 /** @file debug/unordered_map
 
   26  *  This file is a GNU debug extension to the Standard C++ Library.
 
   29 #ifndef _GLIBCXX_DEBUG_UNORDERED_MAP
 
   30 #define _GLIBCXX_DEBUG_UNORDERED_MAP 1
 
   32 #if __cplusplus < 201103L
 
   33 # include <bits/c++0x_warning.h>
 
   35 # include <unordered_map>
 
   37 #include <debug/safe_unordered_container.h>
 
   38 #include <debug/safe_iterator.h>
 
   39 #include <debug/safe_local_iterator.h>
 
   41 namespace std _GLIBCXX_VISIBILITY(default)
 
   45   /// Class std::unordered_map with safety/checking/debug instrumentation.
 
   46   template<typename _Key, typename _Tp,
 
   47       typename _Hash = std::hash<_Key>,
 
   48       typename _Pred = std::equal_to<_Key>,
 
   49       typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
 
   51     : public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>,
 
   52       public __gnu_debug::_Safe_unordered_container<unordered_map<_Key, _Tp,
 
   53                            _Hash, _Pred, _Alloc> >
 
   55       typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash,
 
   57       typedef __gnu_debug::_Safe_unordered_container<unordered_map> _Safe_base;
 
   58       typedef typename _Base::const_iterator _Base_const_iterator;
 
   59       typedef typename _Base::iterator _Base_iterator;
 
   60       typedef typename _Base::const_local_iterator _Base_const_local_iterator;
 
   61       typedef typename _Base::local_iterator _Base_local_iterator;
 
   63       typedef __gnu_cxx::__alloc_traits<typename
 
   64                    _Base::allocator_type> _Alloc_traits;
 
   67       typedef typename _Base::size_type       size_type;
 
   68       typedef typename _Base::hasher          hasher;
 
   69       typedef typename _Base::key_equal       key_equal;
 
   70       typedef typename _Base::allocator_type  allocator_type;
 
   72       typedef typename _Base::key_type        key_type;
 
   73       typedef typename _Base::value_type      value_type;
 
   75       typedef __gnu_debug::_Safe_iterator<_Base_iterator,
 
   76                      unordered_map> iterator;
 
   77       typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
 
   78                      unordered_map> const_iterator;
 
   79       typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator,
 
   80                      unordered_map> local_iterator;
 
   81       typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator,
 
   82                      unordered_map> const_local_iterator;
 
   85       unordered_map(size_type __n = 10,
 
   86            const hasher& __hf = hasher(),
 
   87            const key_equal& __eql = key_equal(),
 
   88            const allocator_type& __a = allocator_type())
 
   89       : _Base(__n, __hf, __eql, __a) { }
 
   91       template<typename _InputIterator>
 
   92    unordered_map(_InputIterator __first, _InputIterator __last, 
 
   94              const hasher& __hf = hasher(), 
 
   95              const key_equal& __eql = key_equal(), 
 
   96              const allocator_type& __a = allocator_type())
 
   97    : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
 
   99        __gnu_debug::__base(__last), __n,
 
  100        __hf, __eql, __a) { }
 
  102       unordered_map(const unordered_map&) = default;
 
  104       unordered_map(const _Base& __x)
 
  107       unordered_map(unordered_map&&) = default;
 
  110       unordered_map(const allocator_type& __a)
 
  114       unordered_map(const unordered_map& __umap,
 
  115            const allocator_type& __a)
 
  116    : _Base(__umap._M_base(), __a)
 
  119       unordered_map(unordered_map&& __umap,
 
  120            const allocator_type& __a)
 
  121    : _Base(std::move(__umap._M_base()), __a)
 
  124       unordered_map(initializer_list<value_type> __l,
 
  126            const hasher& __hf = hasher(),
 
  127            const key_equal& __eql = key_equal(),
 
  128            const allocator_type& __a = allocator_type())
 
  129       : _Base(__l, __n, __hf, __eql, __a) { }
 
  131       ~unordered_map() noexcept { }
 
  134       operator=(const unordered_map& __x)
 
  136    _M_base() = __x._M_base();
 
  137    this->_M_invalidate_all();
 
  142       operator=(unordered_map&& __x)
 
  143       noexcept(_Alloc_traits::_S_nothrow_move())
 
  145    __glibcxx_check_self_move_assign(__x);
 
  146    bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
 
  147        || __x.get_allocator() == this->get_allocator();
 
  148    _M_base() = std::move(__x._M_base());   
 
  152      this->_M_invalidate_all();
 
  153    __x._M_invalidate_all();
 
  158       operator=(initializer_list<value_type> __l)
 
  161    this->_M_invalidate_all();
 
  166       swap(unordered_map& __x)
 
  167       noexcept(_Alloc_traits::_S_nothrow_swap())
 
  169    if (!_Alloc_traits::_S_propagate_on_swap())
 
  170      __glibcxx_check_equal_allocs(__x);
 
  172    _Safe_base::_M_swap(__x);
 
  179    this->_M_invalidate_all();
 
  184       { return iterator(_Base::begin(), this); }
 
  187       begin() const noexcept
 
  188       { return const_iterator(_Base::begin(), this); }
 
  192       { return iterator(_Base::end(), this); }
 
  196       { return const_iterator(_Base::end(), this); }
 
  199       cbegin() const noexcept
 
  200       { return const_iterator(_Base::begin(), this); }
 
  203       cend() const noexcept
 
  204       { return const_iterator(_Base::end(), this); }
 
  210    __glibcxx_check_bucket_index(__b);
 
  211    return local_iterator(_Base::begin(__b), this);
 
  217    __glibcxx_check_bucket_index(__b);
 
  218    return local_iterator(_Base::end(__b), this);
 
  222       begin(size_type __b) const
 
  224    __glibcxx_check_bucket_index(__b);
 
  225    return const_local_iterator(_Base::begin(__b), this);
 
  229       end(size_type __b) const
 
  231    __glibcxx_check_bucket_index(__b);
 
  232    return const_local_iterator(_Base::end(__b), this);
 
  236       cbegin(size_type __b) const
 
  238    __glibcxx_check_bucket_index(__b);
 
  239    return const_local_iterator(_Base::cbegin(__b), this);
 
  243       cend(size_type __b) const
 
  245    __glibcxx_check_bucket_index(__b);
 
  246    return const_local_iterator(_Base::cend(__b), this);
 
  250       bucket_size(size_type __b) const
 
  252    __glibcxx_check_bucket_index(__b);
 
  253    return _Base::bucket_size(__b);
 
  257       max_load_factor() const noexcept
 
  258       { return _Base::max_load_factor(); }
 
  261       max_load_factor(float __f)
 
  263    __glibcxx_check_max_load_factor(__f);
 
  264    _Base::max_load_factor(__f);
 
  267       template<typename... _Args>
 
  268    std::pair<iterator, bool>
 
  269    emplace(_Args&&... __args)
 
  271      size_type __bucket_count = this->bucket_count();
 
  272      std::pair<_Base_iterator, bool> __res
 
  273        = _Base::emplace(std::forward<_Args>(__args)...);
 
  274      _M_check_rehashed(__bucket_count);
 
  275      return std::make_pair(iterator(__res.first, this), __res.second);
 
  278       template<typename... _Args>
 
  280    emplace_hint(const_iterator __hint, _Args&&... __args)
 
  282      __glibcxx_check_insert(__hint);
 
  283      size_type __bucket_count = this->bucket_count();
 
  284      _Base_iterator __it = _Base::emplace_hint(__hint.base(),
 
  285                    std::forward<_Args>(__args)...);
 
  286      _M_check_rehashed(__bucket_count);
 
  287      return iterator(__it, this);
 
  290       std::pair<iterator, bool>
 
  291       insert(const value_type& __obj)
 
  293    size_type __bucket_count = this->bucket_count();
 
  294    std::pair<_Base_iterator, bool> __res = _Base::insert(__obj);
 
  295    _M_check_rehashed(__bucket_count);
 
  296    return std::make_pair(iterator(__res.first, this), __res.second);
 
  300       insert(const_iterator __hint, const value_type& __obj)
 
  302    __glibcxx_check_insert(__hint);
 
  303    size_type __bucket_count = this->bucket_count();
 
  304    _Base_iterator __it = _Base::insert(__hint.base(), __obj); 
 
  305    _M_check_rehashed(__bucket_count);
 
  306    return iterator(__it, this);
 
  309       template<typename _Pair, typename = typename
 
  310           std::enable_if<std::is_constructible<value_type,
 
  311                            _Pair&&>::value>::type>
 
  312    std::pair<iterator, bool>
 
  313    insert(_Pair&& __obj)
 
  315      size_type __bucket_count = this->bucket_count();
 
  316      std::pair<_Base_iterator, bool> __res =
 
  317        _Base::insert(std::forward<_Pair>(__obj));
 
  318      _M_check_rehashed(__bucket_count);
 
  319      return std::make_pair(iterator(__res.first, this), __res.second);
 
  322       template<typename _Pair, typename = typename
 
  323           std::enable_if<std::is_constructible<value_type,
 
  324                            _Pair&&>::value>::type>
 
  326    insert(const_iterator __hint, _Pair&& __obj)
 
  328      __glibcxx_check_insert(__hint);
 
  329      size_type __bucket_count = this->bucket_count();
 
  330      _Base_iterator __it =
 
  331        _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
 
  332      _M_check_rehashed(__bucket_count);
 
  333      return iterator(__it, this);
 
  337       insert(std::initializer_list<value_type> __l)
 
  339    size_type __bucket_count = this->bucket_count();
 
  341    _M_check_rehashed(__bucket_count);
 
  344       template<typename _InputIterator>
 
  346    insert(_InputIterator __first, _InputIterator __last)
 
  348      __glibcxx_check_valid_range(__first, __last);
 
  349      size_type __bucket_count = this->bucket_count();
 
  350      _Base::insert(__gnu_debug::__base(__first),
 
  351            __gnu_debug::__base(__last));
 
  352      _M_check_rehashed(__bucket_count);
 
  356       find(const key_type& __key)
 
  357       { return iterator(_Base::find(__key), this); }
 
  360       find(const key_type& __key) const
 
  361       { return const_iterator(_Base::find(__key), this); }
 
  363       std::pair<iterator, iterator>
 
  364       equal_range(const key_type& __key)
 
  366    std::pair<_Base_iterator, _Base_iterator> __res =
 
  367      _Base::equal_range(__key);
 
  368    return std::make_pair(iterator(__res.first, this),
 
  369                  iterator(__res.second, this));
 
  372       std::pair<const_iterator, const_iterator>
 
  373       equal_range(const key_type& __key) const
 
  375    std::pair<_Base_const_iterator, _Base_const_iterator> __res =
 
  376      _Base::equal_range(__key);
 
  377    return std::make_pair(const_iterator(__res.first, this),
 
  378                  const_iterator(__res.second, this));
 
  382       erase(const key_type& __key)
 
  385    _Base_iterator __victim(_Base::find(__key));
 
  386    if (__victim != _Base::end())
 
  388        this->_M_invalidate_if([__victim](_Base_const_iterator __it)
 
  389                { return __it == __victim; });
 
  390        this->_M_invalidate_local_if(
 
  391                [__victim](_Base_const_local_iterator __it)
 
  392                { return __it._M_curr() == __victim._M_cur; });
 
  393        size_type __bucket_count = this->bucket_count();
 
  394        _Base::erase(__victim);
 
  395        _M_check_rehashed(__bucket_count);
 
  402       erase(const_iterator __it)
 
  404    __glibcxx_check_erase(__it);
 
  405    _Base_const_iterator __victim = __it.base();
 
  406    this->_M_invalidate_if([__victim](_Base_const_iterator __it)
 
  407            { return __it == __victim; });
 
  408    this->_M_invalidate_local_if(
 
  409            [__victim](_Base_const_local_iterator __it)
 
  410            { return __it._M_curr() == __victim._M_cur; });
 
  411    size_type __bucket_count = this->bucket_count();
 
  412    _Base_iterator __next = _Base::erase(__it.base()); 
 
  413    _M_check_rehashed(__bucket_count);
 
  414    return iterator(__next, this);
 
  419       { return erase(const_iterator(__it)); }
 
  422       erase(const_iterator __first, const_iterator __last)
 
  424    __glibcxx_check_erase_range(__first, __last);
 
  425    for (_Base_const_iterator __tmp = __first.base();
 
  426         __tmp != __last.base(); ++__tmp)
 
  428        _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
 
  429                  _M_message(__gnu_debug::__msg_valid_range)
 
  430                  ._M_iterator(__first, "first")
 
  431                  ._M_iterator(__last, "last"));
 
  432        this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
 
  433                { return __it == __tmp; });
 
  434        this->_M_invalidate_local_if(
 
  435                [__tmp](_Base_const_local_iterator __it)
 
  436                { return __it._M_curr() == __tmp._M_cur; });
 
  438    size_type __bucket_count = this->bucket_count();
 
  439    _Base_iterator __next = _Base::erase(__first.base(), __last.base());
 
  440    _M_check_rehashed(__bucket_count);
 
  441    return iterator(__next, this);
 
  445       _M_base() noexcept       { return *this; }
 
  448       _M_base() const noexcept { return *this; }
 
  452       _M_invalidate_locals()
 
  454    _Base_local_iterator __local_end = _Base::end(0);
 
  455    this->_M_invalidate_local_if(
 
  456            [__local_end](_Base_const_local_iterator __it)
 
  457            { return __it != __local_end; });
 
  463    _Base_iterator __end = _Base::end();
 
  464    this->_M_invalidate_if([__end](_Base_const_iterator __it)
 
  465            { return __it != __end; });
 
  466    _M_invalidate_locals();
 
  470       _M_check_rehashed(size_type __prev_count)
 
  472    if (__prev_count != this->bucket_count())
 
  473      _M_invalidate_locals();
 
  477   template<typename _Key, typename _Tp, typename _Hash,
 
  478       typename _Pred, typename _Alloc>
 
  480     swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
 
  481     unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
 
  484   template<typename _Key, typename _Tp, typename _Hash,
 
  485       typename _Pred, typename _Alloc>
 
  487     operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
 
  488           const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
 
  489     { return __x._M_base() == __y._M_base(); }
 
  491   template<typename _Key, typename _Tp, typename _Hash,
 
  492       typename _Pred, typename _Alloc>
 
  494     operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
 
  495           const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
 
  496     { return !(__x == __y); }
 
  499   /// Class std::unordered_multimap with safety/checking/debug instrumentation.
 
  500   template<typename _Key, typename _Tp,
 
  501       typename _Hash = std::hash<_Key>,
 
  502       typename _Pred = std::equal_to<_Key>,
 
  503       typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
 
  504     class unordered_multimap
 
  505     : public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
 
  507       public __gnu_debug::_Safe_unordered_container<unordered_multimap<_Key,
 
  508                        _Tp, _Hash, _Pred, _Alloc> >
 
  510       typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
 
  511                         _Pred, _Alloc> _Base;
 
  512       typedef __gnu_debug::_Safe_unordered_container<unordered_multimap>
 
  514       typedef typename _Base::const_iterator _Base_const_iterator;
 
  515       typedef typename _Base::iterator _Base_iterator;
 
  516       typedef typename _Base::const_local_iterator _Base_const_local_iterator;
 
  517       typedef typename _Base::local_iterator _Base_local_iterator;
 
  519       typedef __gnu_cxx::__alloc_traits<typename
 
  520                    _Base::allocator_type> _Alloc_traits;
 
  523       typedef typename _Base::size_type       size_type;
 
  524       typedef typename _Base::hasher          hasher;
 
  525       typedef typename _Base::key_equal       key_equal;
 
  526       typedef typename _Base::allocator_type  allocator_type;
 
  528       typedef typename _Base::key_type        key_type;
 
  529       typedef typename _Base::value_type      value_type;
 
  531       typedef __gnu_debug::_Safe_iterator<_Base_iterator,
 
  532                      unordered_multimap> iterator;
 
  533       typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
 
  534                      unordered_multimap> const_iterator;
 
  535       typedef __gnu_debug::_Safe_local_iterator<
 
  536    _Base_local_iterator, unordered_multimap> local_iterator;
 
  537       typedef __gnu_debug::_Safe_local_iterator<
 
  538    _Base_const_local_iterator, unordered_multimap> const_local_iterator;
 
  541       unordered_multimap(size_type __n = 10,
 
  542             const hasher& __hf = hasher(),
 
  543             const key_equal& __eql = key_equal(),
 
  544             const allocator_type& __a = allocator_type())
 
  545       : _Base(__n, __hf, __eql, __a) { }
 
  547       template<typename _InputIterator>
 
  548    unordered_multimap(_InputIterator __first, _InputIterator __last, 
 
  550               const hasher& __hf = hasher(), 
 
  551               const key_equal& __eql = key_equal(), 
 
  552               const allocator_type& __a = allocator_type())
 
  553    : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
 
  555        __gnu_debug::__base(__last), __n,
 
  556        __hf, __eql, __a) { }
 
  558       unordered_multimap(const unordered_multimap&) = default;
 
  560       unordered_multimap(const _Base& __x) 
 
  563       unordered_multimap(unordered_multimap&&) = default;
 
  566       unordered_multimap(const allocator_type& __a)
 
  570       unordered_multimap(const unordered_multimap& __umap,
 
  571             const allocator_type& __a)
 
  572    : _Base(__umap._M_base(), __a)
 
  575       unordered_multimap(unordered_multimap&& __umap,
 
  576             const allocator_type& __a)
 
  577    : _Base(std::move(__umap._M_base()), __a)
 
  580       unordered_multimap(initializer_list<value_type> __l,
 
  582             const hasher& __hf = hasher(),
 
  583             const key_equal& __eql = key_equal(),
 
  584             const allocator_type& __a = allocator_type())
 
  585       : _Base(__l, __n, __hf, __eql, __a) { }
 
  587       ~unordered_multimap() noexcept { }
 
  590       operator=(const unordered_multimap& __x)
 
  592    _M_base() = __x._M_base();
 
  593    this->_M_invalidate_all();
 
  598       operator=(unordered_multimap&& __x)
 
  599       noexcept(_Alloc_traits::_S_nothrow_move())
 
  601    __glibcxx_check_self_move_assign(__x);
 
  602    bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
 
  603        || __x.get_allocator() == this->get_allocator();
 
  604    _M_base() = std::move(__x._M_base());
 
  608      this->_M_invalidate_all();
 
  609    __x._M_invalidate_all();
 
  614       operator=(initializer_list<value_type> __l)
 
  617    this->_M_invalidate_all();
 
  622       swap(unordered_multimap& __x)
 
  623       noexcept(_Alloc_traits::_S_nothrow_swap())
 
  625    if (!_Alloc_traits::_S_propagate_on_swap())
 
  626      __glibcxx_check_equal_allocs(__x);
 
  628    _Safe_base::_M_swap(__x);
 
  635    this->_M_invalidate_all();
 
  640       { return iterator(_Base::begin(), this); }
 
  643       begin() const noexcept
 
  644       { return const_iterator(_Base::begin(), this); }
 
  648       { return iterator(_Base::end(), this); }
 
  652       { return const_iterator(_Base::end(), this); }
 
  655       cbegin() const noexcept
 
  656       { return const_iterator(_Base::begin(), this); }
 
  659       cend() const noexcept
 
  660       { return const_iterator(_Base::end(), this); }
 
  666    __glibcxx_check_bucket_index(__b);
 
  667    return local_iterator(_Base::begin(__b), this);
 
  673    __glibcxx_check_bucket_index(__b);
 
  674    return local_iterator(_Base::end(__b), this);
 
  678       begin(size_type __b) const
 
  680    __glibcxx_check_bucket_index(__b);
 
  681    return const_local_iterator(_Base::begin(__b), this);
 
  685       end(size_type __b) const
 
  687    __glibcxx_check_bucket_index(__b);
 
  688    return const_local_iterator(_Base::end(__b), this);
 
  692       cbegin(size_type __b) const
 
  694    __glibcxx_check_bucket_index(__b);
 
  695    return const_local_iterator(_Base::cbegin(__b), this);
 
  699       cend(size_type __b) const
 
  701    __glibcxx_check_bucket_index(__b);
 
  702    return const_local_iterator(_Base::cend(__b), this);
 
  706       bucket_size(size_type __b) const
 
  708    __glibcxx_check_bucket_index(__b);
 
  709    return _Base::bucket_size(__b);
 
  713       max_load_factor() const noexcept
 
  714       { return _Base::max_load_factor(); }
 
  717       max_load_factor(float __f)
 
  719    __glibcxx_check_max_load_factor(__f);
 
  720    _Base::max_load_factor(__f);
 
  723       template<typename... _Args>
 
  725    emplace(_Args&&... __args)
 
  727      size_type __bucket_count = this->bucket_count();
 
  729        = _Base::emplace(std::forward<_Args>(__args)...);
 
  730      _M_check_rehashed(__bucket_count);
 
  731      return iterator(__it, this);
 
  734       template<typename... _Args>
 
  736    emplace_hint(const_iterator __hint, _Args&&... __args)
 
  738      __glibcxx_check_insert(__hint);
 
  739      size_type __bucket_count = this->bucket_count();
 
  740      _Base_iterator __it = _Base::emplace_hint(__hint.base(),
 
  741                    std::forward<_Args>(__args)...);
 
  742      _M_check_rehashed(__bucket_count);
 
  743      return iterator(__it, this);
 
  747       insert(const value_type& __obj)
 
  749    size_type __bucket_count = this->bucket_count();
 
  750    _Base_iterator __it = _Base::insert(__obj);
 
  751    _M_check_rehashed(__bucket_count);
 
  752    return iterator(__it, this);
 
  756       insert(const_iterator __hint, const value_type& __obj)
 
  758    __glibcxx_check_insert(__hint);
 
  759    size_type __bucket_count = this->bucket_count();
 
  760    _Base_iterator __it = _Base::insert(__hint.base(), __obj);
 
  761    _M_check_rehashed(__bucket_count);
 
  762    return iterator(__it, this);
 
  765       template<typename _Pair, typename = typename
 
  766           std::enable_if<std::is_constructible<value_type,
 
  767                            _Pair&&>::value>::type>
 
  769    insert(_Pair&& __obj)
 
  771      size_type __bucket_count = this->bucket_count();
 
  772      _Base_iterator __it = _Base::insert(std::forward<_Pair>(__obj));
 
  773      _M_check_rehashed(__bucket_count);
 
  774      return iterator(__it, this);
 
  777       template<typename _Pair, typename = typename
 
  778           std::enable_if<std::is_constructible<value_type,
 
  779                            _Pair&&>::value>::type>
 
  781    insert(const_iterator __hint, _Pair&& __obj)
 
  783      __glibcxx_check_insert(__hint);
 
  784      size_type __bucket_count = this->bucket_count();
 
  785      _Base_iterator __it =
 
  786        _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
 
  787      _M_check_rehashed(__bucket_count);
 
  788      return iterator(__it, this);
 
  792       insert(std::initializer_list<value_type> __l)
 
  793       { _Base::insert(__l); }
 
  795       template<typename _InputIterator>
 
  797    insert(_InputIterator __first, _InputIterator __last)
 
  799      __glibcxx_check_valid_range(__first, __last);
 
  800      size_type __bucket_count = this->bucket_count();
 
  801      _Base::insert(__gnu_debug::__base(__first),
 
  802            __gnu_debug::__base(__last));
 
  803      _M_check_rehashed(__bucket_count);
 
  807       find(const key_type& __key)
 
  808       { return iterator(_Base::find(__key), this); }
 
  811       find(const key_type& __key) const
 
  812       { return const_iterator(_Base::find(__key), this); }
 
  814       std::pair<iterator, iterator>
 
  815       equal_range(const key_type& __key)
 
  817    std::pair<_Base_iterator, _Base_iterator> __res =
 
  818      _Base::equal_range(__key);
 
  819    return std::make_pair(iterator(__res.first, this),
 
  820                  iterator(__res.second, this));
 
  823       std::pair<const_iterator, const_iterator>
 
  824       equal_range(const key_type& __key) const
 
  826    std::pair<_Base_const_iterator, _Base_const_iterator> __res =
 
  827      _Base::equal_range(__key);
 
  828    return std::make_pair(const_iterator(__res.first, this),
 
  829                  const_iterator(__res.second, this));
 
  833       erase(const key_type& __key)
 
  836    size_type __bucket_count = this->bucket_count();
 
  837    std::pair<_Base_iterator, _Base_iterator> __pair =
 
  838      _Base::equal_range(__key);
 
  839    for (_Base_iterator __victim = __pair.first; __victim != __pair.second;)
 
  841        this->_M_invalidate_if([__victim](_Base_const_iterator __it)
 
  842                { return __it == __victim; });
 
  843        this->_M_invalidate_local_if(
 
  844                [__victim](_Base_const_local_iterator __it)
 
  845                { return __it._M_curr() == __victim._M_cur; });
 
  846        _Base::erase(__victim++);
 
  849    _M_check_rehashed(__bucket_count);
 
  854       erase(const_iterator __it)
 
  856    __glibcxx_check_erase(__it);
 
  857    _Base_const_iterator __victim = __it.base();
 
  858    this->_M_invalidate_if([__victim](_Base_const_iterator __it)
 
  859            { return __it == __victim; });
 
  860    this->_M_invalidate_local_if(
 
  861            [__victim](_Base_const_local_iterator __it)
 
  862            { return __it._M_curr() == __victim._M_cur; });
 
  863    size_type __bucket_count = this->bucket_count();
 
  864    _Base_iterator __next = _Base::erase(__it.base());
 
  865    _M_check_rehashed(__bucket_count);
 
  866    return iterator(__next, this);
 
  871       { return erase(const_iterator(__it)); }
 
  874       erase(const_iterator __first, const_iterator __last)
 
  876    __glibcxx_check_erase_range(__first, __last);
 
  877    for (_Base_const_iterator __tmp = __first.base();
 
  878         __tmp != __last.base(); ++__tmp)
 
  880        _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
 
  881                  _M_message(__gnu_debug::__msg_valid_range)
 
  882                  ._M_iterator(__first, "first")
 
  883                  ._M_iterator(__last, "last"));
 
  884        this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
 
  885                { return __it == __tmp; });
 
  886        this->_M_invalidate_local_if(
 
  887                [__tmp](_Base_const_local_iterator __it)
 
  888                { return __it._M_curr() == __tmp._M_cur; });
 
  890    size_type __bucket_count = this->bucket_count();
 
  891    _Base_iterator __next = _Base::erase(__first.base(), __last.base());
 
  892    _M_check_rehashed(__bucket_count);
 
  893    return iterator(__next, this);
 
  897       _M_base() noexcept       { return *this; }
 
  900       _M_base() const noexcept { return *this; }
 
  904       _M_invalidate_locals()
 
  906    _Base_local_iterator __local_end = _Base::end(0);
 
  907    this->_M_invalidate_local_if(
 
  908            [__local_end](_Base_const_local_iterator __it)
 
  909            { return __it != __local_end; });
 
  915    _Base_iterator __end = _Base::end();
 
  916    this->_M_invalidate_if([__end](_Base_const_iterator __it)
 
  917            { return __it != __end; });
 
  918    _M_invalidate_locals();
 
  922       _M_check_rehashed(size_type __prev_count)
 
  924    if (__prev_count != this->bucket_count())
 
  925      _M_invalidate_locals();
 
  929   template<typename _Key, typename _Tp, typename _Hash,
 
  930       typename _Pred, typename _Alloc>
 
  932     swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
 
  933     unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
 
  936   template<typename _Key, typename _Tp, typename _Hash,
 
  937       typename _Pred, typename _Alloc>
 
  939     operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
 
  940           const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
 
  941     { return __x._M_base() == __y._M_base(); }
 
  943   template<typename _Key, typename _Tp, typename _Hash,
 
  944       typename _Pred, typename _Alloc>
 
  946     operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
 
  947           const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
 
  948     { return !(__x == __y); }
 
  950 } // namespace __debug