138fd1498Szrj // unordered_map implementation -*- C++ -*-
238fd1498Szrj 
338fd1498Szrj // Copyright (C) 2010-2018 Free Software Foundation, Inc.
438fd1498Szrj //
538fd1498Szrj // This file is part of the GNU ISO C++ Library.  This library is free
638fd1498Szrj // software; you can redistribute it and/or modify it under the
738fd1498Szrj // terms of the GNU General Public License as published by the
838fd1498Szrj // Free Software Foundation; either version 3, or (at your option)
938fd1498Szrj // any later version.
1038fd1498Szrj 
1138fd1498Szrj // This library is distributed in the hope that it will be useful,
1238fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
1338fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1438fd1498Szrj // GNU General Public License for more details.
1538fd1498Szrj 
1638fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
1738fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
1838fd1498Szrj // 3.1, as published by the Free Software Foundation.
1938fd1498Szrj 
2038fd1498Szrj // You should have received a copy of the GNU General Public License and
2138fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program;
2238fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2338fd1498Szrj // <http://www.gnu.org/licenses/>.
2438fd1498Szrj 
2538fd1498Szrj /** @file bits/unordered_map.h
2638fd1498Szrj  *  This is an internal header file, included by other library headers.
2738fd1498Szrj  *  Do not attempt to use it directly. @headername{unordered_map}
2838fd1498Szrj  */
2938fd1498Szrj 
3038fd1498Szrj #ifndef _UNORDERED_MAP_H
3138fd1498Szrj #define _UNORDERED_MAP_H
3238fd1498Szrj 
_GLIBCXX_VISIBILITY(default)3338fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default)
3438fd1498Szrj {
3538fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
3638fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
3738fd1498Szrj 
3838fd1498Szrj   /// Base types for unordered_map.
3938fd1498Szrj   template<bool _Cache>
4038fd1498Szrj     using __umap_traits = __detail::_Hashtable_traits<_Cache, false, true>;
4138fd1498Szrj 
4238fd1498Szrj   template<typename _Key,
4338fd1498Szrj 	   typename _Tp,
4438fd1498Szrj 	   typename _Hash = hash<_Key>,
4538fd1498Szrj 	   typename _Pred = std::equal_to<_Key>,
4638fd1498Szrj 	   typename _Alloc = std::allocator<std::pair<const _Key, _Tp> >,
4738fd1498Szrj 	   typename _Tr = __umap_traits<__cache_default<_Key, _Hash>::value>>
4838fd1498Szrj     using __umap_hashtable = _Hashtable<_Key, std::pair<const _Key, _Tp>,
4938fd1498Szrj                                         _Alloc, __detail::_Select1st,
5038fd1498Szrj 				        _Pred, _Hash,
5138fd1498Szrj 				        __detail::_Mod_range_hashing,
5238fd1498Szrj 				        __detail::_Default_ranged_hash,
5338fd1498Szrj 				        __detail::_Prime_rehash_policy, _Tr>;
5438fd1498Szrj 
5538fd1498Szrj   /// Base types for unordered_multimap.
5638fd1498Szrj   template<bool _Cache>
5738fd1498Szrj     using __ummap_traits = __detail::_Hashtable_traits<_Cache, false, false>;
5838fd1498Szrj 
5938fd1498Szrj   template<typename _Key,
6038fd1498Szrj 	   typename _Tp,
6138fd1498Szrj 	   typename _Hash = hash<_Key>,
6238fd1498Szrj 	   typename _Pred = std::equal_to<_Key>,
6338fd1498Szrj 	   typename _Alloc = std::allocator<std::pair<const _Key, _Tp> >,
6438fd1498Szrj 	   typename _Tr = __ummap_traits<__cache_default<_Key, _Hash>::value>>
6538fd1498Szrj     using __ummap_hashtable = _Hashtable<_Key, std::pair<const _Key, _Tp>,
6638fd1498Szrj 					 _Alloc, __detail::_Select1st,
6738fd1498Szrj 					 _Pred, _Hash,
6838fd1498Szrj 					 __detail::_Mod_range_hashing,
6938fd1498Szrj 					 __detail::_Default_ranged_hash,
7038fd1498Szrj 					 __detail::_Prime_rehash_policy, _Tr>;
7138fd1498Szrj 
7238fd1498Szrj   template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
7338fd1498Szrj     class unordered_multimap;
7438fd1498Szrj 
7538fd1498Szrj   /**
7638fd1498Szrj    *  @brief A standard container composed of unique keys (containing
7738fd1498Szrj    *  at most one of each key value) that associates values of another type
7838fd1498Szrj    *  with the keys.
7938fd1498Szrj    *
8038fd1498Szrj    *  @ingroup unordered_associative_containers
8138fd1498Szrj    *
8238fd1498Szrj    *  @tparam  _Key    Type of key objects.
8338fd1498Szrj    *  @tparam  _Tp     Type of mapped objects.
8438fd1498Szrj    *  @tparam  _Hash   Hashing function object type, defaults to hash<_Value>.
8538fd1498Szrj    *  @tparam  _Pred   Predicate function object type, defaults
8638fd1498Szrj    *                   to equal_to<_Value>.
8738fd1498Szrj    *  @tparam  _Alloc  Allocator type, defaults to
8838fd1498Szrj    *                   std::allocator<std::pair<const _Key, _Tp>>.
8938fd1498Szrj    *
9038fd1498Szrj    *  Meets the requirements of a <a href="tables.html#65">container</a>, and
9138fd1498Szrj    *  <a href="tables.html#xx">unordered associative container</a>
9238fd1498Szrj    *
9338fd1498Szrj    * The resulting value type of the container is std::pair<const _Key, _Tp>.
9438fd1498Szrj    *
9538fd1498Szrj    *  Base is _Hashtable, dispatched at compile time via template
9638fd1498Szrj    *  alias __umap_hashtable.
9738fd1498Szrj    */
9838fd1498Szrj   template<typename _Key, typename _Tp,
9938fd1498Szrj 	   typename _Hash = hash<_Key>,
10038fd1498Szrj 	   typename _Pred = equal_to<_Key>,
10138fd1498Szrj 	   typename _Alloc = allocator<std::pair<const _Key, _Tp>>>
10238fd1498Szrj     class unordered_map
10338fd1498Szrj     {
10438fd1498Szrj       typedef __umap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc>  _Hashtable;
10538fd1498Szrj       _Hashtable _M_h;
10638fd1498Szrj 
10738fd1498Szrj     public:
10838fd1498Szrj       // typedefs:
10938fd1498Szrj       //@{
11038fd1498Szrj       /// Public typedefs.
11138fd1498Szrj       typedef typename _Hashtable::key_type	key_type;
11238fd1498Szrj       typedef typename _Hashtable::value_type	value_type;
11338fd1498Szrj       typedef typename _Hashtable::mapped_type	mapped_type;
11438fd1498Szrj       typedef typename _Hashtable::hasher	hasher;
11538fd1498Szrj       typedef typename _Hashtable::key_equal	key_equal;
11638fd1498Szrj       typedef typename _Hashtable::allocator_type allocator_type;
11738fd1498Szrj       //@}
11838fd1498Szrj 
11938fd1498Szrj       //@{
12038fd1498Szrj       ///  Iterator-related typedefs.
12138fd1498Szrj       typedef typename _Hashtable::pointer		pointer;
12238fd1498Szrj       typedef typename _Hashtable::const_pointer	const_pointer;
12338fd1498Szrj       typedef typename _Hashtable::reference		reference;
12438fd1498Szrj       typedef typename _Hashtable::const_reference	const_reference;
12538fd1498Szrj       typedef typename _Hashtable::iterator		iterator;
12638fd1498Szrj       typedef typename _Hashtable::const_iterator	const_iterator;
12738fd1498Szrj       typedef typename _Hashtable::local_iterator	local_iterator;
12838fd1498Szrj       typedef typename _Hashtable::const_local_iterator	const_local_iterator;
12938fd1498Szrj       typedef typename _Hashtable::size_type		size_type;
13038fd1498Szrj       typedef typename _Hashtable::difference_type	difference_type;
13138fd1498Szrj       //@}
13238fd1498Szrj 
13338fd1498Szrj #if __cplusplus > 201402L
13438fd1498Szrj       using node_type = typename _Hashtable::node_type;
13538fd1498Szrj       using insert_return_type = typename _Hashtable::insert_return_type;
13638fd1498Szrj #endif
13738fd1498Szrj 
13838fd1498Szrj       //construct/destroy/copy
13938fd1498Szrj 
14038fd1498Szrj       /// Default constructor.
14138fd1498Szrj       unordered_map() = default;
14238fd1498Szrj 
14338fd1498Szrj       /**
14438fd1498Szrj        *  @brief  Default constructor creates no elements.
14538fd1498Szrj        *  @param __n  Minimal initial number of buckets.
14638fd1498Szrj        *  @param __hf  A hash functor.
14738fd1498Szrj        *  @param __eql  A key equality functor.
14838fd1498Szrj        *  @param __a  An allocator object.
14938fd1498Szrj        */
15038fd1498Szrj       explicit
15138fd1498Szrj       unordered_map(size_type __n,
15238fd1498Szrj 		    const hasher& __hf = hasher(),
15338fd1498Szrj 		    const key_equal& __eql = key_equal(),
15438fd1498Szrj 		    const allocator_type& __a = allocator_type())
15538fd1498Szrj       : _M_h(__n, __hf, __eql, __a)
15638fd1498Szrj       { }
15738fd1498Szrj 
15838fd1498Szrj       /**
15938fd1498Szrj        *  @brief  Builds an %unordered_map from a range.
16038fd1498Szrj        *  @param  __first  An input iterator.
16138fd1498Szrj        *  @param  __last  An input iterator.
16238fd1498Szrj        *  @param __n  Minimal initial number of buckets.
16338fd1498Szrj        *  @param __hf  A hash functor.
16438fd1498Szrj        *  @param __eql  A key equality functor.
16538fd1498Szrj        *  @param __a  An allocator object.
16638fd1498Szrj        *
16738fd1498Szrj        *  Create an %unordered_map consisting of copies of the elements from
16838fd1498Szrj        *  [__first,__last).  This is linear in N (where N is
16938fd1498Szrj        *  distance(__first,__last)).
17038fd1498Szrj        */
17138fd1498Szrj       template<typename _InputIterator>
17238fd1498Szrj 	unordered_map(_InputIterator __first, _InputIterator __last,
17338fd1498Szrj 		      size_type __n = 0,
17438fd1498Szrj 		      const hasher& __hf = hasher(),
17538fd1498Szrj 		      const key_equal& __eql = key_equal(),
17638fd1498Szrj 		      const allocator_type& __a = allocator_type())
17738fd1498Szrj 	: _M_h(__first, __last, __n, __hf, __eql, __a)
17838fd1498Szrj 	{ }
17938fd1498Szrj 
18038fd1498Szrj       /// Copy constructor.
18138fd1498Szrj       unordered_map(const unordered_map&) = default;
18238fd1498Szrj 
18338fd1498Szrj       /// Move constructor.
18438fd1498Szrj       unordered_map(unordered_map&&) = default;
18538fd1498Szrj 
18638fd1498Szrj       /**
18738fd1498Szrj        *  @brief Creates an %unordered_map with no elements.
18838fd1498Szrj        *  @param __a An allocator object.
18938fd1498Szrj        */
19038fd1498Szrj       explicit
19138fd1498Szrj       unordered_map(const allocator_type& __a)
19238fd1498Szrj 	: _M_h(__a)
19338fd1498Szrj       { }
19438fd1498Szrj 
19538fd1498Szrj       /*
19638fd1498Szrj        *  @brief Copy constructor with allocator argument.
19738fd1498Szrj        * @param  __uset  Input %unordered_map to copy.
19838fd1498Szrj        * @param  __a  An allocator object.
19938fd1498Szrj        */
20038fd1498Szrj       unordered_map(const unordered_map& __umap,
20138fd1498Szrj 		    const allocator_type& __a)
20238fd1498Szrj       : _M_h(__umap._M_h, __a)
20338fd1498Szrj       { }
20438fd1498Szrj 
20538fd1498Szrj       /*
20638fd1498Szrj        *  @brief  Move constructor with allocator argument.
20738fd1498Szrj        *  @param  __uset Input %unordered_map to move.
20838fd1498Szrj        *  @param  __a    An allocator object.
20938fd1498Szrj        */
21038fd1498Szrj       unordered_map(unordered_map&& __umap,
21138fd1498Szrj 		    const allocator_type& __a)
21238fd1498Szrj       : _M_h(std::move(__umap._M_h), __a)
21338fd1498Szrj       { }
21438fd1498Szrj 
21538fd1498Szrj       /**
21638fd1498Szrj        *  @brief  Builds an %unordered_map from an initializer_list.
21738fd1498Szrj        *  @param  __l  An initializer_list.
21838fd1498Szrj        *  @param __n  Minimal initial number of buckets.
21938fd1498Szrj        *  @param __hf  A hash functor.
22038fd1498Szrj        *  @param __eql  A key equality functor.
22138fd1498Szrj        *  @param  __a  An allocator object.
22238fd1498Szrj        *
22338fd1498Szrj        *  Create an %unordered_map consisting of copies of the elements in the
22438fd1498Szrj        *  list. This is linear in N (where N is @a __l.size()).
22538fd1498Szrj        */
22638fd1498Szrj       unordered_map(initializer_list<value_type> __l,
22738fd1498Szrj 		    size_type __n = 0,
22838fd1498Szrj 		    const hasher& __hf = hasher(),
22938fd1498Szrj 		    const key_equal& __eql = key_equal(),
23038fd1498Szrj 		    const allocator_type& __a = allocator_type())
23138fd1498Szrj       : _M_h(__l, __n, __hf, __eql, __a)
23238fd1498Szrj       { }
23338fd1498Szrj 
23438fd1498Szrj       unordered_map(size_type __n, const allocator_type& __a)
23538fd1498Szrj       : unordered_map(__n, hasher(), key_equal(), __a)
23638fd1498Szrj       { }
23738fd1498Szrj 
23838fd1498Szrj       unordered_map(size_type __n, const hasher& __hf,
23938fd1498Szrj 		    const allocator_type& __a)
24038fd1498Szrj       : unordered_map(__n, __hf, key_equal(), __a)
24138fd1498Szrj       { }
24238fd1498Szrj 
24338fd1498Szrj       template<typename _InputIterator>
24438fd1498Szrj 	unordered_map(_InputIterator __first, _InputIterator __last,
24538fd1498Szrj 		      size_type __n,
24638fd1498Szrj 		      const allocator_type& __a)
24738fd1498Szrj 	: unordered_map(__first, __last, __n, hasher(), key_equal(), __a)
24838fd1498Szrj 	{ }
24938fd1498Szrj 
25038fd1498Szrj       template<typename _InputIterator>
25138fd1498Szrj 	unordered_map(_InputIterator __first, _InputIterator __last,
25238fd1498Szrj 		      size_type __n, const hasher& __hf,
25338fd1498Szrj 		      const allocator_type& __a)
25438fd1498Szrj 	  : unordered_map(__first, __last, __n, __hf, key_equal(), __a)
25538fd1498Szrj 	{ }
25638fd1498Szrj 
25738fd1498Szrj       unordered_map(initializer_list<value_type> __l,
25838fd1498Szrj 		    size_type __n,
25938fd1498Szrj 		    const allocator_type& __a)
26038fd1498Szrj       : unordered_map(__l, __n, hasher(), key_equal(), __a)
26138fd1498Szrj       { }
26238fd1498Szrj 
26338fd1498Szrj       unordered_map(initializer_list<value_type> __l,
26438fd1498Szrj 		    size_type __n, const hasher& __hf,
26538fd1498Szrj 		    const allocator_type& __a)
26638fd1498Szrj       : unordered_map(__l, __n, __hf, key_equal(), __a)
26738fd1498Szrj       { }
26838fd1498Szrj 
26938fd1498Szrj       /// Copy assignment operator.
27038fd1498Szrj       unordered_map&
27138fd1498Szrj       operator=(const unordered_map&) = default;
27238fd1498Szrj 
27338fd1498Szrj       /// Move assignment operator.
27438fd1498Szrj       unordered_map&
27538fd1498Szrj       operator=(unordered_map&&) = default;
27638fd1498Szrj 
27738fd1498Szrj       /**
27838fd1498Szrj        *  @brief  %Unordered_map list assignment operator.
27938fd1498Szrj        *  @param  __l  An initializer_list.
28038fd1498Szrj        *
28138fd1498Szrj        *  This function fills an %unordered_map with copies of the elements in
28238fd1498Szrj        *  the initializer list @a __l.
28338fd1498Szrj        *
28438fd1498Szrj        *  Note that the assignment completely changes the %unordered_map and
28538fd1498Szrj        *  that the resulting %unordered_map's size is the same as the number
28638fd1498Szrj        *  of elements assigned.
28738fd1498Szrj        */
28838fd1498Szrj       unordered_map&
28938fd1498Szrj       operator=(initializer_list<value_type> __l)
29038fd1498Szrj       {
29138fd1498Szrj 	_M_h = __l;
29238fd1498Szrj 	return *this;
29338fd1498Szrj       }
29438fd1498Szrj 
29538fd1498Szrj       ///  Returns the allocator object used by the %unordered_map.
29638fd1498Szrj       allocator_type
29738fd1498Szrj       get_allocator() const noexcept
29838fd1498Szrj       { return _M_h.get_allocator(); }
29938fd1498Szrj 
30038fd1498Szrj       // size and capacity:
30138fd1498Szrj 
30238fd1498Szrj       ///  Returns true if the %unordered_map is empty.
30338fd1498Szrj       bool
30438fd1498Szrj       empty() const noexcept
30538fd1498Szrj       { return _M_h.empty(); }
30638fd1498Szrj 
30738fd1498Szrj       ///  Returns the size of the %unordered_map.
30838fd1498Szrj       size_type
30938fd1498Szrj       size() const noexcept
31038fd1498Szrj       { return _M_h.size(); }
31138fd1498Szrj 
31238fd1498Szrj       ///  Returns the maximum size of the %unordered_map.
31338fd1498Szrj       size_type
31438fd1498Szrj       max_size() const noexcept
31538fd1498Szrj       { return _M_h.max_size(); }
31638fd1498Szrj 
31738fd1498Szrj       // iterators.
31838fd1498Szrj 
31938fd1498Szrj       /**
32038fd1498Szrj        *  Returns a read/write iterator that points to the first element in the
32138fd1498Szrj        *  %unordered_map.
32238fd1498Szrj        */
32338fd1498Szrj       iterator
32438fd1498Szrj       begin() noexcept
32538fd1498Szrj       { return _M_h.begin(); }
32638fd1498Szrj 
32738fd1498Szrj       //@{
32838fd1498Szrj       /**
32938fd1498Szrj        *  Returns a read-only (constant) iterator that points to the first
33038fd1498Szrj        *  element in the %unordered_map.
33138fd1498Szrj        */
33238fd1498Szrj       const_iterator
33338fd1498Szrj       begin() const noexcept
33438fd1498Szrj       { return _M_h.begin(); }
33538fd1498Szrj 
33638fd1498Szrj       const_iterator
33738fd1498Szrj       cbegin() const noexcept
33838fd1498Szrj       { return _M_h.begin(); }
33938fd1498Szrj       //@}
34038fd1498Szrj 
34138fd1498Szrj       /**
34238fd1498Szrj        *  Returns a read/write iterator that points one past the last element in
34338fd1498Szrj        *  the %unordered_map.
34438fd1498Szrj        */
34538fd1498Szrj       iterator
34638fd1498Szrj       end() noexcept
34738fd1498Szrj       { return _M_h.end(); }
34838fd1498Szrj 
34938fd1498Szrj       //@{
35038fd1498Szrj       /**
35138fd1498Szrj        *  Returns a read-only (constant) iterator that points one past the last
35238fd1498Szrj        *  element in the %unordered_map.
35338fd1498Szrj        */
35438fd1498Szrj       const_iterator
35538fd1498Szrj       end() const noexcept
35638fd1498Szrj       { return _M_h.end(); }
35738fd1498Szrj 
35838fd1498Szrj       const_iterator
35938fd1498Szrj       cend() const noexcept
36038fd1498Szrj       { return _M_h.end(); }
36138fd1498Szrj       //@}
36238fd1498Szrj 
36338fd1498Szrj       // modifiers.
36438fd1498Szrj 
36538fd1498Szrj       /**
36638fd1498Szrj        *  @brief Attempts to build and insert a std::pair into the
36738fd1498Szrj        *  %unordered_map.
36838fd1498Szrj        *
36938fd1498Szrj        *  @param __args  Arguments used to generate a new pair instance (see
37038fd1498Szrj        *	        std::piecewise_contruct for passing arguments to each
37138fd1498Szrj        *	        part of the pair constructor).
37238fd1498Szrj        *
37338fd1498Szrj        *  @return  A pair, of which the first element is an iterator that points
37438fd1498Szrj        *           to the possibly inserted pair, and the second is a bool that
37538fd1498Szrj        *           is true if the pair was actually inserted.
37638fd1498Szrj        *
37738fd1498Szrj        *  This function attempts to build and insert a (key, value) %pair into
37838fd1498Szrj        *  the %unordered_map.
37938fd1498Szrj        *  An %unordered_map relies on unique keys and thus a %pair is only
38038fd1498Szrj        *  inserted if its first element (the key) is not already present in the
38138fd1498Szrj        *  %unordered_map.
38238fd1498Szrj        *
38338fd1498Szrj        *  Insertion requires amortized constant time.
38438fd1498Szrj        */
38538fd1498Szrj       template<typename... _Args>
38638fd1498Szrj 	std::pair<iterator, bool>
38738fd1498Szrj 	emplace(_Args&&... __args)
38838fd1498Szrj 	{ return _M_h.emplace(std::forward<_Args>(__args)...); }
38938fd1498Szrj 
39038fd1498Szrj       /**
39138fd1498Szrj        *  @brief Attempts to build and insert a std::pair into the
39238fd1498Szrj        *  %unordered_map.
39338fd1498Szrj        *
39438fd1498Szrj        *  @param  __pos  An iterator that serves as a hint as to where the pair
39538fd1498Szrj        *                should be inserted.
39638fd1498Szrj        *  @param  __args  Arguments used to generate a new pair instance (see
39738fd1498Szrj        *	         std::piecewise_contruct for passing arguments to each
39838fd1498Szrj        *	         part of the pair constructor).
39938fd1498Szrj        *  @return An iterator that points to the element with key of the
40038fd1498Szrj        *          std::pair built from @a __args (may or may not be that
40138fd1498Szrj        *          std::pair).
40238fd1498Szrj        *
40338fd1498Szrj        *  This function is not concerned about whether the insertion took place,
40438fd1498Szrj        *  and thus does not return a boolean like the single-argument emplace()
40538fd1498Szrj        *  does.
40638fd1498Szrj        *  Note that the first parameter is only a hint and can potentially
40738fd1498Szrj        *  improve the performance of the insertion process. A bad hint would
40838fd1498Szrj        *  cause no gains in efficiency.
40938fd1498Szrj        *
41038fd1498Szrj        *  See
41138fd1498Szrj        *  https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints
41238fd1498Szrj        *  for more on @a hinting.
41338fd1498Szrj        *
41438fd1498Szrj        *  Insertion requires amortized constant time.
41538fd1498Szrj        */
41638fd1498Szrj       template<typename... _Args>
41738fd1498Szrj 	iterator
41838fd1498Szrj 	emplace_hint(const_iterator __pos, _Args&&... __args)
41938fd1498Szrj 	{ return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); }
42038fd1498Szrj 
42138fd1498Szrj #if __cplusplus > 201402L
42238fd1498Szrj       /// Extract a node.
42338fd1498Szrj       node_type
42438fd1498Szrj       extract(const_iterator __pos)
42538fd1498Szrj       {
42638fd1498Szrj 	__glibcxx_assert(__pos != end());
42738fd1498Szrj 	return _M_h.extract(__pos);
42838fd1498Szrj       }
42938fd1498Szrj 
43038fd1498Szrj       /// Extract a node.
43138fd1498Szrj       node_type
43238fd1498Szrj       extract(const key_type& __key)
43338fd1498Szrj       { return _M_h.extract(__key); }
43438fd1498Szrj 
43538fd1498Szrj       /// Re-insert an extracted node.
43638fd1498Szrj       insert_return_type
43738fd1498Szrj       insert(node_type&& __nh)
43838fd1498Szrj       { return _M_h._M_reinsert_node(std::move(__nh)); }
43938fd1498Szrj 
44038fd1498Szrj       /// Re-insert an extracted node.
44138fd1498Szrj       iterator
44238fd1498Szrj       insert(const_iterator, node_type&& __nh)
44338fd1498Szrj       { return _M_h._M_reinsert_node(std::move(__nh)).position; }
44438fd1498Szrj 
44538fd1498Szrj #define __cpp_lib_unordered_map_try_emplace 201411
44638fd1498Szrj       /**
44738fd1498Szrj        *  @brief Attempts to build and insert a std::pair into the
44838fd1498Szrj        *  %unordered_map.
44938fd1498Szrj        *
45038fd1498Szrj        *  @param __k    Key to use for finding a possibly existing pair in
45138fd1498Szrj        *                the unordered_map.
45238fd1498Szrj        *  @param __args  Arguments used to generate the .second for a
45338fd1498Szrj        *                new pair instance.
45438fd1498Szrj        *
45538fd1498Szrj        *  @return  A pair, of which the first element is an iterator that points
45638fd1498Szrj        *           to the possibly inserted pair, and the second is a bool that
45738fd1498Szrj        *           is true if the pair was actually inserted.
45838fd1498Szrj        *
45938fd1498Szrj        *  This function attempts to build and insert a (key, value) %pair into
46038fd1498Szrj        *  the %unordered_map.
46138fd1498Szrj        *  An %unordered_map relies on unique keys and thus a %pair is only
46238fd1498Szrj        *  inserted if its first element (the key) is not already present in the
46338fd1498Szrj        *  %unordered_map.
46438fd1498Szrj        *  If a %pair is not inserted, this function has no effect.
46538fd1498Szrj        *
46638fd1498Szrj        *  Insertion requires amortized constant time.
46738fd1498Szrj        */
46838fd1498Szrj       template <typename... _Args>
46938fd1498Szrj         pair<iterator, bool>
47038fd1498Szrj         try_emplace(const key_type& __k, _Args&&... __args)
47138fd1498Szrj         {
47238fd1498Szrj           iterator __i = find(__k);
47338fd1498Szrj           if (__i == end())
47438fd1498Szrj             {
47538fd1498Szrj               __i = emplace(std::piecewise_construct,
47638fd1498Szrj                             std::forward_as_tuple(__k),
47738fd1498Szrj                             std::forward_as_tuple(
47838fd1498Szrj                               std::forward<_Args>(__args)...))
47938fd1498Szrj                 .first;
48038fd1498Szrj               return {__i, true};
48138fd1498Szrj             }
48238fd1498Szrj           return {__i, false};
48338fd1498Szrj         }
48438fd1498Szrj 
48538fd1498Szrj       // move-capable overload
48638fd1498Szrj       template <typename... _Args>
48738fd1498Szrj         pair<iterator, bool>
48838fd1498Szrj         try_emplace(key_type&& __k, _Args&&... __args)
48938fd1498Szrj         {
49038fd1498Szrj           iterator __i = find(__k);
49138fd1498Szrj           if (__i == end())
49238fd1498Szrj             {
49338fd1498Szrj               __i = emplace(std::piecewise_construct,
49438fd1498Szrj                             std::forward_as_tuple(std::move(__k)),
49538fd1498Szrj                             std::forward_as_tuple(
49638fd1498Szrj                               std::forward<_Args>(__args)...))
49738fd1498Szrj                 .first;
49838fd1498Szrj               return {__i, true};
49938fd1498Szrj             }
50038fd1498Szrj           return {__i, false};
50138fd1498Szrj         }
50238fd1498Szrj 
50338fd1498Szrj       /**
50438fd1498Szrj        *  @brief Attempts to build and insert a std::pair into the
50538fd1498Szrj        *  %unordered_map.
50638fd1498Szrj        *
50738fd1498Szrj        *  @param  __hint  An iterator that serves as a hint as to where the pair
50838fd1498Szrj        *                should be inserted.
50938fd1498Szrj        *  @param __k    Key to use for finding a possibly existing pair in
51038fd1498Szrj        *                the unordered_map.
51138fd1498Szrj        *  @param __args  Arguments used to generate the .second for a
51238fd1498Szrj        *                new pair instance.
51338fd1498Szrj        *  @return An iterator that points to the element with key of the
51438fd1498Szrj        *          std::pair built from @a __args (may or may not be that
51538fd1498Szrj        *          std::pair).
51638fd1498Szrj        *
51738fd1498Szrj        *  This function is not concerned about whether the insertion took place,
51838fd1498Szrj        *  and thus does not return a boolean like the single-argument emplace()
51938fd1498Szrj        *  does. However, if insertion did not take place,
52038fd1498Szrj        *  this function has no effect.
52138fd1498Szrj        *  Note that the first parameter is only a hint and can potentially
52238fd1498Szrj        *  improve the performance of the insertion process. A bad hint would
52338fd1498Szrj        *  cause no gains in efficiency.
52438fd1498Szrj        *
52538fd1498Szrj        *  See
52638fd1498Szrj        *  https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints
52738fd1498Szrj        *  for more on @a hinting.
52838fd1498Szrj        *
52938fd1498Szrj        *  Insertion requires amortized constant time.
53038fd1498Szrj        */
53138fd1498Szrj       template <typename... _Args>
53238fd1498Szrj         iterator
53338fd1498Szrj         try_emplace(const_iterator __hint, const key_type& __k,
53438fd1498Szrj                     _Args&&... __args)
53538fd1498Szrj         {
53638fd1498Szrj           iterator __i = find(__k);
53738fd1498Szrj           if (__i == end())
53838fd1498Szrj             __i = emplace_hint(__hint, std::piecewise_construct,
53938fd1498Szrj                                std::forward_as_tuple(__k),
54038fd1498Szrj                                std::forward_as_tuple(
54138fd1498Szrj                                  std::forward<_Args>(__args)...));
54238fd1498Szrj           return __i;
54338fd1498Szrj         }
54438fd1498Szrj 
54538fd1498Szrj       // move-capable overload
54638fd1498Szrj       template <typename... _Args>
54738fd1498Szrj         iterator
54838fd1498Szrj         try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args)
54938fd1498Szrj         {
55038fd1498Szrj           iterator __i = find(__k);
55138fd1498Szrj           if (__i == end())
55238fd1498Szrj             __i = emplace_hint(__hint, std::piecewise_construct,
55338fd1498Szrj                                std::forward_as_tuple(std::move(__k)),
55438fd1498Szrj                                std::forward_as_tuple(
55538fd1498Szrj                                  std::forward<_Args>(__args)...));
55638fd1498Szrj           return __i;
55738fd1498Szrj         }
55838fd1498Szrj #endif // C++17
55938fd1498Szrj 
56038fd1498Szrj       //@{
56138fd1498Szrj       /**
56238fd1498Szrj        *  @brief Attempts to insert a std::pair into the %unordered_map.
56338fd1498Szrj 
56438fd1498Szrj        *  @param __x Pair to be inserted (see std::make_pair for easy
56538fd1498Szrj        *	     creation of pairs).
56638fd1498Szrj        *
56738fd1498Szrj        *  @return  A pair, of which the first element is an iterator that
56838fd1498Szrj        *           points to the possibly inserted pair, and the second is
56938fd1498Szrj        *           a bool that is true if the pair was actually inserted.
57038fd1498Szrj        *
57138fd1498Szrj        *  This function attempts to insert a (key, value) %pair into the
57238fd1498Szrj        *  %unordered_map. An %unordered_map relies on unique keys and thus a
57338fd1498Szrj        *  %pair is only inserted if its first element (the key) is not already
57438fd1498Szrj        *  present in the %unordered_map.
57538fd1498Szrj        *
57638fd1498Szrj        *  Insertion requires amortized constant time.
57738fd1498Szrj        */
57838fd1498Szrj       std::pair<iterator, bool>
57938fd1498Szrj       insert(const value_type& __x)
58038fd1498Szrj       { return _M_h.insert(__x); }
58138fd1498Szrj 
58238fd1498Szrj       // _GLIBCXX_RESOLVE_LIB_DEFECTS
58338fd1498Szrj       // 2354. Unnecessary copying when inserting into maps with braced-init
58438fd1498Szrj       std::pair<iterator, bool>
58538fd1498Szrj       insert(value_type&& __x)
58638fd1498Szrj       { return _M_h.insert(std::move(__x)); }
58738fd1498Szrj 
588*58e805e6Szrj       template<typename _Pair>
589*58e805e6Szrj 	__enable_if_t<is_constructible<value_type, _Pair&&>::value,
590*58e805e6Szrj 		      pair<iterator, bool>>
59138fd1498Szrj 	insert(_Pair&& __x)
592*58e805e6Szrj         { return _M_h.emplace(std::forward<_Pair>(__x)); }
59338fd1498Szrj       //@}
59438fd1498Szrj 
59538fd1498Szrj       //@{
59638fd1498Szrj       /**
59738fd1498Szrj        *  @brief Attempts to insert a std::pair into the %unordered_map.
59838fd1498Szrj        *  @param  __hint  An iterator that serves as a hint as to where the
59938fd1498Szrj        *                 pair should be inserted.
60038fd1498Szrj        *  @param  __x  Pair to be inserted (see std::make_pair for easy creation
60138fd1498Szrj        *               of pairs).
60238fd1498Szrj        *  @return An iterator that points to the element with key of
60338fd1498Szrj        *           @a __x (may or may not be the %pair passed in).
60438fd1498Szrj        *
60538fd1498Szrj        *  This function is not concerned about whether the insertion took place,
60638fd1498Szrj        *  and thus does not return a boolean like the single-argument insert()
60738fd1498Szrj        *  does.  Note that the first parameter is only a hint and can
60838fd1498Szrj        *  potentially improve the performance of the insertion process.  A bad
60938fd1498Szrj        *  hint would cause no gains in efficiency.
61038fd1498Szrj        *
61138fd1498Szrj        *  See
61238fd1498Szrj        *  https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints
61338fd1498Szrj        *  for more on @a hinting.
61438fd1498Szrj        *
61538fd1498Szrj        *  Insertion requires amortized constant time.
61638fd1498Szrj        */
61738fd1498Szrj       iterator
61838fd1498Szrj       insert(const_iterator __hint, const value_type& __x)
61938fd1498Szrj       { return _M_h.insert(__hint, __x); }
62038fd1498Szrj 
62138fd1498Szrj       // _GLIBCXX_RESOLVE_LIB_DEFECTS
62238fd1498Szrj       // 2354. Unnecessary copying when inserting into maps with braced-init
62338fd1498Szrj       iterator
62438fd1498Szrj       insert(const_iterator __hint, value_type&& __x)
62538fd1498Szrj       { return _M_h.insert(__hint, std::move(__x)); }
62638fd1498Szrj 
627*58e805e6Szrj       template<typename _Pair>
628*58e805e6Szrj 	__enable_if_t<is_constructible<value_type, _Pair&&>::value, iterator>
62938fd1498Szrj 	insert(const_iterator __hint, _Pair&& __x)
630*58e805e6Szrj 	{ return _M_h.emplace_hint(__hint, std::forward<_Pair>(__x)); }
63138fd1498Szrj       //@}
63238fd1498Szrj 
63338fd1498Szrj       /**
63438fd1498Szrj        *  @brief A template function that attempts to insert a range of
63538fd1498Szrj        *  elements.
63638fd1498Szrj        *  @param  __first  Iterator pointing to the start of the range to be
63738fd1498Szrj        *                   inserted.
63838fd1498Szrj        *  @param  __last  Iterator pointing to the end of the range.
63938fd1498Szrj        *
64038fd1498Szrj        *  Complexity similar to that of the range constructor.
64138fd1498Szrj        */
64238fd1498Szrj       template<typename _InputIterator>
64338fd1498Szrj 	void
64438fd1498Szrj 	insert(_InputIterator __first, _InputIterator __last)
64538fd1498Szrj 	{ _M_h.insert(__first, __last); }
64638fd1498Szrj 
64738fd1498Szrj       /**
64838fd1498Szrj        *  @brief Attempts to insert a list of elements into the %unordered_map.
64938fd1498Szrj        *  @param  __l  A std::initializer_list<value_type> of elements
65038fd1498Szrj        *               to be inserted.
65138fd1498Szrj        *
65238fd1498Szrj        *  Complexity similar to that of the range constructor.
65338fd1498Szrj        */
65438fd1498Szrj       void
65538fd1498Szrj       insert(initializer_list<value_type> __l)
65638fd1498Szrj       { _M_h.insert(__l); }
65738fd1498Szrj 
65838fd1498Szrj 
65938fd1498Szrj #if __cplusplus > 201402L
66038fd1498Szrj #define __cpp_lib_unordered_map_insertion 201411
66138fd1498Szrj       /**
66238fd1498Szrj        *  @brief Attempts to insert a std::pair into the %unordered_map.
66338fd1498Szrj        *  @param __k    Key to use for finding a possibly existing pair in
66438fd1498Szrj        *                the map.
66538fd1498Szrj        *  @param __obj  Argument used to generate the .second for a pair
66638fd1498Szrj        *                instance.
66738fd1498Szrj        *
66838fd1498Szrj        *  @return  A pair, of which the first element is an iterator that
66938fd1498Szrj        *           points to the possibly inserted pair, and the second is
67038fd1498Szrj        *           a bool that is true if the pair was actually inserted.
67138fd1498Szrj        *
67238fd1498Szrj        *  This function attempts to insert a (key, value) %pair into the
67338fd1498Szrj        *  %unordered_map. An %unordered_map relies on unique keys and thus a
67438fd1498Szrj        *  %pair is only inserted if its first element (the key) is not already
67538fd1498Szrj        *  present in the %unordered_map.
67638fd1498Szrj        *  If the %pair was already in the %unordered_map, the .second of
67738fd1498Szrj        *  the %pair is assigned from __obj.
67838fd1498Szrj        *
67938fd1498Szrj        *  Insertion requires amortized constant time.
68038fd1498Szrj        */
68138fd1498Szrj       template <typename _Obj>
68238fd1498Szrj         pair<iterator, bool>
68338fd1498Szrj         insert_or_assign(const key_type& __k, _Obj&& __obj)
68438fd1498Szrj         {
68538fd1498Szrj           iterator __i = find(__k);
68638fd1498Szrj           if (__i == end())
68738fd1498Szrj             {
68838fd1498Szrj               __i = emplace(std::piecewise_construct,
68938fd1498Szrj                             std::forward_as_tuple(__k),
69038fd1498Szrj                             std::forward_as_tuple(std::forward<_Obj>(__obj)))
69138fd1498Szrj                 .first;
69238fd1498Szrj               return {__i, true};
69338fd1498Szrj             }
69438fd1498Szrj           (*__i).second = std::forward<_Obj>(__obj);
69538fd1498Szrj           return {__i, false};
69638fd1498Szrj         }
69738fd1498Szrj 
69838fd1498Szrj       // move-capable overload
69938fd1498Szrj       template <typename _Obj>
70038fd1498Szrj         pair<iterator, bool>
70138fd1498Szrj         insert_or_assign(key_type&& __k, _Obj&& __obj)
70238fd1498Szrj         {
70338fd1498Szrj           iterator __i = find(__k);
70438fd1498Szrj           if (__i == end())
70538fd1498Szrj             {
70638fd1498Szrj               __i = emplace(std::piecewise_construct,
70738fd1498Szrj                             std::forward_as_tuple(std::move(__k)),
70838fd1498Szrj                             std::forward_as_tuple(std::forward<_Obj>(__obj)))
70938fd1498Szrj                 .first;
71038fd1498Szrj               return {__i, true};
71138fd1498Szrj             }
71238fd1498Szrj           (*__i).second = std::forward<_Obj>(__obj);
71338fd1498Szrj           return {__i, false};
71438fd1498Szrj         }
71538fd1498Szrj 
71638fd1498Szrj       /**
71738fd1498Szrj        *  @brief Attempts to insert a std::pair into the %unordered_map.
71838fd1498Szrj        *  @param  __hint  An iterator that serves as a hint as to where the
71938fd1498Szrj        *                  pair should be inserted.
72038fd1498Szrj        *  @param __k    Key to use for finding a possibly existing pair in
72138fd1498Szrj        *                the unordered_map.
72238fd1498Szrj        *  @param __obj  Argument used to generate the .second for a pair
72338fd1498Szrj        *                instance.
72438fd1498Szrj        *  @return An iterator that points to the element with key of
72538fd1498Szrj        *           @a __x (may or may not be the %pair passed in).
72638fd1498Szrj        *
72738fd1498Szrj        *  This function is not concerned about whether the insertion took place,
72838fd1498Szrj        *  and thus does not return a boolean like the single-argument insert()
72938fd1498Szrj        *  does.
73038fd1498Szrj        *  If the %pair was already in the %unordered map, the .second of
73138fd1498Szrj        *  the %pair is assigned from __obj.
73238fd1498Szrj        *  Note that the first parameter is only a hint and can
73338fd1498Szrj        *  potentially improve the performance of the insertion process.  A bad
73438fd1498Szrj        *  hint would cause no gains in efficiency.
73538fd1498Szrj        *
73638fd1498Szrj        *  See
73738fd1498Szrj        *  https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints
73838fd1498Szrj        *  for more on @a hinting.
73938fd1498Szrj        *
74038fd1498Szrj        *  Insertion requires amortized constant time.
74138fd1498Szrj        */
74238fd1498Szrj       template <typename _Obj>
74338fd1498Szrj         iterator
74438fd1498Szrj         insert_or_assign(const_iterator __hint, const key_type& __k,
74538fd1498Szrj                          _Obj&& __obj)
74638fd1498Szrj         {
74738fd1498Szrj           iterator __i = find(__k);
74838fd1498Szrj           if (__i == end())
74938fd1498Szrj             {
75038fd1498Szrj               return emplace_hint(__hint, std::piecewise_construct,
75138fd1498Szrj                                   std::forward_as_tuple(__k),
75238fd1498Szrj                                   std::forward_as_tuple(
75338fd1498Szrj                                     std::forward<_Obj>(__obj)));
75438fd1498Szrj             }
75538fd1498Szrj           (*__i).second = std::forward<_Obj>(__obj);
75638fd1498Szrj           return __i;
75738fd1498Szrj         }
75838fd1498Szrj 
75938fd1498Szrj       // move-capable overload
76038fd1498Szrj       template <typename _Obj>
76138fd1498Szrj         iterator
76238fd1498Szrj         insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj)
76338fd1498Szrj         {
76438fd1498Szrj           iterator __i = find(__k);
76538fd1498Szrj           if (__i == end())
76638fd1498Szrj             {
76738fd1498Szrj               return emplace_hint(__hint, std::piecewise_construct,
76838fd1498Szrj                                   std::forward_as_tuple(std::move(__k)),
76938fd1498Szrj                                   std::forward_as_tuple(
77038fd1498Szrj                                     std::forward<_Obj>(__obj)));
77138fd1498Szrj             }
77238fd1498Szrj           (*__i).second = std::forward<_Obj>(__obj);
77338fd1498Szrj           return __i;
77438fd1498Szrj         }
77538fd1498Szrj #endif
77638fd1498Szrj 
77738fd1498Szrj       //@{
77838fd1498Szrj       /**
77938fd1498Szrj        *  @brief Erases an element from an %unordered_map.
78038fd1498Szrj        *  @param  __position  An iterator pointing to the element to be erased.
78138fd1498Szrj        *  @return An iterator pointing to the element immediately following
78238fd1498Szrj        *          @a __position prior to the element being erased. If no such
78338fd1498Szrj        *          element exists, end() is returned.
78438fd1498Szrj        *
78538fd1498Szrj        *  This function erases an element, pointed to by the given iterator,
78638fd1498Szrj        *  from an %unordered_map.
78738fd1498Szrj        *  Note that this function only erases the element, and that if the
78838fd1498Szrj        *  element is itself a pointer, the pointed-to memory is not touched in
78938fd1498Szrj        *  any way.  Managing the pointer is the user's responsibility.
79038fd1498Szrj        */
79138fd1498Szrj       iterator
79238fd1498Szrj       erase(const_iterator __position)
79338fd1498Szrj       { return _M_h.erase(__position); }
79438fd1498Szrj 
79538fd1498Szrj       // LWG 2059.
79638fd1498Szrj       iterator
79738fd1498Szrj       erase(iterator __position)
79838fd1498Szrj       { return _M_h.erase(__position); }
79938fd1498Szrj       //@}
80038fd1498Szrj 
80138fd1498Szrj       /**
80238fd1498Szrj        *  @brief Erases elements according to the provided key.
80338fd1498Szrj        *  @param  __x  Key of element to be erased.
80438fd1498Szrj        *  @return  The number of elements erased.
80538fd1498Szrj        *
80638fd1498Szrj        *  This function erases all the elements located by the given key from
80738fd1498Szrj        *  an %unordered_map. For an %unordered_map the result of this function
80838fd1498Szrj        *  can only be 0 (not present) or 1 (present).
80938fd1498Szrj        *  Note that this function only erases the element, and that if the
81038fd1498Szrj        *  element is itself a pointer, the pointed-to memory is not touched in
81138fd1498Szrj        *  any way.  Managing the pointer is the user's responsibility.
81238fd1498Szrj        */
81338fd1498Szrj       size_type
81438fd1498Szrj       erase(const key_type& __x)
81538fd1498Szrj       { return _M_h.erase(__x); }
81638fd1498Szrj 
81738fd1498Szrj       /**
81838fd1498Szrj        *  @brief Erases a [__first,__last) range of elements from an
81938fd1498Szrj        *  %unordered_map.
82038fd1498Szrj        *  @param  __first  Iterator pointing to the start of the range to be
82138fd1498Szrj        *                  erased.
82238fd1498Szrj        *  @param __last  Iterator pointing to the end of the range to
82338fd1498Szrj        *                be erased.
82438fd1498Szrj        *  @return The iterator @a __last.
82538fd1498Szrj        *
82638fd1498Szrj        *  This function erases a sequence of elements from an %unordered_map.
82738fd1498Szrj        *  Note that this function only erases the elements, and that if
82838fd1498Szrj        *  the element is itself a pointer, the pointed-to memory is not touched
82938fd1498Szrj        *  in any way.  Managing the pointer is the user's responsibility.
83038fd1498Szrj        */
83138fd1498Szrj       iterator
83238fd1498Szrj       erase(const_iterator __first, const_iterator __last)
83338fd1498Szrj       { return _M_h.erase(__first, __last); }
83438fd1498Szrj 
83538fd1498Szrj       /**
83638fd1498Szrj        *  Erases all elements in an %unordered_map.
83738fd1498Szrj        *  Note that this function only erases the elements, and that if the
83838fd1498Szrj        *  elements themselves are pointers, the pointed-to memory is not touched
83938fd1498Szrj        *  in any way.  Managing the pointer is the user's responsibility.
84038fd1498Szrj        */
84138fd1498Szrj       void
84238fd1498Szrj       clear() noexcept
84338fd1498Szrj       { _M_h.clear(); }
84438fd1498Szrj 
84538fd1498Szrj       /**
84638fd1498Szrj        *  @brief  Swaps data with another %unordered_map.
84738fd1498Szrj        *  @param  __x  An %unordered_map of the same element and allocator
84838fd1498Szrj        *  types.
84938fd1498Szrj        *
85038fd1498Szrj        *  This exchanges the elements between two %unordered_map in constant
85138fd1498Szrj        *  time.
85238fd1498Szrj        *  Note that the global std::swap() function is specialized such that
85338fd1498Szrj        *  std::swap(m1,m2) will feed to this function.
85438fd1498Szrj        */
85538fd1498Szrj       void
85638fd1498Szrj       swap(unordered_map& __x)
85738fd1498Szrj       noexcept( noexcept(_M_h.swap(__x._M_h)) )
85838fd1498Szrj       { _M_h.swap(__x._M_h); }
85938fd1498Szrj 
86038fd1498Szrj #if __cplusplus > 201402L
86138fd1498Szrj       template<typename, typename, typename>
86238fd1498Szrj 	friend class std::_Hash_merge_helper;
86338fd1498Szrj 
86438fd1498Szrj       template<typename _H2, typename _P2>
86538fd1498Szrj 	void
86638fd1498Szrj 	merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>& __source)
86738fd1498Szrj 	{
86838fd1498Szrj 	  using _Merge_helper = _Hash_merge_helper<unordered_map, _H2, _P2>;
86938fd1498Szrj 	  _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source));
87038fd1498Szrj 	}
87138fd1498Szrj 
87238fd1498Szrj       template<typename _H2, typename _P2>
87338fd1498Szrj 	void
87438fd1498Szrj 	merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>&& __source)
87538fd1498Szrj 	{ merge(__source); }
87638fd1498Szrj 
87738fd1498Szrj       template<typename _H2, typename _P2>
87838fd1498Szrj 	void
87938fd1498Szrj 	merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>& __source)
88038fd1498Szrj 	{
88138fd1498Szrj 	  using _Merge_helper = _Hash_merge_helper<unordered_map, _H2, _P2>;
88238fd1498Szrj 	  _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source));
88338fd1498Szrj 	}
88438fd1498Szrj 
88538fd1498Szrj       template<typename _H2, typename _P2>
88638fd1498Szrj 	void
88738fd1498Szrj 	merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>&& __source)
88838fd1498Szrj 	{ merge(__source); }
88938fd1498Szrj #endif // C++17
89038fd1498Szrj 
89138fd1498Szrj       // observers.
89238fd1498Szrj 
89338fd1498Szrj       ///  Returns the hash functor object with which the %unordered_map was
89438fd1498Szrj       ///  constructed.
89538fd1498Szrj       hasher
89638fd1498Szrj       hash_function() const
89738fd1498Szrj       { return _M_h.hash_function(); }
89838fd1498Szrj 
89938fd1498Szrj       ///  Returns the key comparison object with which the %unordered_map was
90038fd1498Szrj       ///  constructed.
90138fd1498Szrj       key_equal
90238fd1498Szrj       key_eq() const
90338fd1498Szrj       { return _M_h.key_eq(); }
90438fd1498Szrj 
90538fd1498Szrj       // lookup.
90638fd1498Szrj 
90738fd1498Szrj       //@{
90838fd1498Szrj       /**
90938fd1498Szrj        *  @brief Tries to locate an element in an %unordered_map.
91038fd1498Szrj        *  @param  __x  Key to be located.
91138fd1498Szrj        *  @return  Iterator pointing to sought-after element, or end() if not
91238fd1498Szrj        *           found.
91338fd1498Szrj        *
91438fd1498Szrj        *  This function takes a key and tries to locate the element with which
91538fd1498Szrj        *  the key matches.  If successful the function returns an iterator
91638fd1498Szrj        *  pointing to the sought after element.  If unsuccessful it returns the
91738fd1498Szrj        *  past-the-end ( @c end() ) iterator.
91838fd1498Szrj        */
91938fd1498Szrj       iterator
92038fd1498Szrj       find(const key_type& __x)
92138fd1498Szrj       { return _M_h.find(__x); }
92238fd1498Szrj 
92338fd1498Szrj       const_iterator
92438fd1498Szrj       find(const key_type& __x) const
92538fd1498Szrj       { return _M_h.find(__x); }
92638fd1498Szrj       //@}
92738fd1498Szrj 
92838fd1498Szrj       /**
92938fd1498Szrj        *  @brief  Finds the number of elements.
93038fd1498Szrj        *  @param  __x  Key to count.
93138fd1498Szrj        *  @return  Number of elements with specified key.
93238fd1498Szrj        *
93338fd1498Szrj        *  This function only makes sense for %unordered_multimap; for
93438fd1498Szrj        *  %unordered_map the result will either be 0 (not present) or 1
93538fd1498Szrj        *  (present).
93638fd1498Szrj        */
93738fd1498Szrj       size_type
93838fd1498Szrj       count(const key_type& __x) const
93938fd1498Szrj       { return _M_h.count(__x); }
94038fd1498Szrj 
94138fd1498Szrj       //@{
94238fd1498Szrj       /**
94338fd1498Szrj        *  @brief Finds a subsequence matching given key.
94438fd1498Szrj        *  @param  __x  Key to be located.
94538fd1498Szrj        *  @return  Pair of iterators that possibly points to the subsequence
94638fd1498Szrj        *           matching given key.
94738fd1498Szrj        *
94838fd1498Szrj        *  This function probably only makes sense for %unordered_multimap.
94938fd1498Szrj        */
95038fd1498Szrj       std::pair<iterator, iterator>
95138fd1498Szrj       equal_range(const key_type& __x)
95238fd1498Szrj       { return _M_h.equal_range(__x); }
95338fd1498Szrj 
95438fd1498Szrj       std::pair<const_iterator, const_iterator>
95538fd1498Szrj       equal_range(const key_type& __x) const
95638fd1498Szrj       { return _M_h.equal_range(__x); }
95738fd1498Szrj       //@}
95838fd1498Szrj 
95938fd1498Szrj       //@{
96038fd1498Szrj       /**
96138fd1498Szrj        *  @brief  Subscript ( @c [] ) access to %unordered_map data.
96238fd1498Szrj        *  @param  __k  The key for which data should be retrieved.
96338fd1498Szrj        *  @return  A reference to the data of the (key,data) %pair.
96438fd1498Szrj        *
96538fd1498Szrj        *  Allows for easy lookup with the subscript ( @c [] )operator.  Returns
96638fd1498Szrj        *  data associated with the key specified in subscript.  If the key does
96738fd1498Szrj        *  not exist, a pair with that key is created using default values, which
96838fd1498Szrj        *  is then returned.
96938fd1498Szrj        *
97038fd1498Szrj        *  Lookup requires constant time.
97138fd1498Szrj        */
97238fd1498Szrj       mapped_type&
97338fd1498Szrj       operator[](const key_type& __k)
97438fd1498Szrj       { return _M_h[__k]; }
97538fd1498Szrj 
97638fd1498Szrj       mapped_type&
97738fd1498Szrj       operator[](key_type&& __k)
97838fd1498Szrj       { return _M_h[std::move(__k)]; }
97938fd1498Szrj       //@}
98038fd1498Szrj 
98138fd1498Szrj       //@{
98238fd1498Szrj       /**
98338fd1498Szrj        *  @brief  Access to %unordered_map data.
98438fd1498Szrj        *  @param  __k  The key for which data should be retrieved.
98538fd1498Szrj        *  @return  A reference to the data whose key is equal to @a __k, if
98638fd1498Szrj        *           such a data is present in the %unordered_map.
98738fd1498Szrj        *  @throw  std::out_of_range  If no such data is present.
98838fd1498Szrj        */
98938fd1498Szrj       mapped_type&
99038fd1498Szrj       at(const key_type& __k)
99138fd1498Szrj       { return _M_h.at(__k); }
99238fd1498Szrj 
99338fd1498Szrj       const mapped_type&
99438fd1498Szrj       at(const key_type& __k) const
99538fd1498Szrj       { return _M_h.at(__k); }
99638fd1498Szrj       //@}
99738fd1498Szrj 
99838fd1498Szrj       // bucket interface.
99938fd1498Szrj 
100038fd1498Szrj       /// Returns the number of buckets of the %unordered_map.
100138fd1498Szrj       size_type
100238fd1498Szrj       bucket_count() const noexcept
100338fd1498Szrj       { return _M_h.bucket_count(); }
100438fd1498Szrj 
100538fd1498Szrj       /// Returns the maximum number of buckets of the %unordered_map.
100638fd1498Szrj       size_type
100738fd1498Szrj       max_bucket_count() const noexcept
100838fd1498Szrj       { return _M_h.max_bucket_count(); }
100938fd1498Szrj 
101038fd1498Szrj       /*
101138fd1498Szrj        * @brief  Returns the number of elements in a given bucket.
101238fd1498Szrj        * @param  __n  A bucket index.
101338fd1498Szrj        * @return  The number of elements in the bucket.
101438fd1498Szrj        */
101538fd1498Szrj       size_type
101638fd1498Szrj       bucket_size(size_type __n) const
101738fd1498Szrj       { return _M_h.bucket_size(__n); }
101838fd1498Szrj 
101938fd1498Szrj       /*
102038fd1498Szrj        * @brief  Returns the bucket index of a given element.
102138fd1498Szrj        * @param  __key  A key instance.
102238fd1498Szrj        * @return  The key bucket index.
102338fd1498Szrj        */
102438fd1498Szrj       size_type
102538fd1498Szrj       bucket(const key_type& __key) const
102638fd1498Szrj       { return _M_h.bucket(__key); }
102738fd1498Szrj 
102838fd1498Szrj       /**
102938fd1498Szrj        *  @brief  Returns a read/write iterator pointing to the first bucket
103038fd1498Szrj        *         element.
103138fd1498Szrj        *  @param  __n The bucket index.
103238fd1498Szrj        *  @return  A read/write local iterator.
103338fd1498Szrj        */
103438fd1498Szrj       local_iterator
103538fd1498Szrj       begin(size_type __n)
103638fd1498Szrj       { return _M_h.begin(__n); }
103738fd1498Szrj 
103838fd1498Szrj       //@{
103938fd1498Szrj       /**
104038fd1498Szrj        *  @brief  Returns a read-only (constant) iterator pointing to the first
104138fd1498Szrj        *         bucket element.
104238fd1498Szrj        *  @param  __n The bucket index.
104338fd1498Szrj        *  @return  A read-only local iterator.
104438fd1498Szrj        */
104538fd1498Szrj       const_local_iterator
104638fd1498Szrj       begin(size_type __n) const
104738fd1498Szrj       { return _M_h.begin(__n); }
104838fd1498Szrj 
104938fd1498Szrj       const_local_iterator
105038fd1498Szrj       cbegin(size_type __n) const
105138fd1498Szrj       { return _M_h.cbegin(__n); }
105238fd1498Szrj       //@}
105338fd1498Szrj 
105438fd1498Szrj       /**
105538fd1498Szrj        *  @brief  Returns a read/write iterator pointing to one past the last
105638fd1498Szrj        *         bucket elements.
105738fd1498Szrj        *  @param  __n The bucket index.
105838fd1498Szrj        *  @return  A read/write local iterator.
105938fd1498Szrj        */
106038fd1498Szrj       local_iterator
106138fd1498Szrj       end(size_type __n)
106238fd1498Szrj       { return _M_h.end(__n); }
106338fd1498Szrj 
106438fd1498Szrj       //@{
106538fd1498Szrj       /**
106638fd1498Szrj        *  @brief  Returns a read-only (constant) iterator pointing to one past
106738fd1498Szrj        *         the last bucket elements.
106838fd1498Szrj        *  @param  __n The bucket index.
106938fd1498Szrj        *  @return  A read-only local iterator.
107038fd1498Szrj        */
107138fd1498Szrj       const_local_iterator
107238fd1498Szrj       end(size_type __n) const
107338fd1498Szrj       { return _M_h.end(__n); }
107438fd1498Szrj 
107538fd1498Szrj       const_local_iterator
107638fd1498Szrj       cend(size_type __n) const
107738fd1498Szrj       { return _M_h.cend(__n); }
107838fd1498Szrj       //@}
107938fd1498Szrj 
108038fd1498Szrj       // hash policy.
108138fd1498Szrj 
108238fd1498Szrj       /// Returns the average number of elements per bucket.
108338fd1498Szrj       float
108438fd1498Szrj       load_factor() const noexcept
108538fd1498Szrj       { return _M_h.load_factor(); }
108638fd1498Szrj 
108738fd1498Szrj       /// Returns a positive number that the %unordered_map tries to keep the
108838fd1498Szrj       /// load factor less than or equal to.
108938fd1498Szrj       float
109038fd1498Szrj       max_load_factor() const noexcept
109138fd1498Szrj       { return _M_h.max_load_factor(); }
109238fd1498Szrj 
109338fd1498Szrj       /**
109438fd1498Szrj        *  @brief  Change the %unordered_map maximum load factor.
109538fd1498Szrj        *  @param  __z The new maximum load factor.
109638fd1498Szrj        */
109738fd1498Szrj       void
109838fd1498Szrj       max_load_factor(float __z)
109938fd1498Szrj       { _M_h.max_load_factor(__z); }
110038fd1498Szrj 
110138fd1498Szrj       /**
110238fd1498Szrj        *  @brief  May rehash the %unordered_map.
110338fd1498Szrj        *  @param  __n The new number of buckets.
110438fd1498Szrj        *
110538fd1498Szrj        *  Rehash will occur only if the new number of buckets respect the
110638fd1498Szrj        *  %unordered_map maximum load factor.
110738fd1498Szrj        */
110838fd1498Szrj       void
110938fd1498Szrj       rehash(size_type __n)
111038fd1498Szrj       { _M_h.rehash(__n); }
111138fd1498Szrj 
111238fd1498Szrj       /**
111338fd1498Szrj        *  @brief  Prepare the %unordered_map for a specified number of
111438fd1498Szrj        *          elements.
111538fd1498Szrj        *  @param  __n Number of elements required.
111638fd1498Szrj        *
111738fd1498Szrj        *  Same as rehash(ceil(n / max_load_factor())).
111838fd1498Szrj        */
111938fd1498Szrj       void
112038fd1498Szrj       reserve(size_type __n)
112138fd1498Szrj       { _M_h.reserve(__n); }
112238fd1498Szrj 
112338fd1498Szrj       template<typename _Key1, typename _Tp1, typename _Hash1, typename _Pred1,
112438fd1498Szrj 	       typename _Alloc1>
112538fd1498Szrj         friend bool
112638fd1498Szrj 	operator==(const unordered_map<_Key1, _Tp1, _Hash1, _Pred1, _Alloc1>&,
112738fd1498Szrj 		   const unordered_map<_Key1, _Tp1, _Hash1, _Pred1, _Alloc1>&);
112838fd1498Szrj     };
112938fd1498Szrj 
113038fd1498Szrj #if __cpp_deduction_guides >= 201606
113138fd1498Szrj 
113238fd1498Szrj   template<typename _InputIterator,
113338fd1498Szrj 	   typename _Hash = hash<__iter_key_t<_InputIterator>>,
113438fd1498Szrj 	   typename _Pred = equal_to<__iter_key_t<_InputIterator>>,
113538fd1498Szrj 	   typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>,
113638fd1498Szrj 	   typename = _RequireInputIter<_InputIterator>,
113738fd1498Szrj 	   typename = _RequireAllocator<_Allocator>>
113838fd1498Szrj     unordered_map(_InputIterator, _InputIterator,
113938fd1498Szrj 		  typename unordered_map<int, int>::size_type = {},
114038fd1498Szrj 		  _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator())
114138fd1498Szrj     -> unordered_map<__iter_key_t<_InputIterator>,
114238fd1498Szrj 		     __iter_val_t<_InputIterator>,
114338fd1498Szrj 		     _Hash, _Pred, _Allocator>;
114438fd1498Szrj 
114538fd1498Szrj   template<typename _Key, typename _Tp, typename _Hash = hash<_Key>,
114638fd1498Szrj 	   typename _Pred = equal_to<_Key>,
114738fd1498Szrj 	   typename _Allocator = allocator<pair<const _Key, _Tp>>,
114838fd1498Szrj 	   typename = _RequireAllocator<_Allocator>>
114938fd1498Szrj     unordered_map(initializer_list<pair<_Key, _Tp>>,
115038fd1498Szrj 		  typename unordered_map<int, int>::size_type = {},
115138fd1498Szrj 		  _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator())
115238fd1498Szrj     -> unordered_map<_Key, _Tp, _Hash, _Pred, _Allocator>;
115338fd1498Szrj 
115438fd1498Szrj   template<typename _InputIterator, typename _Allocator,
115538fd1498Szrj 	   typename = _RequireInputIter<_InputIterator>,
115638fd1498Szrj 	   typename = _RequireAllocator<_Allocator>>
115738fd1498Szrj     unordered_map(_InputIterator, _InputIterator,
115838fd1498Szrj 		  typename unordered_map<int, int>::size_type, _Allocator)
115938fd1498Szrj     -> unordered_map<__iter_key_t<_InputIterator>,
116038fd1498Szrj 		     __iter_val_t<_InputIterator>,
116138fd1498Szrj 		     hash<__iter_key_t<_InputIterator>>,
116238fd1498Szrj 		     equal_to<__iter_key_t<_InputIterator>>,
116338fd1498Szrj 		     _Allocator>;
116438fd1498Szrj 
116538fd1498Szrj   template<typename _InputIterator, typename _Allocator,
116638fd1498Szrj 	   typename = _RequireInputIter<_InputIterator>,
116738fd1498Szrj 	   typename = _RequireAllocator<_Allocator>>
116838fd1498Szrj     unordered_map(_InputIterator, _InputIterator, _Allocator)
116938fd1498Szrj     -> unordered_map<__iter_key_t<_InputIterator>,
117038fd1498Szrj 		     __iter_val_t<_InputIterator>,
117138fd1498Szrj 		     hash<__iter_key_t<_InputIterator>>,
117238fd1498Szrj 		     equal_to<__iter_key_t<_InputIterator>>,
117338fd1498Szrj 		     _Allocator>;
117438fd1498Szrj 
117538fd1498Szrj   template<typename _InputIterator, typename _Hash, typename _Allocator,
117638fd1498Szrj 	   typename = _RequireInputIter<_InputIterator>,
117738fd1498Szrj 	   typename = _RequireAllocator<_Allocator>>
117838fd1498Szrj     unordered_map(_InputIterator, _InputIterator,
117938fd1498Szrj 		  typename unordered_map<int, int>::size_type,
118038fd1498Szrj 		  _Hash, _Allocator)
118138fd1498Szrj     -> unordered_map<__iter_key_t<_InputIterator>,
118238fd1498Szrj 		     __iter_val_t<_InputIterator>, _Hash,
118338fd1498Szrj 		     equal_to<__iter_key_t<_InputIterator>>, _Allocator>;
118438fd1498Szrj 
118538fd1498Szrj   template<typename _Key, typename _Tp, typename _Allocator,
118638fd1498Szrj 	   typename = _RequireAllocator<_Allocator>>
118738fd1498Szrj     unordered_map(initializer_list<pair<_Key, _Tp>>,
118838fd1498Szrj 		  typename unordered_map<int, int>::size_type,
118938fd1498Szrj 		  _Allocator)
119038fd1498Szrj     -> unordered_map<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>;
119138fd1498Szrj 
119238fd1498Szrj   template<typename _Key, typename _Tp, typename _Allocator,
119338fd1498Szrj 	   typename = _RequireAllocator<_Allocator>>
119438fd1498Szrj     unordered_map(initializer_list<pair<_Key, _Tp>>, _Allocator)
119538fd1498Szrj     -> unordered_map<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>;
119638fd1498Szrj 
119738fd1498Szrj   template<typename _Key, typename _Tp, typename _Hash, typename _Allocator,
119838fd1498Szrj 	   typename = _RequireAllocator<_Allocator>>
119938fd1498Szrj     unordered_map(initializer_list<pair<_Key, _Tp>>,
120038fd1498Szrj 		  typename unordered_map<int, int>::size_type,
120138fd1498Szrj 		  _Hash, _Allocator)
120238fd1498Szrj     -> unordered_map<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>;
120338fd1498Szrj 
120438fd1498Szrj #endif
120538fd1498Szrj 
120638fd1498Szrj   /**
120738fd1498Szrj    *  @brief A standard container composed of equivalent keys
120838fd1498Szrj    *  (possibly containing multiple of each key value) that associates
120938fd1498Szrj    *  values of another type with the keys.
121038fd1498Szrj    *
121138fd1498Szrj    *  @ingroup unordered_associative_containers
121238fd1498Szrj    *
121338fd1498Szrj    *  @tparam  _Key    Type of key objects.
121438fd1498Szrj    *  @tparam  _Tp     Type of mapped objects.
121538fd1498Szrj    *  @tparam  _Hash   Hashing function object type, defaults to hash<_Value>.
121638fd1498Szrj    *  @tparam  _Pred   Predicate function object type, defaults
121738fd1498Szrj    *                   to equal_to<_Value>.
121838fd1498Szrj    *  @tparam  _Alloc  Allocator type, defaults to
121938fd1498Szrj    *                   std::allocator<std::pair<const _Key, _Tp>>.
122038fd1498Szrj    *
122138fd1498Szrj    *  Meets the requirements of a <a href="tables.html#65">container</a>, and
122238fd1498Szrj    *  <a href="tables.html#xx">unordered associative container</a>
122338fd1498Szrj    *
122438fd1498Szrj    * The resulting value type of the container is std::pair<const _Key, _Tp>.
122538fd1498Szrj    *
122638fd1498Szrj    *  Base is _Hashtable, dispatched at compile time via template
122738fd1498Szrj    *  alias __ummap_hashtable.
122838fd1498Szrj    */
122938fd1498Szrj   template<typename _Key, typename _Tp,
123038fd1498Szrj 	   typename _Hash = hash<_Key>,
123138fd1498Szrj 	   typename _Pred = equal_to<_Key>,
123238fd1498Szrj 	   typename _Alloc = allocator<std::pair<const _Key, _Tp>>>
123338fd1498Szrj     class unordered_multimap
123438fd1498Szrj     {
123538fd1498Szrj       typedef __ummap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc>  _Hashtable;
123638fd1498Szrj       _Hashtable _M_h;
123738fd1498Szrj 
123838fd1498Szrj     public:
123938fd1498Szrj       // typedefs:
124038fd1498Szrj       //@{
124138fd1498Szrj       /// Public typedefs.
124238fd1498Szrj       typedef typename _Hashtable::key_type	key_type;
124338fd1498Szrj       typedef typename _Hashtable::value_type	value_type;
124438fd1498Szrj       typedef typename _Hashtable::mapped_type	mapped_type;
124538fd1498Szrj       typedef typename _Hashtable::hasher	hasher;
124638fd1498Szrj       typedef typename _Hashtable::key_equal	key_equal;
124738fd1498Szrj       typedef typename _Hashtable::allocator_type allocator_type;
124838fd1498Szrj       //@}
124938fd1498Szrj 
125038fd1498Szrj       //@{
125138fd1498Szrj       ///  Iterator-related typedefs.
125238fd1498Szrj       typedef typename _Hashtable::pointer		pointer;
125338fd1498Szrj       typedef typename _Hashtable::const_pointer	const_pointer;
125438fd1498Szrj       typedef typename _Hashtable::reference		reference;
125538fd1498Szrj       typedef typename _Hashtable::const_reference	const_reference;
125638fd1498Szrj       typedef typename _Hashtable::iterator		iterator;
125738fd1498Szrj       typedef typename _Hashtable::const_iterator	const_iterator;
125838fd1498Szrj       typedef typename _Hashtable::local_iterator	local_iterator;
125938fd1498Szrj       typedef typename _Hashtable::const_local_iterator	const_local_iterator;
126038fd1498Szrj       typedef typename _Hashtable::size_type		size_type;
126138fd1498Szrj       typedef typename _Hashtable::difference_type	difference_type;
126238fd1498Szrj       //@}
126338fd1498Szrj 
126438fd1498Szrj #if __cplusplus > 201402L
126538fd1498Szrj       using node_type = typename _Hashtable::node_type;
126638fd1498Szrj #endif
126738fd1498Szrj 
126838fd1498Szrj       //construct/destroy/copy
126938fd1498Szrj 
127038fd1498Szrj       /// Default constructor.
127138fd1498Szrj       unordered_multimap() = default;
127238fd1498Szrj 
127338fd1498Szrj       /**
127438fd1498Szrj        *  @brief  Default constructor creates no elements.
127538fd1498Szrj        *  @param __n  Mnimal initial number of buckets.
127638fd1498Szrj        *  @param __hf  A hash functor.
127738fd1498Szrj        *  @param __eql  A key equality functor.
127838fd1498Szrj        *  @param __a  An allocator object.
127938fd1498Szrj        */
128038fd1498Szrj       explicit
128138fd1498Szrj       unordered_multimap(size_type __n,
128238fd1498Szrj 			 const hasher& __hf = hasher(),
128338fd1498Szrj 			 const key_equal& __eql = key_equal(),
128438fd1498Szrj 			 const allocator_type& __a = allocator_type())
128538fd1498Szrj       : _M_h(__n, __hf, __eql, __a)
128638fd1498Szrj       { }
128738fd1498Szrj 
128838fd1498Szrj       /**
128938fd1498Szrj        *  @brief  Builds an %unordered_multimap from a range.
129038fd1498Szrj        *  @param  __first An input iterator.
129138fd1498Szrj        *  @param  __last  An input iterator.
129238fd1498Szrj        *  @param __n      Minimal initial number of buckets.
129338fd1498Szrj        *  @param __hf     A hash functor.
129438fd1498Szrj        *  @param __eql    A key equality functor.
129538fd1498Szrj        *  @param __a      An allocator object.
129638fd1498Szrj        *
129738fd1498Szrj        *  Create an %unordered_multimap consisting of copies of the elements
129838fd1498Szrj        *  from [__first,__last).  This is linear in N (where N is
129938fd1498Szrj        *  distance(__first,__last)).
130038fd1498Szrj        */
130138fd1498Szrj       template<typename _InputIterator>
130238fd1498Szrj 	unordered_multimap(_InputIterator __first, _InputIterator __last,
130338fd1498Szrj 			   size_type __n = 0,
130438fd1498Szrj 			   const hasher& __hf = hasher(),
130538fd1498Szrj 			   const key_equal& __eql = key_equal(),
130638fd1498Szrj 			   const allocator_type& __a = allocator_type())
130738fd1498Szrj 	: _M_h(__first, __last, __n, __hf, __eql, __a)
130838fd1498Szrj 	{ }
130938fd1498Szrj 
131038fd1498Szrj       /// Copy constructor.
131138fd1498Szrj       unordered_multimap(const unordered_multimap&) = default;
131238fd1498Szrj 
131338fd1498Szrj       /// Move constructor.
131438fd1498Szrj       unordered_multimap(unordered_multimap&&) = default;
131538fd1498Szrj 
131638fd1498Szrj       /**
131738fd1498Szrj        *  @brief Creates an %unordered_multimap with no elements.
131838fd1498Szrj        *  @param __a An allocator object.
131938fd1498Szrj        */
132038fd1498Szrj       explicit
132138fd1498Szrj       unordered_multimap(const allocator_type& __a)
132238fd1498Szrj       : _M_h(__a)
132338fd1498Szrj       { }
132438fd1498Szrj 
132538fd1498Szrj       /*
132638fd1498Szrj        *  @brief Copy constructor with allocator argument.
132738fd1498Szrj        * @param  __uset  Input %unordered_multimap to copy.
132838fd1498Szrj        * @param  __a  An allocator object.
132938fd1498Szrj        */
133038fd1498Szrj       unordered_multimap(const unordered_multimap& __ummap,
133138fd1498Szrj 			 const allocator_type& __a)
133238fd1498Szrj       : _M_h(__ummap._M_h, __a)
133338fd1498Szrj       { }
133438fd1498Szrj 
133538fd1498Szrj       /*
133638fd1498Szrj        *  @brief  Move constructor with allocator argument.
133738fd1498Szrj        *  @param  __uset Input %unordered_multimap to move.
133838fd1498Szrj        *  @param  __a    An allocator object.
133938fd1498Szrj        */
134038fd1498Szrj       unordered_multimap(unordered_multimap&& __ummap,
134138fd1498Szrj 			 const allocator_type& __a)
134238fd1498Szrj       : _M_h(std::move(__ummap._M_h), __a)
134338fd1498Szrj       { }
134438fd1498Szrj 
134538fd1498Szrj       /**
134638fd1498Szrj        *  @brief  Builds an %unordered_multimap from an initializer_list.
134738fd1498Szrj        *  @param  __l  An initializer_list.
134838fd1498Szrj        *  @param __n  Minimal initial number of buckets.
134938fd1498Szrj        *  @param __hf  A hash functor.
135038fd1498Szrj        *  @param __eql  A key equality functor.
135138fd1498Szrj        *  @param  __a  An allocator object.
135238fd1498Szrj        *
135338fd1498Szrj        *  Create an %unordered_multimap consisting of copies of the elements in
135438fd1498Szrj        *  the list. This is linear in N (where N is @a __l.size()).
135538fd1498Szrj        */
135638fd1498Szrj       unordered_multimap(initializer_list<value_type> __l,
135738fd1498Szrj 			 size_type __n = 0,
135838fd1498Szrj 			 const hasher& __hf = hasher(),
135938fd1498Szrj 			 const key_equal& __eql = key_equal(),
136038fd1498Szrj 			 const allocator_type& __a = allocator_type())
136138fd1498Szrj       : _M_h(__l, __n, __hf, __eql, __a)
136238fd1498Szrj       { }
136338fd1498Szrj 
136438fd1498Szrj       unordered_multimap(size_type __n, const allocator_type& __a)
136538fd1498Szrj       : unordered_multimap(__n, hasher(), key_equal(), __a)
136638fd1498Szrj       { }
136738fd1498Szrj 
136838fd1498Szrj       unordered_multimap(size_type __n, const hasher& __hf,
136938fd1498Szrj 			 const allocator_type& __a)
137038fd1498Szrj       : unordered_multimap(__n, __hf, key_equal(), __a)
137138fd1498Szrj       { }
137238fd1498Szrj 
137338fd1498Szrj       template<typename _InputIterator>
137438fd1498Szrj 	unordered_multimap(_InputIterator __first, _InputIterator __last,
137538fd1498Szrj 			   size_type __n,
137638fd1498Szrj 			   const allocator_type& __a)
137738fd1498Szrj 	: unordered_multimap(__first, __last, __n, hasher(), key_equal(), __a)
137838fd1498Szrj 	{ }
137938fd1498Szrj 
138038fd1498Szrj       template<typename _InputIterator>
138138fd1498Szrj 	unordered_multimap(_InputIterator __first, _InputIterator __last,
138238fd1498Szrj 			   size_type __n, const hasher& __hf,
138338fd1498Szrj 			   const allocator_type& __a)
138438fd1498Szrj 	: unordered_multimap(__first, __last, __n, __hf, key_equal(), __a)
138538fd1498Szrj 	{ }
138638fd1498Szrj 
138738fd1498Szrj       unordered_multimap(initializer_list<value_type> __l,
138838fd1498Szrj 			 size_type __n,
138938fd1498Szrj 			 const allocator_type& __a)
139038fd1498Szrj       : unordered_multimap(__l, __n, hasher(), key_equal(), __a)
139138fd1498Szrj       { }
139238fd1498Szrj 
139338fd1498Szrj       unordered_multimap(initializer_list<value_type> __l,
139438fd1498Szrj 			 size_type __n, const hasher& __hf,
139538fd1498Szrj 			 const allocator_type& __a)
139638fd1498Szrj       : unordered_multimap(__l, __n, __hf, key_equal(), __a)
139738fd1498Szrj       { }
139838fd1498Szrj 
139938fd1498Szrj       /// Copy assignment operator.
140038fd1498Szrj       unordered_multimap&
140138fd1498Szrj       operator=(const unordered_multimap&) = default;
140238fd1498Szrj 
140338fd1498Szrj       /// Move assignment operator.
140438fd1498Szrj       unordered_multimap&
140538fd1498Szrj       operator=(unordered_multimap&&) = default;
140638fd1498Szrj 
140738fd1498Szrj       /**
140838fd1498Szrj        *  @brief  %Unordered_multimap list assignment operator.
140938fd1498Szrj        *  @param  __l  An initializer_list.
141038fd1498Szrj        *
141138fd1498Szrj        *  This function fills an %unordered_multimap with copies of the
141238fd1498Szrj        *  elements in the initializer list @a __l.
141338fd1498Szrj        *
141438fd1498Szrj        *  Note that the assignment completely changes the %unordered_multimap
141538fd1498Szrj        *  and that the resulting %unordered_multimap's size is the same as the
141638fd1498Szrj        *  number of elements assigned.
141738fd1498Szrj        */
141838fd1498Szrj       unordered_multimap&
141938fd1498Szrj       operator=(initializer_list<value_type> __l)
142038fd1498Szrj       {
142138fd1498Szrj 	_M_h = __l;
142238fd1498Szrj 	return *this;
142338fd1498Szrj       }
142438fd1498Szrj 
142538fd1498Szrj       ///  Returns the allocator object used by the %unordered_multimap.
142638fd1498Szrj       allocator_type
142738fd1498Szrj       get_allocator() const noexcept
142838fd1498Szrj       { return _M_h.get_allocator(); }
142938fd1498Szrj 
143038fd1498Szrj       // size and capacity:
143138fd1498Szrj 
143238fd1498Szrj       ///  Returns true if the %unordered_multimap is empty.
143338fd1498Szrj       bool
143438fd1498Szrj       empty() const noexcept
143538fd1498Szrj       { return _M_h.empty(); }
143638fd1498Szrj 
143738fd1498Szrj       ///  Returns the size of the %unordered_multimap.
143838fd1498Szrj       size_type
143938fd1498Szrj       size() const noexcept
144038fd1498Szrj       { return _M_h.size(); }
144138fd1498Szrj 
144238fd1498Szrj       ///  Returns the maximum size of the %unordered_multimap.
144338fd1498Szrj       size_type
144438fd1498Szrj       max_size() const noexcept
144538fd1498Szrj       { return _M_h.max_size(); }
144638fd1498Szrj 
144738fd1498Szrj       // iterators.
144838fd1498Szrj 
144938fd1498Szrj       /**
145038fd1498Szrj        *  Returns a read/write iterator that points to the first element in the
145138fd1498Szrj        *  %unordered_multimap.
145238fd1498Szrj        */
145338fd1498Szrj       iterator
145438fd1498Szrj       begin() noexcept
145538fd1498Szrj       { return _M_h.begin(); }
145638fd1498Szrj 
145738fd1498Szrj       //@{
145838fd1498Szrj       /**
145938fd1498Szrj        *  Returns a read-only (constant) iterator that points to the first
146038fd1498Szrj        *  element in the %unordered_multimap.
146138fd1498Szrj        */
146238fd1498Szrj       const_iterator
146338fd1498Szrj       begin() const noexcept
146438fd1498Szrj       { return _M_h.begin(); }
146538fd1498Szrj 
146638fd1498Szrj       const_iterator
146738fd1498Szrj       cbegin() const noexcept
146838fd1498Szrj       { return _M_h.begin(); }
146938fd1498Szrj       //@}
147038fd1498Szrj 
147138fd1498Szrj       /**
147238fd1498Szrj        *  Returns a read/write iterator that points one past the last element in
147338fd1498Szrj        *  the %unordered_multimap.
147438fd1498Szrj        */
147538fd1498Szrj       iterator
147638fd1498Szrj       end() noexcept
147738fd1498Szrj       { return _M_h.end(); }
147838fd1498Szrj 
147938fd1498Szrj       //@{
148038fd1498Szrj       /**
148138fd1498Szrj        *  Returns a read-only (constant) iterator that points one past the last
148238fd1498Szrj        *  element in the %unordered_multimap.
148338fd1498Szrj        */
148438fd1498Szrj       const_iterator
148538fd1498Szrj       end() const noexcept
148638fd1498Szrj       { return _M_h.end(); }
148738fd1498Szrj 
148838fd1498Szrj       const_iterator
148938fd1498Szrj       cend() const noexcept
149038fd1498Szrj       { return _M_h.end(); }
149138fd1498Szrj       //@}
149238fd1498Szrj 
149338fd1498Szrj       // modifiers.
149438fd1498Szrj 
149538fd1498Szrj       /**
149638fd1498Szrj        *  @brief Attempts to build and insert a std::pair into the
149738fd1498Szrj        *  %unordered_multimap.
149838fd1498Szrj        *
149938fd1498Szrj        *  @param __args  Arguments used to generate a new pair instance (see
150038fd1498Szrj        *	        std::piecewise_contruct for passing arguments to each
150138fd1498Szrj        *	        part of the pair constructor).
150238fd1498Szrj        *
150338fd1498Szrj        *  @return  An iterator that points to the inserted pair.
150438fd1498Szrj        *
150538fd1498Szrj        *  This function attempts to build and insert a (key, value) %pair into
150638fd1498Szrj        *  the %unordered_multimap.
150738fd1498Szrj        *
150838fd1498Szrj        *  Insertion requires amortized constant time.
150938fd1498Szrj        */
151038fd1498Szrj       template<typename... _Args>
151138fd1498Szrj 	iterator
151238fd1498Szrj 	emplace(_Args&&... __args)
151338fd1498Szrj 	{ return _M_h.emplace(std::forward<_Args>(__args)...); }
151438fd1498Szrj 
151538fd1498Szrj       /**
151638fd1498Szrj        *  @brief Attempts to build and insert a std::pair into the
151738fd1498Szrj        *  %unordered_multimap.
151838fd1498Szrj        *
151938fd1498Szrj        *  @param  __pos  An iterator that serves as a hint as to where the pair
152038fd1498Szrj        *                should be inserted.
152138fd1498Szrj        *  @param  __args  Arguments used to generate a new pair instance (see
152238fd1498Szrj        *	         std::piecewise_contruct for passing arguments to each
152338fd1498Szrj        *	         part of the pair constructor).
152438fd1498Szrj        *  @return An iterator that points to the element with key of the
152538fd1498Szrj        *          std::pair built from @a __args.
152638fd1498Szrj        *
152738fd1498Szrj        *  Note that the first parameter is only a hint and can potentially
152838fd1498Szrj        *  improve the performance of the insertion process. A bad hint would
152938fd1498Szrj        *  cause no gains in efficiency.
153038fd1498Szrj        *
153138fd1498Szrj        *  See
153238fd1498Szrj        *  https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints
153338fd1498Szrj        *  for more on @a hinting.
153438fd1498Szrj        *
153538fd1498Szrj        *  Insertion requires amortized constant time.
153638fd1498Szrj        */
153738fd1498Szrj       template<typename... _Args>
153838fd1498Szrj 	iterator
153938fd1498Szrj 	emplace_hint(const_iterator __pos, _Args&&... __args)
154038fd1498Szrj 	{ return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); }
154138fd1498Szrj 
154238fd1498Szrj       //@{
154338fd1498Szrj       /**
154438fd1498Szrj        *  @brief Inserts a std::pair into the %unordered_multimap.
154538fd1498Szrj        *  @param __x Pair to be inserted (see std::make_pair for easy
154638fd1498Szrj        *	     creation of pairs).
154738fd1498Szrj        *
154838fd1498Szrj        *  @return  An iterator that points to the inserted pair.
154938fd1498Szrj        *
155038fd1498Szrj        *  Insertion requires amortized constant time.
155138fd1498Szrj        */
155238fd1498Szrj       iterator
155338fd1498Szrj       insert(const value_type& __x)
155438fd1498Szrj       { return _M_h.insert(__x); }
155538fd1498Szrj 
155638fd1498Szrj       iterator
155738fd1498Szrj       insert(value_type&& __x)
155838fd1498Szrj       { return _M_h.insert(std::move(__x)); }
155938fd1498Szrj 
1560*58e805e6Szrj       template<typename _Pair>
1561*58e805e6Szrj 	__enable_if_t<is_constructible<value_type, _Pair&&>::value, iterator>
156238fd1498Szrj 	insert(_Pair&& __x)
1563*58e805e6Szrj         { return _M_h.emplace(std::forward<_Pair>(__x)); }
156438fd1498Szrj       //@}
156538fd1498Szrj 
156638fd1498Szrj       //@{
156738fd1498Szrj       /**
156838fd1498Szrj        *  @brief Inserts a std::pair into the %unordered_multimap.
156938fd1498Szrj        *  @param  __hint  An iterator that serves as a hint as to where the
157038fd1498Szrj        *                 pair should be inserted.
157138fd1498Szrj        *  @param  __x  Pair to be inserted (see std::make_pair for easy creation
157238fd1498Szrj        *               of pairs).
157338fd1498Szrj        *  @return An iterator that points to the element with key of
157438fd1498Szrj        *           @a __x (may or may not be the %pair passed in).
157538fd1498Szrj        *
157638fd1498Szrj        *  Note that the first parameter is only a hint and can potentially
157738fd1498Szrj        *  improve the performance of the insertion process.  A bad hint would
157838fd1498Szrj        *  cause no gains in efficiency.
157938fd1498Szrj        *
158038fd1498Szrj        *  See
158138fd1498Szrj        *  https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints
158238fd1498Szrj        *  for more on @a hinting.
158338fd1498Szrj        *
158438fd1498Szrj        *  Insertion requires amortized constant time.
158538fd1498Szrj        */
158638fd1498Szrj       iterator
158738fd1498Szrj       insert(const_iterator __hint, const value_type& __x)
158838fd1498Szrj       { return _M_h.insert(__hint, __x); }
158938fd1498Szrj 
159038fd1498Szrj       // _GLIBCXX_RESOLVE_LIB_DEFECTS
159138fd1498Szrj       // 2354. Unnecessary copying when inserting into maps with braced-init
159238fd1498Szrj       iterator
159338fd1498Szrj       insert(const_iterator __hint, value_type&& __x)
159438fd1498Szrj       { return _M_h.insert(__hint, std::move(__x)); }
159538fd1498Szrj 
1596*58e805e6Szrj       template<typename _Pair>
1597*58e805e6Szrj 	__enable_if_t<is_constructible<value_type, _Pair&&>::value, iterator>
159838fd1498Szrj 	insert(const_iterator __hint, _Pair&& __x)
1599*58e805e6Szrj         { return _M_h.emplace_hint(__hint, std::forward<_Pair>(__x)); }
160038fd1498Szrj       //@}
160138fd1498Szrj 
160238fd1498Szrj       /**
160338fd1498Szrj        *  @brief A template function that attempts to insert a range of
160438fd1498Szrj        *  elements.
160538fd1498Szrj        *  @param  __first  Iterator pointing to the start of the range to be
160638fd1498Szrj        *                   inserted.
160738fd1498Szrj        *  @param  __last  Iterator pointing to the end of the range.
160838fd1498Szrj        *
160938fd1498Szrj        *  Complexity similar to that of the range constructor.
161038fd1498Szrj        */
161138fd1498Szrj       template<typename _InputIterator>
161238fd1498Szrj 	void
161338fd1498Szrj 	insert(_InputIterator __first, _InputIterator __last)
161438fd1498Szrj 	{ _M_h.insert(__first, __last); }
161538fd1498Szrj 
161638fd1498Szrj       /**
161738fd1498Szrj        *  @brief Attempts to insert a list of elements into the
161838fd1498Szrj        *  %unordered_multimap.
161938fd1498Szrj        *  @param  __l  A std::initializer_list<value_type> of elements
162038fd1498Szrj        *               to be inserted.
162138fd1498Szrj        *
162238fd1498Szrj        *  Complexity similar to that of the range constructor.
162338fd1498Szrj        */
162438fd1498Szrj       void
162538fd1498Szrj       insert(initializer_list<value_type> __l)
162638fd1498Szrj       { _M_h.insert(__l); }
162738fd1498Szrj 
162838fd1498Szrj #if __cplusplus > 201402L
162938fd1498Szrj       /// Extract a node.
163038fd1498Szrj       node_type
163138fd1498Szrj       extract(const_iterator __pos)
163238fd1498Szrj       {
163338fd1498Szrj 	__glibcxx_assert(__pos != end());
163438fd1498Szrj 	return _M_h.extract(__pos);
163538fd1498Szrj       }
163638fd1498Szrj 
163738fd1498Szrj       /// Extract a node.
163838fd1498Szrj       node_type
163938fd1498Szrj       extract(const key_type& __key)
164038fd1498Szrj       { return _M_h.extract(__key); }
164138fd1498Szrj 
164238fd1498Szrj       /// Re-insert an extracted node.
164338fd1498Szrj       iterator
164438fd1498Szrj       insert(node_type&& __nh)
164538fd1498Szrj       { return _M_h._M_reinsert_node_multi(cend(), std::move(__nh)); }
164638fd1498Szrj 
164738fd1498Szrj       /// Re-insert an extracted node.
164838fd1498Szrj       iterator
164938fd1498Szrj       insert(const_iterator __hint, node_type&& __nh)
165038fd1498Szrj       { return _M_h._M_reinsert_node_multi(__hint, std::move(__nh)); }
165138fd1498Szrj #endif // C++17
165238fd1498Szrj 
165338fd1498Szrj       //@{
165438fd1498Szrj       /**
165538fd1498Szrj        *  @brief Erases an element from an %unordered_multimap.
165638fd1498Szrj        *  @param  __position  An iterator pointing to the element to be erased.
165738fd1498Szrj        *  @return An iterator pointing to the element immediately following
165838fd1498Szrj        *          @a __position prior to the element being erased. If no such
165938fd1498Szrj        *          element exists, end() is returned.
166038fd1498Szrj        *
166138fd1498Szrj        *  This function erases an element, pointed to by the given iterator,
166238fd1498Szrj        *  from an %unordered_multimap.
166338fd1498Szrj        *  Note that this function only erases the element, and that if the
166438fd1498Szrj        *  element is itself a pointer, the pointed-to memory is not touched in
166538fd1498Szrj        *  any way.  Managing the pointer is the user's responsibility.
166638fd1498Szrj        */
166738fd1498Szrj       iterator
166838fd1498Szrj       erase(const_iterator __position)
166938fd1498Szrj       { return _M_h.erase(__position); }
167038fd1498Szrj 
167138fd1498Szrj       // LWG 2059.
167238fd1498Szrj       iterator
167338fd1498Szrj       erase(iterator __position)
167438fd1498Szrj       { return _M_h.erase(__position); }
167538fd1498Szrj       //@}
167638fd1498Szrj 
167738fd1498Szrj       /**
167838fd1498Szrj        *  @brief Erases elements according to the provided key.
167938fd1498Szrj        *  @param  __x  Key of elements to be erased.
168038fd1498Szrj        *  @return  The number of elements erased.
168138fd1498Szrj        *
168238fd1498Szrj        *  This function erases all the elements located by the given key from
168338fd1498Szrj        *  an %unordered_multimap.
168438fd1498Szrj        *  Note that this function only erases the element, and that if the
168538fd1498Szrj        *  element is itself a pointer, the pointed-to memory is not touched in
168638fd1498Szrj        *  any way.  Managing the pointer is the user's responsibility.
168738fd1498Szrj        */
168838fd1498Szrj       size_type
168938fd1498Szrj       erase(const key_type& __x)
169038fd1498Szrj       { return _M_h.erase(__x); }
169138fd1498Szrj 
169238fd1498Szrj       /**
169338fd1498Szrj        *  @brief Erases a [__first,__last) range of elements from an
169438fd1498Szrj        *  %unordered_multimap.
169538fd1498Szrj        *  @param  __first  Iterator pointing to the start of the range to be
169638fd1498Szrj        *                  erased.
169738fd1498Szrj        *  @param __last  Iterator pointing to the end of the range to
169838fd1498Szrj        *                be erased.
169938fd1498Szrj        *  @return The iterator @a __last.
170038fd1498Szrj        *
170138fd1498Szrj        *  This function erases a sequence of elements from an
170238fd1498Szrj        *  %unordered_multimap.
170338fd1498Szrj        *  Note that this function only erases the elements, and that if
170438fd1498Szrj        *  the element is itself a pointer, the pointed-to memory is not touched
170538fd1498Szrj        *  in any way.  Managing the pointer is the user's responsibility.
170638fd1498Szrj        */
170738fd1498Szrj       iterator
170838fd1498Szrj       erase(const_iterator __first, const_iterator __last)
170938fd1498Szrj       { return _M_h.erase(__first, __last); }
171038fd1498Szrj 
171138fd1498Szrj       /**
171238fd1498Szrj        *  Erases all elements in an %unordered_multimap.
171338fd1498Szrj        *  Note that this function only erases the elements, and that if the
171438fd1498Szrj        *  elements themselves are pointers, the pointed-to memory is not touched
171538fd1498Szrj        *  in any way.  Managing the pointer is the user's responsibility.
171638fd1498Szrj        */
171738fd1498Szrj       void
171838fd1498Szrj       clear() noexcept
171938fd1498Szrj       { _M_h.clear(); }
172038fd1498Szrj 
172138fd1498Szrj       /**
172238fd1498Szrj        *  @brief  Swaps data with another %unordered_multimap.
172338fd1498Szrj        *  @param  __x  An %unordered_multimap of the same element and allocator
172438fd1498Szrj        *  types.
172538fd1498Szrj        *
172638fd1498Szrj        *  This exchanges the elements between two %unordered_multimap in
172738fd1498Szrj        *  constant time.
172838fd1498Szrj        *  Note that the global std::swap() function is specialized such that
172938fd1498Szrj        *  std::swap(m1,m2) will feed to this function.
173038fd1498Szrj        */
173138fd1498Szrj       void
173238fd1498Szrj       swap(unordered_multimap& __x)
173338fd1498Szrj       noexcept( noexcept(_M_h.swap(__x._M_h)) )
173438fd1498Szrj       { _M_h.swap(__x._M_h); }
173538fd1498Szrj 
173638fd1498Szrj #if __cplusplus > 201402L
173738fd1498Szrj       template<typename, typename, typename>
173838fd1498Szrj 	friend class std::_Hash_merge_helper;
173938fd1498Szrj 
174038fd1498Szrj       template<typename _H2, typename _P2>
174138fd1498Szrj 	void
174238fd1498Szrj 	merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>& __source)
174338fd1498Szrj 	{
174438fd1498Szrj 	  using _Merge_helper
174538fd1498Szrj 	    = _Hash_merge_helper<unordered_multimap, _H2, _P2>;
174638fd1498Szrj 	  _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source));
174738fd1498Szrj 	}
174838fd1498Szrj 
174938fd1498Szrj       template<typename _H2, typename _P2>
175038fd1498Szrj 	void
175138fd1498Szrj 	merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>&& __source)
175238fd1498Szrj 	{ merge(__source); }
175338fd1498Szrj 
175438fd1498Szrj       template<typename _H2, typename _P2>
175538fd1498Szrj 	void
175638fd1498Szrj 	merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>& __source)
175738fd1498Szrj 	{
175838fd1498Szrj 	  using _Merge_helper
175938fd1498Szrj 	    = _Hash_merge_helper<unordered_multimap, _H2, _P2>;
176038fd1498Szrj 	  _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source));
176138fd1498Szrj 	}
176238fd1498Szrj 
176338fd1498Szrj       template<typename _H2, typename _P2>
176438fd1498Szrj 	void
176538fd1498Szrj 	merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>&& __source)
176638fd1498Szrj 	{ merge(__source); }
176738fd1498Szrj #endif // C++17
176838fd1498Szrj 
176938fd1498Szrj       // observers.
177038fd1498Szrj 
177138fd1498Szrj       ///  Returns the hash functor object with which the %unordered_multimap
177238fd1498Szrj       ///  was constructed.
177338fd1498Szrj       hasher
177438fd1498Szrj       hash_function() const
177538fd1498Szrj       { return _M_h.hash_function(); }
177638fd1498Szrj 
177738fd1498Szrj       ///  Returns the key comparison object with which the %unordered_multimap
177838fd1498Szrj       ///  was constructed.
177938fd1498Szrj       key_equal
178038fd1498Szrj       key_eq() const
178138fd1498Szrj       { return _M_h.key_eq(); }
178238fd1498Szrj 
178338fd1498Szrj       // lookup.
178438fd1498Szrj 
178538fd1498Szrj       //@{
178638fd1498Szrj       /**
178738fd1498Szrj        *  @brief Tries to locate an element in an %unordered_multimap.
178838fd1498Szrj        *  @param  __x  Key to be located.
178938fd1498Szrj        *  @return  Iterator pointing to sought-after element, or end() if not
179038fd1498Szrj        *           found.
179138fd1498Szrj        *
179238fd1498Szrj        *  This function takes a key and tries to locate the element with which
179338fd1498Szrj        *  the key matches.  If successful the function returns an iterator
179438fd1498Szrj        *  pointing to the sought after element.  If unsuccessful it returns the
179538fd1498Szrj        *  past-the-end ( @c end() ) iterator.
179638fd1498Szrj        */
179738fd1498Szrj       iterator
179838fd1498Szrj       find(const key_type& __x)
179938fd1498Szrj       { return _M_h.find(__x); }
180038fd1498Szrj 
180138fd1498Szrj       const_iterator
180238fd1498Szrj       find(const key_type& __x) const
180338fd1498Szrj       { return _M_h.find(__x); }
180438fd1498Szrj       //@}
180538fd1498Szrj 
180638fd1498Szrj       /**
180738fd1498Szrj        *  @brief  Finds the number of elements.
180838fd1498Szrj        *  @param  __x  Key to count.
180938fd1498Szrj        *  @return  Number of elements with specified key.
181038fd1498Szrj        */
181138fd1498Szrj       size_type
181238fd1498Szrj       count(const key_type& __x) const
181338fd1498Szrj       { return _M_h.count(__x); }
181438fd1498Szrj 
181538fd1498Szrj       //@{
181638fd1498Szrj       /**
181738fd1498Szrj        *  @brief Finds a subsequence matching given key.
181838fd1498Szrj        *  @param  __x  Key to be located.
181938fd1498Szrj        *  @return  Pair of iterators that possibly points to the subsequence
182038fd1498Szrj        *           matching given key.
182138fd1498Szrj        */
182238fd1498Szrj       std::pair<iterator, iterator>
182338fd1498Szrj       equal_range(const key_type& __x)
182438fd1498Szrj       { return _M_h.equal_range(__x); }
182538fd1498Szrj 
182638fd1498Szrj       std::pair<const_iterator, const_iterator>
182738fd1498Szrj       equal_range(const key_type& __x) const
182838fd1498Szrj       { return _M_h.equal_range(__x); }
182938fd1498Szrj       //@}
183038fd1498Szrj 
183138fd1498Szrj       // bucket interface.
183238fd1498Szrj 
183338fd1498Szrj       /// Returns the number of buckets of the %unordered_multimap.
183438fd1498Szrj       size_type
183538fd1498Szrj       bucket_count() const noexcept
183638fd1498Szrj       { return _M_h.bucket_count(); }
183738fd1498Szrj 
183838fd1498Szrj       /// Returns the maximum number of buckets of the %unordered_multimap.
183938fd1498Szrj       size_type
184038fd1498Szrj       max_bucket_count() const noexcept
184138fd1498Szrj       { return _M_h.max_bucket_count(); }
184238fd1498Szrj 
184338fd1498Szrj       /*
184438fd1498Szrj        * @brief  Returns the number of elements in a given bucket.
184538fd1498Szrj        * @param  __n  A bucket index.
184638fd1498Szrj        * @return  The number of elements in the bucket.
184738fd1498Szrj        */
184838fd1498Szrj       size_type
184938fd1498Szrj       bucket_size(size_type __n) const
185038fd1498Szrj       { return _M_h.bucket_size(__n); }
185138fd1498Szrj 
185238fd1498Szrj       /*
185338fd1498Szrj        * @brief  Returns the bucket index of a given element.
185438fd1498Szrj        * @param  __key  A key instance.
185538fd1498Szrj        * @return  The key bucket index.
185638fd1498Szrj        */
185738fd1498Szrj       size_type
185838fd1498Szrj       bucket(const key_type& __key) const
185938fd1498Szrj       { return _M_h.bucket(__key); }
186038fd1498Szrj 
186138fd1498Szrj       /**
186238fd1498Szrj        *  @brief  Returns a read/write iterator pointing to the first bucket
186338fd1498Szrj        *         element.
186438fd1498Szrj        *  @param  __n The bucket index.
186538fd1498Szrj        *  @return  A read/write local iterator.
186638fd1498Szrj        */
186738fd1498Szrj       local_iterator
186838fd1498Szrj       begin(size_type __n)
186938fd1498Szrj       { return _M_h.begin(__n); }
187038fd1498Szrj 
187138fd1498Szrj       //@{
187238fd1498Szrj       /**
187338fd1498Szrj        *  @brief  Returns a read-only (constant) iterator pointing to the first
187438fd1498Szrj        *         bucket element.
187538fd1498Szrj        *  @param  __n The bucket index.
187638fd1498Szrj        *  @return  A read-only local iterator.
187738fd1498Szrj        */
187838fd1498Szrj       const_local_iterator
187938fd1498Szrj       begin(size_type __n) const
188038fd1498Szrj       { return _M_h.begin(__n); }
188138fd1498Szrj 
188238fd1498Szrj       const_local_iterator
188338fd1498Szrj       cbegin(size_type __n) const
188438fd1498Szrj       { return _M_h.cbegin(__n); }
188538fd1498Szrj       //@}
188638fd1498Szrj 
188738fd1498Szrj       /**
188838fd1498Szrj        *  @brief  Returns a read/write iterator pointing to one past the last
188938fd1498Szrj        *         bucket elements.
189038fd1498Szrj        *  @param  __n The bucket index.
189138fd1498Szrj        *  @return  A read/write local iterator.
189238fd1498Szrj        */
189338fd1498Szrj       local_iterator
189438fd1498Szrj       end(size_type __n)
189538fd1498Szrj       { return _M_h.end(__n); }
189638fd1498Szrj 
189738fd1498Szrj       //@{
189838fd1498Szrj       /**
189938fd1498Szrj        *  @brief  Returns a read-only (constant) iterator pointing to one past
190038fd1498Szrj        *         the last bucket elements.
190138fd1498Szrj        *  @param  __n The bucket index.
190238fd1498Szrj        *  @return  A read-only local iterator.
190338fd1498Szrj        */
190438fd1498Szrj       const_local_iterator
190538fd1498Szrj       end(size_type __n) const
190638fd1498Szrj       { return _M_h.end(__n); }
190738fd1498Szrj 
190838fd1498Szrj       const_local_iterator
190938fd1498Szrj       cend(size_type __n) const
191038fd1498Szrj       { return _M_h.cend(__n); }
191138fd1498Szrj       //@}
191238fd1498Szrj 
191338fd1498Szrj       // hash policy.
191438fd1498Szrj 
191538fd1498Szrj       /// Returns the average number of elements per bucket.
191638fd1498Szrj       float
191738fd1498Szrj       load_factor() const noexcept
191838fd1498Szrj       { return _M_h.load_factor(); }
191938fd1498Szrj 
192038fd1498Szrj       /// Returns a positive number that the %unordered_multimap tries to keep
192138fd1498Szrj       /// the load factor less than or equal to.
192238fd1498Szrj       float
192338fd1498Szrj       max_load_factor() const noexcept
192438fd1498Szrj       { return _M_h.max_load_factor(); }
192538fd1498Szrj 
192638fd1498Szrj       /**
192738fd1498Szrj        *  @brief  Change the %unordered_multimap maximum load factor.
192838fd1498Szrj        *  @param  __z The new maximum load factor.
192938fd1498Szrj        */
193038fd1498Szrj       void
193138fd1498Szrj       max_load_factor(float __z)
193238fd1498Szrj       { _M_h.max_load_factor(__z); }
193338fd1498Szrj 
193438fd1498Szrj       /**
193538fd1498Szrj        *  @brief  May rehash the %unordered_multimap.
193638fd1498Szrj        *  @param  __n The new number of buckets.
193738fd1498Szrj        *
193838fd1498Szrj        *  Rehash will occur only if the new number of buckets respect the
193938fd1498Szrj        *  %unordered_multimap maximum load factor.
194038fd1498Szrj        */
194138fd1498Szrj       void
194238fd1498Szrj       rehash(size_type __n)
194338fd1498Szrj       { _M_h.rehash(__n); }
194438fd1498Szrj 
194538fd1498Szrj       /**
194638fd1498Szrj        *  @brief  Prepare the %unordered_multimap for a specified number of
194738fd1498Szrj        *          elements.
194838fd1498Szrj        *  @param  __n Number of elements required.
194938fd1498Szrj        *
195038fd1498Szrj        *  Same as rehash(ceil(n / max_load_factor())).
195138fd1498Szrj        */
195238fd1498Szrj       void
195338fd1498Szrj       reserve(size_type __n)
195438fd1498Szrj       { _M_h.reserve(__n); }
195538fd1498Szrj 
195638fd1498Szrj       template<typename _Key1, typename _Tp1, typename _Hash1, typename _Pred1,
195738fd1498Szrj 	       typename _Alloc1>
195838fd1498Szrj         friend bool
195938fd1498Szrj 	operator==(const unordered_multimap<_Key1, _Tp1,
196038fd1498Szrj 					    _Hash1, _Pred1, _Alloc1>&,
196138fd1498Szrj 		   const unordered_multimap<_Key1, _Tp1,
196238fd1498Szrj 					    _Hash1, _Pred1, _Alloc1>&);
196338fd1498Szrj     };
196438fd1498Szrj 
196538fd1498Szrj #if __cpp_deduction_guides >= 201606
196638fd1498Szrj 
196738fd1498Szrj   template<typename _InputIterator,
196838fd1498Szrj 	   typename _Hash = hash<__iter_key_t<_InputIterator>>,
196938fd1498Szrj 	   typename _Pred = equal_to<__iter_key_t<_InputIterator>>,
197038fd1498Szrj 	   typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>,
197138fd1498Szrj 	   typename = _RequireInputIter<_InputIterator>,
197238fd1498Szrj 	   typename = _RequireAllocator<_Allocator>>
197338fd1498Szrj     unordered_multimap(_InputIterator, _InputIterator,
197438fd1498Szrj 		       unordered_multimap<int, int>::size_type = {},
197538fd1498Szrj 		       _Hash = _Hash(), _Pred = _Pred(),
197638fd1498Szrj 		       _Allocator = _Allocator())
197738fd1498Szrj     -> unordered_multimap<__iter_key_t<_InputIterator>,
197838fd1498Szrj 			  __iter_val_t<_InputIterator>, _Hash, _Pred,
197938fd1498Szrj 			  _Allocator>;
198038fd1498Szrj 
198138fd1498Szrj   template<typename _Key, typename _Tp, typename _Hash = hash<_Key>,
198238fd1498Szrj 	   typename _Pred = equal_to<_Key>,
198338fd1498Szrj 	   typename _Allocator = allocator<pair<const _Key, _Tp>>,
198438fd1498Szrj 	   typename = _RequireAllocator<_Allocator>>
198538fd1498Szrj     unordered_multimap(initializer_list<pair<_Key, _Tp>>,
198638fd1498Szrj 		       unordered_multimap<int, int>::size_type = {},
198738fd1498Szrj 		       _Hash = _Hash(), _Pred = _Pred(),
198838fd1498Szrj 		       _Allocator = _Allocator())
198938fd1498Szrj     -> unordered_multimap<_Key, _Tp, _Hash, _Pred, _Allocator>;
199038fd1498Szrj 
199138fd1498Szrj   template<typename _InputIterator, typename _Allocator,
199238fd1498Szrj 	   typename = _RequireInputIter<_InputIterator>,
199338fd1498Szrj 	   typename = _RequireAllocator<_Allocator>>
199438fd1498Szrj     unordered_multimap(_InputIterator, _InputIterator,
199538fd1498Szrj 		       unordered_multimap<int, int>::size_type, _Allocator)
199638fd1498Szrj     -> unordered_multimap<__iter_key_t<_InputIterator>,
199738fd1498Szrj 			  __iter_val_t<_InputIterator>,
199838fd1498Szrj 			  hash<__iter_key_t<_InputIterator>>,
199938fd1498Szrj 			  equal_to<__iter_key_t<_InputIterator>>, _Allocator>;
200038fd1498Szrj 
200138fd1498Szrj   template<typename _InputIterator, typename _Allocator,
200238fd1498Szrj 	   typename = _RequireInputIter<_InputIterator>,
200338fd1498Szrj 	   typename = _RequireAllocator<_Allocator>>
200438fd1498Szrj     unordered_multimap(_InputIterator, _InputIterator, _Allocator)
200538fd1498Szrj     -> unordered_multimap<__iter_key_t<_InputIterator>,
200638fd1498Szrj 			  __iter_val_t<_InputIterator>,
200738fd1498Szrj 			  hash<__iter_key_t<_InputIterator>>,
200838fd1498Szrj 			  equal_to<__iter_key_t<_InputIterator>>, _Allocator>;
200938fd1498Szrj 
201038fd1498Szrj   template<typename _InputIterator, typename _Hash, typename _Allocator,
201138fd1498Szrj 	   typename = _RequireInputIter<_InputIterator>,
201238fd1498Szrj 	   typename = _RequireAllocator<_Allocator>>
201338fd1498Szrj     unordered_multimap(_InputIterator, _InputIterator,
201438fd1498Szrj 		       unordered_multimap<int, int>::size_type, _Hash,
201538fd1498Szrj 		       _Allocator)
201638fd1498Szrj     -> unordered_multimap<__iter_key_t<_InputIterator>,
201738fd1498Szrj 			  __iter_val_t<_InputIterator>, _Hash,
201838fd1498Szrj 			  equal_to<__iter_key_t<_InputIterator>>, _Allocator>;
201938fd1498Szrj 
202038fd1498Szrj   template<typename _Key, typename _Tp, typename _Allocator,
202138fd1498Szrj 	   typename = _RequireAllocator<_Allocator>>
202238fd1498Szrj     unordered_multimap(initializer_list<pair<_Key, _Tp>>,
202338fd1498Szrj 		       unordered_multimap<int, int>::size_type,
202438fd1498Szrj 		       _Allocator)
202538fd1498Szrj     -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>;
202638fd1498Szrj 
202738fd1498Szrj   template<typename _Key, typename _Tp, typename _Allocator,
202838fd1498Szrj 	   typename = _RequireAllocator<_Allocator>>
202938fd1498Szrj     unordered_multimap(initializer_list<pair<_Key, _Tp>>, _Allocator)
203038fd1498Szrj     -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>;
203138fd1498Szrj 
203238fd1498Szrj   template<typename _Key, typename _Tp, typename _Hash, typename _Allocator,
203338fd1498Szrj 	   typename = _RequireAllocator<_Allocator>>
203438fd1498Szrj     unordered_multimap(initializer_list<pair<_Key, _Tp>>,
203538fd1498Szrj 		       unordered_multimap<int, int>::size_type,
203638fd1498Szrj 		       _Hash, _Allocator)
203738fd1498Szrj     -> unordered_multimap<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>;
203838fd1498Szrj 
203938fd1498Szrj #endif
204038fd1498Szrj 
204138fd1498Szrj   template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
204238fd1498Szrj     inline void
204338fd1498Szrj     swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
204438fd1498Szrj 	 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
204538fd1498Szrj     noexcept(noexcept(__x.swap(__y)))
204638fd1498Szrj     { __x.swap(__y); }
204738fd1498Szrj 
204838fd1498Szrj   template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
204938fd1498Szrj     inline void
205038fd1498Szrj     swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
205138fd1498Szrj 	 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
205238fd1498Szrj     noexcept(noexcept(__x.swap(__y)))
205338fd1498Szrj     { __x.swap(__y); }
205438fd1498Szrj 
205538fd1498Szrj   template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
205638fd1498Szrj     inline bool
205738fd1498Szrj     operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
205838fd1498Szrj 	       const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
205938fd1498Szrj     { return __x._M_h._M_equal(__y._M_h); }
206038fd1498Szrj 
206138fd1498Szrj   template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
206238fd1498Szrj     inline bool
206338fd1498Szrj     operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
206438fd1498Szrj 	       const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
206538fd1498Szrj     { return !(__x == __y); }
206638fd1498Szrj 
206738fd1498Szrj   template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
206838fd1498Szrj     inline bool
206938fd1498Szrj     operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
207038fd1498Szrj 	       const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
207138fd1498Szrj     { return __x._M_h._M_equal(__y._M_h); }
207238fd1498Szrj 
207338fd1498Szrj   template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
207438fd1498Szrj     inline bool
207538fd1498Szrj     operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
207638fd1498Szrj 	       const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
207738fd1498Szrj     { return !(__x == __y); }
207838fd1498Szrj 
207938fd1498Szrj _GLIBCXX_END_NAMESPACE_CONTAINER
208038fd1498Szrj 
208138fd1498Szrj #if __cplusplus > 201402L
208238fd1498Szrj   // Allow std::unordered_map access to internals of compatible maps.
208338fd1498Szrj   template<typename _Key, typename _Val, typename _Hash1, typename _Eq1,
208438fd1498Szrj 	   typename _Alloc, typename _Hash2, typename _Eq2>
208538fd1498Szrj     struct _Hash_merge_helper<
208638fd1498Szrj       _GLIBCXX_STD_C::unordered_map<_Key, _Val, _Hash1, _Eq1, _Alloc>,
208738fd1498Szrj       _Hash2, _Eq2>
208838fd1498Szrj     {
208938fd1498Szrj     private:
209038fd1498Szrj       template<typename... _Tp>
209138fd1498Szrj 	using unordered_map = _GLIBCXX_STD_C::unordered_map<_Tp...>;
209238fd1498Szrj       template<typename... _Tp>
209338fd1498Szrj 	using unordered_multimap = _GLIBCXX_STD_C::unordered_multimap<_Tp...>;
209438fd1498Szrj 
209538fd1498Szrj       friend unordered_map<_Key, _Val, _Hash1, _Eq1, _Alloc>;
209638fd1498Szrj 
209738fd1498Szrj       static auto&
209838fd1498Szrj       _S_get_table(unordered_map<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map)
209938fd1498Szrj       { return __map._M_h; }
210038fd1498Szrj 
210138fd1498Szrj       static auto&
210238fd1498Szrj       _S_get_table(unordered_multimap<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map)
210338fd1498Szrj       { return __map._M_h; }
210438fd1498Szrj     };
210538fd1498Szrj 
210638fd1498Szrj   // Allow std::unordered_multimap access to internals of compatible maps.
210738fd1498Szrj   template<typename _Key, typename _Val, typename _Hash1, typename _Eq1,
210838fd1498Szrj 	   typename _Alloc, typename _Hash2, typename _Eq2>
210938fd1498Szrj     struct _Hash_merge_helper<
211038fd1498Szrj       _GLIBCXX_STD_C::unordered_multimap<_Key, _Val, _Hash1, _Eq1, _Alloc>,
211138fd1498Szrj       _Hash2, _Eq2>
211238fd1498Szrj     {
211338fd1498Szrj     private:
211438fd1498Szrj       template<typename... _Tp>
211538fd1498Szrj 	using unordered_map = _GLIBCXX_STD_C::unordered_map<_Tp...>;
211638fd1498Szrj       template<typename... _Tp>
211738fd1498Szrj 	using unordered_multimap = _GLIBCXX_STD_C::unordered_multimap<_Tp...>;
211838fd1498Szrj 
211938fd1498Szrj       friend unordered_multimap<_Key, _Val, _Hash1, _Eq1, _Alloc>;
212038fd1498Szrj 
212138fd1498Szrj       static auto&
212238fd1498Szrj       _S_get_table(unordered_map<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map)
212338fd1498Szrj       { return __map._M_h; }
212438fd1498Szrj 
212538fd1498Szrj       static auto&
212638fd1498Szrj       _S_get_table(unordered_multimap<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map)
212738fd1498Szrj       { return __map._M_h; }
212838fd1498Szrj     };
212938fd1498Szrj #endif // C++17
213038fd1498Szrj 
213138fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
213238fd1498Szrj } // namespace std
213338fd1498Szrj 
213438fd1498Szrj #endif /* _UNORDERED_MAP_H */
2135