xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/bits/hashtable_policy.h (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
14fee23f9Smrg // Internal policy header for unordered_set and unordered_map -*- C++ -*-
24fee23f9Smrg 
3b1e83836Smrg // Copyright (C) 2010-2022 Free Software Foundation, Inc.
44fee23f9Smrg //
54fee23f9Smrg // This file is part of the GNU ISO C++ Library.  This library is free
64fee23f9Smrg // software; you can redistribute it and/or modify it under the
74fee23f9Smrg // terms of the GNU General Public License as published by the
84fee23f9Smrg // Free Software Foundation; either version 3, or (at your option)
94fee23f9Smrg // any later version.
104fee23f9Smrg 
114fee23f9Smrg // This library is distributed in the hope that it will be useful,
124fee23f9Smrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
134fee23f9Smrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
144fee23f9Smrg // GNU General Public License for more details.
154fee23f9Smrg 
164fee23f9Smrg // Under Section 7 of GPL version 3, you are granted additional
174fee23f9Smrg // permissions described in the GCC Runtime Library Exception, version
184fee23f9Smrg // 3.1, as published by the Free Software Foundation.
194fee23f9Smrg 
204fee23f9Smrg // You should have received a copy of the GNU General Public License and
214fee23f9Smrg // a copy of the GCC Runtime Library Exception along with this program;
224fee23f9Smrg // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
234fee23f9Smrg // <http://www.gnu.org/licenses/>.
244fee23f9Smrg 
254fee23f9Smrg /** @file bits/hashtable_policy.h
264fee23f9Smrg  *  This is an internal header file, included by other library headers.
2748fb7bfaSmrg  *  Do not attempt to use it directly.
2848fb7bfaSmrg  *  @headername{unordered_map,unordered_set}
294fee23f9Smrg  */
304fee23f9Smrg 
314fee23f9Smrg #ifndef _HASHTABLE_POLICY_H
324fee23f9Smrg #define _HASHTABLE_POLICY_H 1
334fee23f9Smrg 
34a3e9eb18Smrg #include <tuple>		// for std::tuple, std::forward_as_tuple
35fb8a8121Smrg #include <bits/stl_algobase.h>	// for std::min, std::is_permutation.
36b1e83836Smrg #include <ext/aligned_buffer.h>	// for __gnu_cxx::__aligned_buffer
37b1e83836Smrg #include <ext/alloc_traits.h>	// for std::__alloc_rebind
38b1e83836Smrg #include <ext/numeric_traits.h>	// for __gnu_cxx::__int_traits
39b17d1066Smrg 
_GLIBCXX_VISIBILITY(default)4048fb7bfaSmrg namespace std _GLIBCXX_VISIBILITY(default)
414fee23f9Smrg {
4248fb7bfaSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
43b1e83836Smrg /// @cond undocumented
4448fb7bfaSmrg 
4548fb7bfaSmrg   template<typename _Key, typename _Value, typename _Alloc,
4648fb7bfaSmrg 	   typename _ExtractKey, typename _Equal,
47b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
4848fb7bfaSmrg 	   typename _RehashPolicy, typename _Traits>
4948fb7bfaSmrg     class _Hashtable;
5048fb7bfaSmrg 
514fee23f9Smrg namespace __detail
524fee23f9Smrg {
5348fb7bfaSmrg   /**
5448fb7bfaSmrg    *  @defgroup hashtable-detail Base and Implementation Classes
5548fb7bfaSmrg    *  @ingroup unordered_associative_containers
5648fb7bfaSmrg    *  @{
5748fb7bfaSmrg    */
58b1e83836Smrg   template<typename _Key, typename _Value, typename _ExtractKey,
59b1e83836Smrg 	   typename _Equal, typename _Hash, typename _RangeHash,
60b1e83836Smrg 	   typename _Unused, typename _Traits>
6148fb7bfaSmrg     struct _Hashtable_base;
6248fb7bfaSmrg 
634fee23f9Smrg   // Helper function: return distance(first, last) for forward
64a3e9eb18Smrg   // iterators, or 0/1 for input iterators.
65b1e83836Smrg   template<typename _Iterator>
664fee23f9Smrg     inline typename std::iterator_traits<_Iterator>::difference_type
674fee23f9Smrg     __distance_fw(_Iterator __first, _Iterator __last,
684fee23f9Smrg 		  std::input_iterator_tag)
69a3e9eb18Smrg     { return __first != __last ? 1 : 0; }
704fee23f9Smrg 
71b1e83836Smrg   template<typename _Iterator>
724fee23f9Smrg     inline typename std::iterator_traits<_Iterator>::difference_type
734fee23f9Smrg     __distance_fw(_Iterator __first, _Iterator __last,
744fee23f9Smrg 		  std::forward_iterator_tag)
754fee23f9Smrg     { return std::distance(__first, __last); }
764fee23f9Smrg 
77b1e83836Smrg   template<typename _Iterator>
784fee23f9Smrg     inline typename std::iterator_traits<_Iterator>::difference_type
794fee23f9Smrg     __distance_fw(_Iterator __first, _Iterator __last)
80a3e9eb18Smrg     { return __distance_fw(__first, __last,
81a3e9eb18Smrg 			   std::__iterator_category(__first)); }
8248fb7bfaSmrg 
8348fb7bfaSmrg   struct _Identity
8448fb7bfaSmrg   {
8548fb7bfaSmrg     template<typename _Tp>
8648fb7bfaSmrg       _Tp&&
87b1e83836Smrg       operator()(_Tp&& __x) const noexcept
8848fb7bfaSmrg       { return std::forward<_Tp>(__x); }
8948fb7bfaSmrg   };
9048fb7bfaSmrg 
9148fb7bfaSmrg   struct _Select1st
9248fb7bfaSmrg   {
93b1e83836Smrg     template<typename _Pair>
94b1e83836Smrg       struct __1st_type;
95b1e83836Smrg 
96b1e83836Smrg     template<typename _Tp, typename _Up>
97b1e83836Smrg       struct __1st_type<pair<_Tp, _Up>>
98b1e83836Smrg       { using type = _Tp; };
99b1e83836Smrg 
100b1e83836Smrg     template<typename _Tp, typename _Up>
101b1e83836Smrg       struct __1st_type<const pair<_Tp, _Up>>
102b1e83836Smrg       { using type = const _Tp; };
103b1e83836Smrg 
104b1e83836Smrg     template<typename _Pair>
105b1e83836Smrg       struct __1st_type<_Pair&>
106b1e83836Smrg       { using type = typename __1st_type<_Pair>::type&; };
107b1e83836Smrg 
10848fb7bfaSmrg     template<typename _Tp>
109b1e83836Smrg       typename __1st_type<_Tp>::type&&
110b1e83836Smrg       operator()(_Tp&& __x) const noexcept
111b1e83836Smrg       { return std::forward<_Tp>(__x).first; }
112b1e83836Smrg   };
113b1e83836Smrg 
114b1e83836Smrg   template<typename _ExKey>
115b1e83836Smrg     struct _NodeBuilder;
116b1e83836Smrg 
117b1e83836Smrg   template<>
118b1e83836Smrg     struct _NodeBuilder<_Select1st>
119b1e83836Smrg     {
120b1e83836Smrg       template<typename _Kt, typename _Arg, typename _NodeGenerator>
121b1e83836Smrg 	static auto
122b1e83836Smrg 	_S_build(_Kt&& __k, _Arg&& __arg, const _NodeGenerator& __node_gen)
123b1e83836Smrg 	-> typename _NodeGenerator::__node_type*
124b1e83836Smrg 	{
125b1e83836Smrg 	  return __node_gen(std::forward<_Kt>(__k),
126b1e83836Smrg 			    std::forward<_Arg>(__arg).second);
127b1e83836Smrg 	}
128b1e83836Smrg     };
129b1e83836Smrg 
130b1e83836Smrg   template<>
131b1e83836Smrg     struct _NodeBuilder<_Identity>
132b1e83836Smrg     {
133b1e83836Smrg       template<typename _Kt, typename _Arg, typename _NodeGenerator>
134b1e83836Smrg 	static auto
135b1e83836Smrg 	_S_build(_Kt&& __k, _Arg&&, const _NodeGenerator& __node_gen)
136b1e83836Smrg 	-> typename _NodeGenerator::__node_type*
137b1e83836Smrg 	{ return __node_gen(std::forward<_Kt>(__k)); }
13848fb7bfaSmrg     };
13948fb7bfaSmrg 
1404d5abbe8Smrg   template<typename _NodeAlloc>
1414d5abbe8Smrg     struct _Hashtable_alloc;
1424d5abbe8Smrg 
1434d5abbe8Smrg   // Functor recycling a pool of nodes and using allocation once the pool is
1444d5abbe8Smrg   // empty.
1454d5abbe8Smrg   template<typename _NodeAlloc>
1464d5abbe8Smrg     struct _ReuseOrAllocNode
1474d5abbe8Smrg     {
1484d5abbe8Smrg     private:
1494d5abbe8Smrg       using __node_alloc_type = _NodeAlloc;
1504d5abbe8Smrg       using __hashtable_alloc = _Hashtable_alloc<__node_alloc_type>;
1514d5abbe8Smrg       using __node_alloc_traits =
1524d5abbe8Smrg 	typename __hashtable_alloc::__node_alloc_traits;
1534d5abbe8Smrg 
1544d5abbe8Smrg     public:
155b1e83836Smrg       using __node_type = typename __hashtable_alloc::__node_type;
156b1e83836Smrg 
1574d5abbe8Smrg       _ReuseOrAllocNode(__node_type* __nodes, __hashtable_alloc& __h)
1584d5abbe8Smrg       : _M_nodes(__nodes), _M_h(__h) { }
1594d5abbe8Smrg       _ReuseOrAllocNode(const _ReuseOrAllocNode&) = delete;
1604d5abbe8Smrg 
1614d5abbe8Smrg       ~_ReuseOrAllocNode()
1624d5abbe8Smrg       { _M_h._M_deallocate_nodes(_M_nodes); }
1634d5abbe8Smrg 
164b1e83836Smrg       template<typename... _Args>
1654d5abbe8Smrg 	__node_type*
166b1e83836Smrg 	operator()(_Args&&... __args) const
1674d5abbe8Smrg 	{
1684d5abbe8Smrg 	  if (_M_nodes)
1694d5abbe8Smrg 	    {
1704d5abbe8Smrg 	      __node_type* __node = _M_nodes;
1714d5abbe8Smrg 	      _M_nodes = _M_nodes->_M_next();
1724d5abbe8Smrg 	      __node->_M_nxt = nullptr;
173a3e9eb18Smrg 	      auto& __a = _M_h._M_node_allocator();
174a3e9eb18Smrg 	      __node_alloc_traits::destroy(__a, __node->_M_valptr());
1754d5abbe8Smrg 	      __try
1764d5abbe8Smrg 		{
177a3e9eb18Smrg 		  __node_alloc_traits::construct(__a, __node->_M_valptr(),
178b1e83836Smrg 						 std::forward<_Args>(__args)...);
1794d5abbe8Smrg 		}
1804d5abbe8Smrg 	      __catch(...)
1814d5abbe8Smrg 		{
182181254a7Smrg 		  _M_h._M_deallocate_node_ptr(__node);
1834d5abbe8Smrg 		  __throw_exception_again;
1844d5abbe8Smrg 		}
1854d5abbe8Smrg 	      return __node;
1864d5abbe8Smrg 	    }
187b1e83836Smrg 	  return _M_h._M_allocate_node(std::forward<_Args>(__args)...);
1884d5abbe8Smrg 	}
1894d5abbe8Smrg 
1904d5abbe8Smrg     private:
1914d5abbe8Smrg       mutable __node_type* _M_nodes;
1924d5abbe8Smrg       __hashtable_alloc& _M_h;
1934d5abbe8Smrg     };
1944d5abbe8Smrg 
1954d5abbe8Smrg   // Functor similar to the previous one but without any pool of nodes to
1964d5abbe8Smrg   // recycle.
1974d5abbe8Smrg   template<typename _NodeAlloc>
1984d5abbe8Smrg     struct _AllocNode
1994d5abbe8Smrg     {
2004d5abbe8Smrg     private:
2014d5abbe8Smrg       using __hashtable_alloc = _Hashtable_alloc<_NodeAlloc>;
2024d5abbe8Smrg 
2034d5abbe8Smrg     public:
204b1e83836Smrg       using __node_type = typename __hashtable_alloc::__node_type;
205b1e83836Smrg 
2064d5abbe8Smrg       _AllocNode(__hashtable_alloc& __h)
2074d5abbe8Smrg       : _M_h(__h) { }
2084d5abbe8Smrg 
209b1e83836Smrg       template<typename... _Args>
2104d5abbe8Smrg 	__node_type*
211b1e83836Smrg 	operator()(_Args&&... __args) const
212b1e83836Smrg 	{ return _M_h._M_allocate_node(std::forward<_Args>(__args)...); }
2134d5abbe8Smrg 
2144d5abbe8Smrg     private:
2154d5abbe8Smrg       __hashtable_alloc& _M_h;
2164d5abbe8Smrg     };
2174d5abbe8Smrg 
21848fb7bfaSmrg   // Auxiliary types used for all instantiations of _Hashtable nodes
2194fee23f9Smrg   // and iterators.
2204fee23f9Smrg 
22148fb7bfaSmrg   /**
22248fb7bfaSmrg    *  struct _Hashtable_traits
22348fb7bfaSmrg    *
22448fb7bfaSmrg    *  Important traits for hash tables.
22548fb7bfaSmrg    *
22648fb7bfaSmrg    *  @tparam _Cache_hash_code  Boolean value. True if the value of
22748fb7bfaSmrg    *  the hash function is stored along with the value. This is a
22848fb7bfaSmrg    *  time-space tradeoff.  Storing it may improve lookup speed by
229fb8a8121Smrg    *  reducing the number of times we need to call the _Hash or _Equal
230fb8a8121Smrg    *  functors.
23148fb7bfaSmrg    *
23248fb7bfaSmrg    *  @tparam _Constant_iterators  Boolean value. True if iterator and
23348fb7bfaSmrg    *  const_iterator are both constant iterator types. This is true
23448fb7bfaSmrg    *  for unordered_set and unordered_multiset, false for
23548fb7bfaSmrg    *  unordered_map and unordered_multimap.
23648fb7bfaSmrg    *
23748fb7bfaSmrg    *  @tparam _Unique_keys  Boolean value. True if the return value
23848fb7bfaSmrg    *  of _Hashtable::count(k) is always at most one, false if it may
23948fb7bfaSmrg    *  be an arbitrary number. This is true for unordered_set and
24048fb7bfaSmrg    *  unordered_map, false for unordered_multiset and
24148fb7bfaSmrg    *  unordered_multimap.
24248fb7bfaSmrg    */
24348fb7bfaSmrg   template<bool _Cache_hash_code, bool _Constant_iterators, bool _Unique_keys>
24448fb7bfaSmrg     struct _Hashtable_traits
24548fb7bfaSmrg     {
24648fb7bfaSmrg       using __hash_cached = __bool_constant<_Cache_hash_code>;
24748fb7bfaSmrg       using __constant_iterators = __bool_constant<_Constant_iterators>;
24848fb7bfaSmrg       using __unique_keys = __bool_constant<_Unique_keys>;
24948fb7bfaSmrg     };
25048fb7bfaSmrg 
25148fb7bfaSmrg   /**
252b1e83836Smrg    *  struct _Hashtable_hash_traits
253b1e83836Smrg    *
254b1e83836Smrg    *  Important traits for hash tables depending on associated hasher.
255b1e83836Smrg    *
256b1e83836Smrg    */
257b1e83836Smrg   template<typename _Hash>
258b1e83836Smrg     struct _Hashtable_hash_traits
259b1e83836Smrg     {
260b1e83836Smrg       static constexpr std::size_t
261b1e83836Smrg       __small_size_threshold() noexcept
262b1e83836Smrg       { return std::__is_fast_hash<_Hash>::value ? 0 : 20; }
263b1e83836Smrg     };
264b1e83836Smrg 
265b1e83836Smrg   /**
26648fb7bfaSmrg    *  struct _Hash_node_base
26748fb7bfaSmrg    *
26848fb7bfaSmrg    *  Nodes, used to wrap elements stored in the hash table.  A policy
26948fb7bfaSmrg    *  template parameter of class template _Hashtable controls whether
27048fb7bfaSmrg    *  nodes also store a hash code. In some cases (e.g. strings) this
27148fb7bfaSmrg    *  may be a performance win.
27248fb7bfaSmrg    */
27348fb7bfaSmrg   struct _Hash_node_base
27448fb7bfaSmrg   {
27548fb7bfaSmrg     _Hash_node_base* _M_nxt;
27648fb7bfaSmrg 
2774d5abbe8Smrg     _Hash_node_base() noexcept : _M_nxt() { }
27848fb7bfaSmrg 
2794d5abbe8Smrg     _Hash_node_base(_Hash_node_base* __next) noexcept : _M_nxt(__next) { }
2804d5abbe8Smrg   };
2814d5abbe8Smrg 
2824d5abbe8Smrg   /**
2834d5abbe8Smrg    *  struct _Hash_node_value_base
2844d5abbe8Smrg    *
2854d5abbe8Smrg    *  Node type with the value to store.
2864d5abbe8Smrg    */
2874d5abbe8Smrg   template<typename _Value>
288b1e83836Smrg     struct _Hash_node_value_base
2894d5abbe8Smrg     {
2904d5abbe8Smrg       typedef _Value value_type;
2914d5abbe8Smrg 
2924d5abbe8Smrg       __gnu_cxx::__aligned_buffer<_Value> _M_storage;
2934d5abbe8Smrg 
294*0a307195Smrg       [[__gnu__::__always_inline__]]
2954d5abbe8Smrg       _Value*
2964d5abbe8Smrg       _M_valptr() noexcept
2974d5abbe8Smrg       { return _M_storage._M_ptr(); }
2984d5abbe8Smrg 
299*0a307195Smrg       [[__gnu__::__always_inline__]]
3004d5abbe8Smrg       const _Value*
3014d5abbe8Smrg       _M_valptr() const noexcept
3024d5abbe8Smrg       { return _M_storage._M_ptr(); }
3034d5abbe8Smrg 
304*0a307195Smrg       [[__gnu__::__always_inline__]]
3054d5abbe8Smrg       _Value&
3064d5abbe8Smrg       _M_v() noexcept
3074d5abbe8Smrg       { return *_M_valptr(); }
3084d5abbe8Smrg 
309*0a307195Smrg       [[__gnu__::__always_inline__]]
3104d5abbe8Smrg       const _Value&
3114d5abbe8Smrg       _M_v() const noexcept
3124d5abbe8Smrg       { return *_M_valptr(); }
31348fb7bfaSmrg     };
31448fb7bfaSmrg 
31548fb7bfaSmrg   /**
316b1e83836Smrg    *  Primary template struct _Hash_node_code_cache.
317b1e83836Smrg    */
318b1e83836Smrg   template<bool _Cache_hash_code>
319b1e83836Smrg     struct _Hash_node_code_cache
320b1e83836Smrg     { };
321b1e83836Smrg 
322b1e83836Smrg   /**
323b1e83836Smrg    *  Specialization for node with cache, struct _Hash_node_code_cache.
324b1e83836Smrg    */
325b1e83836Smrg   template<>
326b1e83836Smrg     struct _Hash_node_code_cache<true>
327b1e83836Smrg     { std::size_t  _M_hash_code; };
328b1e83836Smrg 
329b1e83836Smrg   template<typename _Value, bool _Cache_hash_code>
330b1e83836Smrg     struct _Hash_node_value
331b1e83836Smrg     : _Hash_node_value_base<_Value>
332b1e83836Smrg     , _Hash_node_code_cache<_Cache_hash_code>
333b1e83836Smrg     { };
334b1e83836Smrg 
335b1e83836Smrg   /**
33648fb7bfaSmrg    *  Primary template struct _Hash_node.
33748fb7bfaSmrg    */
33848fb7bfaSmrg   template<typename _Value, bool _Cache_hash_code>
339b1e83836Smrg     struct _Hash_node
340b1e83836Smrg     : _Hash_node_base
341b1e83836Smrg     , _Hash_node_value<_Value, _Cache_hash_code>
3424fee23f9Smrg     {
34348fb7bfaSmrg       _Hash_node*
3444d5abbe8Smrg       _M_next() const noexcept
3454d5abbe8Smrg       { return static_cast<_Hash_node*>(this->_M_nxt); }
3464fee23f9Smrg     };
3474fee23f9Smrg 
34848fb7bfaSmrg   /// Base class for node iterators.
34948fb7bfaSmrg   template<typename _Value, bool _Cache_hash_code>
3504fee23f9Smrg     struct _Node_iterator_base
3514fee23f9Smrg     {
35248fb7bfaSmrg       using __node_type = _Hash_node<_Value, _Cache_hash_code>;
35348fb7bfaSmrg 
35448fb7bfaSmrg       __node_type* _M_cur;
35548fb7bfaSmrg 
356b1e83836Smrg       _Node_iterator_base() : _M_cur(nullptr) { }
3574d5abbe8Smrg       _Node_iterator_base(__node_type* __p) noexcept
3584fee23f9Smrg       : _M_cur(__p) { }
3594fee23f9Smrg 
3604fee23f9Smrg       void
3614d5abbe8Smrg       _M_incr() noexcept
36248fb7bfaSmrg       { _M_cur = _M_cur->_M_next(); }
3634fee23f9Smrg 
364b1e83836Smrg       friend bool
365b1e83836Smrg       operator==(const _Node_iterator_base& __x, const _Node_iterator_base& __y)
3664d5abbe8Smrg       noexcept
3674fee23f9Smrg       { return __x._M_cur == __y._M_cur; }
3684fee23f9Smrg 
369b1e83836Smrg #if __cpp_impl_three_way_comparison < 201907L
370b1e83836Smrg       friend bool
371b1e83836Smrg       operator!=(const _Node_iterator_base& __x, const _Node_iterator_base& __y)
3724d5abbe8Smrg       noexcept
3734fee23f9Smrg       { return __x._M_cur != __y._M_cur; }
374b1e83836Smrg #endif
375b1e83836Smrg     };
3764fee23f9Smrg 
37748fb7bfaSmrg   /// Node iterators, used to iterate through all the hashtable.
3784fee23f9Smrg   template<typename _Value, bool __constant_iterators, bool __cache>
3794fee23f9Smrg     struct _Node_iterator
3804fee23f9Smrg     : public _Node_iterator_base<_Value, __cache>
3814fee23f9Smrg     {
38248fb7bfaSmrg     private:
38348fb7bfaSmrg       using __base_type = _Node_iterator_base<_Value, __cache>;
38448fb7bfaSmrg       using __node_type = typename __base_type::__node_type;
38548fb7bfaSmrg 
38648fb7bfaSmrg     public:
387b1e83836Smrg       using value_type = _Value;
388b1e83836Smrg       using difference_type = std::ptrdiff_t;
389b1e83836Smrg       using iterator_category = std::forward_iterator_tag;
3904fee23f9Smrg 
391b1e83836Smrg       using pointer = __conditional_t<__constant_iterators,
392b1e83836Smrg 				      const value_type*, value_type*>;
39348fb7bfaSmrg 
394b1e83836Smrg       using reference = __conditional_t<__constant_iterators,
395b1e83836Smrg 					const value_type&, value_type&>;
39648fb7bfaSmrg 
397b1e83836Smrg       _Node_iterator() = default;
3984fee23f9Smrg 
3994fee23f9Smrg       explicit
4004d5abbe8Smrg       _Node_iterator(__node_type* __p) noexcept
40148fb7bfaSmrg       : __base_type(__p) { }
4024fee23f9Smrg 
4034fee23f9Smrg       reference
4044d5abbe8Smrg       operator*() const noexcept
4054d5abbe8Smrg       { return this->_M_cur->_M_v(); }
4064fee23f9Smrg 
4074fee23f9Smrg       pointer
4084d5abbe8Smrg       operator->() const noexcept
4094d5abbe8Smrg       { return this->_M_cur->_M_valptr(); }
4104fee23f9Smrg 
4114fee23f9Smrg       _Node_iterator&
4124d5abbe8Smrg       operator++() noexcept
4134fee23f9Smrg       {
4144fee23f9Smrg 	this->_M_incr();
4154fee23f9Smrg 	return *this;
4164fee23f9Smrg       }
4174fee23f9Smrg 
4184fee23f9Smrg       _Node_iterator
4194d5abbe8Smrg       operator++(int) noexcept
4204fee23f9Smrg       {
4214fee23f9Smrg 	_Node_iterator __tmp(*this);
4224fee23f9Smrg 	this->_M_incr();
4234fee23f9Smrg 	return __tmp;
4244fee23f9Smrg       }
4254fee23f9Smrg     };
4264fee23f9Smrg 
42748fb7bfaSmrg   /// Node const_iterators, used to iterate through all the hashtable.
4284fee23f9Smrg   template<typename _Value, bool __constant_iterators, bool __cache>
4294fee23f9Smrg     struct _Node_const_iterator
4304fee23f9Smrg     : public _Node_iterator_base<_Value, __cache>
4314fee23f9Smrg     {
43248fb7bfaSmrg     private:
43348fb7bfaSmrg       using __base_type = _Node_iterator_base<_Value, __cache>;
43448fb7bfaSmrg       using __node_type = typename __base_type::__node_type;
43548fb7bfaSmrg 
43648fb7bfaSmrg     public:
4374fee23f9Smrg       typedef _Value					value_type;
4384fee23f9Smrg       typedef std::ptrdiff_t				difference_type;
4394fee23f9Smrg       typedef std::forward_iterator_tag			iterator_category;
4404fee23f9Smrg 
441b1e83836Smrg       typedef const value_type*				pointer;
442b1e83836Smrg       typedef const value_type&				reference;
44348fb7bfaSmrg 
444b1e83836Smrg       _Node_const_iterator() = default;
4454fee23f9Smrg 
4464fee23f9Smrg       explicit
4474d5abbe8Smrg       _Node_const_iterator(__node_type* __p) noexcept
44848fb7bfaSmrg       : __base_type(__p) { }
4494fee23f9Smrg 
4504fee23f9Smrg       _Node_const_iterator(const _Node_iterator<_Value, __constant_iterators,
4514d5abbe8Smrg 			   __cache>& __x) noexcept
45248fb7bfaSmrg       : __base_type(__x._M_cur) { }
4534fee23f9Smrg 
4544fee23f9Smrg       reference
4554d5abbe8Smrg       operator*() const noexcept
4564d5abbe8Smrg       { return this->_M_cur->_M_v(); }
4574fee23f9Smrg 
4584fee23f9Smrg       pointer
4594d5abbe8Smrg       operator->() const noexcept
4604d5abbe8Smrg       { return this->_M_cur->_M_valptr(); }
4614fee23f9Smrg 
4624fee23f9Smrg       _Node_const_iterator&
4634d5abbe8Smrg       operator++() noexcept
4644fee23f9Smrg       {
4654fee23f9Smrg 	this->_M_incr();
4664fee23f9Smrg 	return *this;
4674fee23f9Smrg       }
4684fee23f9Smrg 
4694fee23f9Smrg       _Node_const_iterator
4704d5abbe8Smrg       operator++(int) noexcept
4714fee23f9Smrg       {
4724fee23f9Smrg 	_Node_const_iterator __tmp(*this);
4734fee23f9Smrg 	this->_M_incr();
4744fee23f9Smrg 	return __tmp;
4754fee23f9Smrg       }
4764fee23f9Smrg     };
4774fee23f9Smrg 
4784fee23f9Smrg   // Many of class template _Hashtable's template parameters are policy
4794fee23f9Smrg   // classes.  These are defaults for the policies.
4804fee23f9Smrg 
48148fb7bfaSmrg   /// Default range hashing function: use division to fold a large number
48248fb7bfaSmrg   /// into the range [0, N).
4834fee23f9Smrg   struct _Mod_range_hashing
4844fee23f9Smrg   {
4854fee23f9Smrg     typedef std::size_t first_argument_type;
4864fee23f9Smrg     typedef std::size_t second_argument_type;
4874fee23f9Smrg     typedef std::size_t result_type;
4884fee23f9Smrg 
4894fee23f9Smrg     result_type
4904d5abbe8Smrg     operator()(first_argument_type __num,
4914d5abbe8Smrg 	       second_argument_type __den) const noexcept
4924fee23f9Smrg     { return __num % __den; }
4934fee23f9Smrg   };
4944fee23f9Smrg 
49548fb7bfaSmrg   /// Default ranged hash function H.  In principle it should be a
49648fb7bfaSmrg   /// function object composed from objects of type H1 and H2 such that
49748fb7bfaSmrg   /// h(k, N) = h2(h1(k), N), but that would mean making extra copies of
49848fb7bfaSmrg   /// h1 and h2.  So instead we'll just use a tag to tell class template
49948fb7bfaSmrg   /// hashtable to do that composition.
5004fee23f9Smrg   struct _Default_ranged_hash { };
5014fee23f9Smrg 
50248fb7bfaSmrg   /// Default value for rehash policy.  Bucket size is (usually) the
50348fb7bfaSmrg   /// smallest prime that keeps the load factor small enough.
5044fee23f9Smrg   struct _Prime_rehash_policy
5054fee23f9Smrg   {
506fb8a8121Smrg     using __has_load_factor = true_type;
507b17d1066Smrg 
5084d5abbe8Smrg     _Prime_rehash_policy(float __z = 1.0) noexcept
50948fb7bfaSmrg     : _M_max_load_factor(__z), _M_next_resize(0) { }
5104fee23f9Smrg 
5114fee23f9Smrg     float
51248fb7bfaSmrg     max_load_factor() const noexcept
5134fee23f9Smrg     { return _M_max_load_factor; }
5144fee23f9Smrg 
5154fee23f9Smrg     // Return a bucket size no smaller than n.
5164fee23f9Smrg     std::size_t
5174fee23f9Smrg     _M_next_bkt(std::size_t __n) const;
5184fee23f9Smrg 
5194fee23f9Smrg     // Return a bucket count appropriate for n elements
5204fee23f9Smrg     std::size_t
52148fb7bfaSmrg     _M_bkt_for_elements(std::size_t __n) const
522b1e83836Smrg     { return __builtin_ceil(__n / (double)_M_max_load_factor); }
5234fee23f9Smrg 
5244fee23f9Smrg     // __n_bkt is current bucket count, __n_elt is current element count,
5254fee23f9Smrg     // and __n_ins is number of elements to be inserted.  Do we need to
5264fee23f9Smrg     // increase bucket count?  If so, return make_pair(true, n), where n
5274fee23f9Smrg     // is the new bucket count.  If not, return make_pair(false, 0).
5284fee23f9Smrg     std::pair<bool, std::size_t>
5294fee23f9Smrg     _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt,
5304fee23f9Smrg 		   std::size_t __n_ins) const;
5314fee23f9Smrg 
53248fb7bfaSmrg     typedef std::size_t _State;
53348fb7bfaSmrg 
53448fb7bfaSmrg     _State
53548fb7bfaSmrg     _M_state() const
53648fb7bfaSmrg     { return _M_next_resize; }
53748fb7bfaSmrg 
53848fb7bfaSmrg     void
5394d5abbe8Smrg     _M_reset() noexcept
5404d5abbe8Smrg     { _M_next_resize = 0; }
5414d5abbe8Smrg 
5424d5abbe8Smrg     void
54348fb7bfaSmrg     _M_reset(_State __state)
54448fb7bfaSmrg     { _M_next_resize = __state; }
54548fb7bfaSmrg 
54648fb7bfaSmrg     static const std::size_t _S_growth_factor = 2;
54748fb7bfaSmrg 
5484fee23f9Smrg     float		_M_max_load_factor;
5494fee23f9Smrg     mutable std::size_t	_M_next_resize;
5504fee23f9Smrg   };
5514fee23f9Smrg 
552b17d1066Smrg   /// Range hashing function assuming that second arg is a power of 2.
553b17d1066Smrg   struct _Mask_range_hashing
554b17d1066Smrg   {
555b17d1066Smrg     typedef std::size_t first_argument_type;
556b17d1066Smrg     typedef std::size_t second_argument_type;
557b17d1066Smrg     typedef std::size_t result_type;
558b17d1066Smrg 
559b17d1066Smrg     result_type
560b17d1066Smrg     operator()(first_argument_type __num,
561b17d1066Smrg 	       second_argument_type __den) const noexcept
562b17d1066Smrg     { return __num & (__den - 1); }
563b17d1066Smrg   };
564b17d1066Smrg 
565181254a7Smrg   /// Compute closest power of 2 not less than __n
566b17d1066Smrg   inline std::size_t
567b17d1066Smrg   __clp2(std::size_t __n) noexcept
568b17d1066Smrg   {
569b1e83836Smrg     using __gnu_cxx::__int_traits;
570fb8a8121Smrg     // Equivalent to return __n ? std::bit_ceil(__n) : 0;
571181254a7Smrg     if (__n < 2)
572181254a7Smrg       return __n;
573181254a7Smrg     const unsigned __lz = sizeof(size_t) > sizeof(long)
574181254a7Smrg       ? __builtin_clzll(__n - 1ull)
575181254a7Smrg       : __builtin_clzl(__n - 1ul);
576181254a7Smrg     // Doing two shifts avoids undefined behaviour when __lz == 0.
577b1e83836Smrg     return (size_t(1) << (__int_traits<size_t>::__digits - __lz - 1)) << 1;
578b17d1066Smrg   }
579b17d1066Smrg 
580b17d1066Smrg   /// Rehash policy providing power of 2 bucket numbers. Avoids modulo
581b17d1066Smrg   /// operations.
582b17d1066Smrg   struct _Power2_rehash_policy
583b17d1066Smrg   {
584fb8a8121Smrg     using __has_load_factor = true_type;
585b17d1066Smrg 
586b17d1066Smrg     _Power2_rehash_policy(float __z = 1.0) noexcept
587b17d1066Smrg     : _M_max_load_factor(__z), _M_next_resize(0) { }
588b17d1066Smrg 
589b17d1066Smrg     float
590b17d1066Smrg     max_load_factor() const noexcept
591b17d1066Smrg     { return _M_max_load_factor; }
592b17d1066Smrg 
593b17d1066Smrg     // Return a bucket size no smaller than n (as long as n is not above the
594b17d1066Smrg     // highest power of 2).
595b17d1066Smrg     std::size_t
596b17d1066Smrg     _M_next_bkt(std::size_t __n) noexcept
597b17d1066Smrg     {
598fb8a8121Smrg       if (__n == 0)
599fb8a8121Smrg 	// Special case on container 1st initialization with 0 bucket count
600fb8a8121Smrg 	// hint. We keep _M_next_resize to 0 to make sure that next time we
601fb8a8121Smrg 	// want to add an element allocation will take place.
602fb8a8121Smrg 	return 1;
603fb8a8121Smrg 
604b17d1066Smrg       const auto __max_width = std::min<size_t>(sizeof(size_t), 8);
605b17d1066Smrg       const auto __max_bkt = size_t(1) << (__max_width * __CHAR_BIT__ - 1);
606b17d1066Smrg       std::size_t __res = __clp2(__n);
607b17d1066Smrg 
608b17d1066Smrg       if (__res == 0)
609b17d1066Smrg 	__res = __max_bkt;
610fb8a8121Smrg       else if (__res == 1)
611fb8a8121Smrg 	// If __res is 1 we force it to 2 to make sure there will be an
612fb8a8121Smrg 	// allocation so that nothing need to be stored in the initial
613fb8a8121Smrg 	// single bucket
614fb8a8121Smrg 	__res = 2;
615b17d1066Smrg 
616b17d1066Smrg       if (__res == __max_bkt)
617b17d1066Smrg 	// Set next resize to the max value so that we never try to rehash again
618b17d1066Smrg 	// as we already reach the biggest possible bucket number.
619b17d1066Smrg 	// Note that it might result in max_load_factor not being respected.
620b1e83836Smrg 	_M_next_resize = size_t(-1);
621b17d1066Smrg       else
622b17d1066Smrg 	_M_next_resize
623b1e83836Smrg 	  = __builtin_floor(__res * (double)_M_max_load_factor);
624b17d1066Smrg 
625b17d1066Smrg       return __res;
626b17d1066Smrg     }
627b17d1066Smrg 
628b17d1066Smrg     // Return a bucket count appropriate for n elements
629b17d1066Smrg     std::size_t
630b17d1066Smrg     _M_bkt_for_elements(std::size_t __n) const noexcept
631b1e83836Smrg     { return __builtin_ceil(__n / (double)_M_max_load_factor); }
632b17d1066Smrg 
633b17d1066Smrg     // __n_bkt is current bucket count, __n_elt is current element count,
634b17d1066Smrg     // and __n_ins is number of elements to be inserted.  Do we need to
635b17d1066Smrg     // increase bucket count?  If so, return make_pair(true, n), where n
636b17d1066Smrg     // is the new bucket count.  If not, return make_pair(false, 0).
637b17d1066Smrg     std::pair<bool, std::size_t>
638b17d1066Smrg     _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt,
639b17d1066Smrg 		   std::size_t __n_ins) noexcept
640b17d1066Smrg     {
641fb8a8121Smrg       if (__n_elt + __n_ins > _M_next_resize)
642b17d1066Smrg 	{
643fb8a8121Smrg 	  // If _M_next_resize is 0 it means that we have nothing allocated so
644fb8a8121Smrg 	  // far and that we start inserting elements. In this case we start
645fb8a8121Smrg 	  // with an initial bucket size of 11.
646b1e83836Smrg 	  double __min_bkts
647fb8a8121Smrg 	    = std::max<std::size_t>(__n_elt + __n_ins, _M_next_resize ? 0 : 11)
648b1e83836Smrg 	      / (double)_M_max_load_factor;
649b17d1066Smrg 	  if (__min_bkts >= __n_bkt)
650fb8a8121Smrg 	    return { true,
651b1e83836Smrg 	      _M_next_bkt(std::max<std::size_t>(__builtin_floor(__min_bkts) + 1,
652fb8a8121Smrg 						__n_bkt * _S_growth_factor)) };
653b17d1066Smrg 
654b17d1066Smrg 	  _M_next_resize
655b1e83836Smrg 	    = __builtin_floor(__n_bkt * (double)_M_max_load_factor);
656fb8a8121Smrg 	  return { false, 0 };
657b17d1066Smrg 	}
658b17d1066Smrg       else
659fb8a8121Smrg 	return { false, 0 };
660b17d1066Smrg     }
661b17d1066Smrg 
662b17d1066Smrg     typedef std::size_t _State;
663b17d1066Smrg 
664b17d1066Smrg     _State
665b17d1066Smrg     _M_state() const noexcept
666b17d1066Smrg     { return _M_next_resize; }
667b17d1066Smrg 
668b17d1066Smrg     void
669b17d1066Smrg     _M_reset() noexcept
670b17d1066Smrg     { _M_next_resize = 0; }
671b17d1066Smrg 
672b17d1066Smrg     void
673b17d1066Smrg     _M_reset(_State __state) noexcept
674b17d1066Smrg     { _M_next_resize = __state; }
675b17d1066Smrg 
676b17d1066Smrg     static const std::size_t _S_growth_factor = 2;
677b17d1066Smrg 
678b17d1066Smrg     float	_M_max_load_factor;
679b17d1066Smrg     std::size_t	_M_next_resize;
680b17d1066Smrg   };
681b17d1066Smrg 
6824fee23f9Smrg   // Base classes for std::_Hashtable.  We define these base classes
68348fb7bfaSmrg   // because in some cases we want to do different things depending on
68448fb7bfaSmrg   // the value of a policy class.  In some cases the policy class
6854fee23f9Smrg   // affects which member functions and nested typedefs are defined;
6864fee23f9Smrg   // we handle that by specializing base class templates.  Several of
6874fee23f9Smrg   // the base class templates need to access other members of class
68848fb7bfaSmrg   // template _Hashtable, so we use a variant of the "Curiously
68948fb7bfaSmrg   // Recurring Template Pattern" (CRTP) technique.
6904fee23f9Smrg 
69148fb7bfaSmrg   /**
69248fb7bfaSmrg    *  Primary class template _Map_base.
69348fb7bfaSmrg    *
694b1e83836Smrg    *  If the hashtable has a value type of the form pair<const T1, T2> and
695b1e83836Smrg    *  a key extraction policy (_ExtractKey) that returns the first part
69648fb7bfaSmrg    *  of the pair, the hashtable gets a mapped_type typedef.  If it
69748fb7bfaSmrg    *  satisfies those criteria and also has unique keys, then it also
69848fb7bfaSmrg    *  gets an operator[].
69948fb7bfaSmrg    */
70048fb7bfaSmrg   template<typename _Key, typename _Value, typename _Alloc,
70148fb7bfaSmrg 	   typename _ExtractKey, typename _Equal,
702b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
70348fb7bfaSmrg 	   typename _RehashPolicy, typename _Traits,
70448fb7bfaSmrg 	   bool _Unique_keys = _Traits::__unique_keys::value>
7054fee23f9Smrg     struct _Map_base { };
7064fee23f9Smrg 
707b1e83836Smrg   /// Partial specialization, __unique_keys set to false, std::pair value type.
708b1e83836Smrg   template<typename _Key, typename _Val, typename _Alloc, typename _Equal,
709b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
71048fb7bfaSmrg 	   typename _RehashPolicy, typename _Traits>
711b1e83836Smrg     struct _Map_base<_Key, pair<const _Key, _Val>, _Alloc, _Select1st, _Equal,
712b1e83836Smrg 		     _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits, false>
7134fee23f9Smrg     {
714b1e83836Smrg       using mapped_type = _Val;
7154fee23f9Smrg     };
7164fee23f9Smrg 
71748fb7bfaSmrg   /// Partial specialization, __unique_keys set to true.
718b1e83836Smrg   template<typename _Key, typename _Val, typename _Alloc, typename _Equal,
719b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
72048fb7bfaSmrg 	   typename _RehashPolicy, typename _Traits>
721b1e83836Smrg     struct _Map_base<_Key, pair<const _Key, _Val>, _Alloc, _Select1st, _Equal,
722b1e83836Smrg 		     _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits, true>
7234fee23f9Smrg     {
72448fb7bfaSmrg     private:
725b1e83836Smrg       using __hashtable_base = _Hashtable_base<_Key, pair<const _Key, _Val>,
726b1e83836Smrg 					       _Select1st, _Equal, _Hash,
727b1e83836Smrg 					       _RangeHash, _Unused,
72848fb7bfaSmrg 					       _Traits>;
72948fb7bfaSmrg 
730b1e83836Smrg       using __hashtable = _Hashtable<_Key, pair<const _Key, _Val>, _Alloc,
731b1e83836Smrg 				     _Select1st, _Equal, _Hash, _RangeHash,
732b1e83836Smrg 				     _Unused, _RehashPolicy, _Traits>;
73348fb7bfaSmrg 
73448fb7bfaSmrg       using __hash_code = typename __hashtable_base::__hash_code;
73548fb7bfaSmrg 
73648fb7bfaSmrg     public:
73748fb7bfaSmrg       using key_type = typename __hashtable_base::key_type;
738b1e83836Smrg       using mapped_type = _Val;
7394fee23f9Smrg 
7404fee23f9Smrg       mapped_type&
74148fb7bfaSmrg       operator[](const key_type& __k);
74248fb7bfaSmrg 
74348fb7bfaSmrg       mapped_type&
74448fb7bfaSmrg       operator[](key_type&& __k);
7454fee23f9Smrg 
7464fee23f9Smrg       // _GLIBCXX_RESOLVE_LIB_DEFECTS
7474fee23f9Smrg       // DR 761. unordered_map needs an at() member function.
7484fee23f9Smrg       mapped_type&
749b1e83836Smrg       at(const key_type& __k)
750b1e83836Smrg       {
751b1e83836Smrg 	auto __ite = static_cast<__hashtable*>(this)->find(__k);
752b1e83836Smrg 	if (!__ite._M_cur)
753b1e83836Smrg 	  __throw_out_of_range(__N("unordered_map::at"));
754b1e83836Smrg 	return __ite->second;
755b1e83836Smrg       }
7564fee23f9Smrg 
7574fee23f9Smrg       const mapped_type&
758b1e83836Smrg       at(const key_type& __k) const
759b1e83836Smrg       {
760b1e83836Smrg 	auto __ite = static_cast<const __hashtable*>(this)->find(__k);
761b1e83836Smrg 	if (!__ite._M_cur)
762b1e83836Smrg 	  __throw_out_of_range(__N("unordered_map::at"));
763b1e83836Smrg 	return __ite->second;
764b1e83836Smrg       }
7654fee23f9Smrg     };
7664fee23f9Smrg 
767b1e83836Smrg   template<typename _Key, typename _Val, typename _Alloc, typename _Equal,
768b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
76948fb7bfaSmrg 	   typename _RehashPolicy, typename _Traits>
7704d5abbe8Smrg     auto
771b1e83836Smrg     _Map_base<_Key, pair<const _Key, _Val>, _Alloc, _Select1st, _Equal,
772b1e83836Smrg 	      _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits, true>::
77348fb7bfaSmrg     operator[](const key_type& __k)
7744d5abbe8Smrg     -> mapped_type&
7754fee23f9Smrg     {
77648fb7bfaSmrg       __hashtable* __h = static_cast<__hashtable*>(this);
77748fb7bfaSmrg       __hash_code __code = __h->_M_hash_code(__k);
778b1e83836Smrg       std::size_t __bkt = __h->_M_bucket_index(__code);
779b1e83836Smrg       if (auto __node = __h->_M_find_node(__bkt, __k, __code))
780fb8a8121Smrg 	return __node->_M_v().second;
7814fee23f9Smrg 
782fb8a8121Smrg       typename __hashtable::_Scoped_node __node {
783fb8a8121Smrg 	__h,
784fb8a8121Smrg 	std::piecewise_construct,
78548fb7bfaSmrg 	std::tuple<const key_type&>(__k),
786fb8a8121Smrg 	std::tuple<>()
787fb8a8121Smrg       };
788fb8a8121Smrg       auto __pos
789b1e83836Smrg 	= __h->_M_insert_unique_node(__bkt, __code, __node._M_node);
790fb8a8121Smrg       __node._M_node = nullptr;
791fb8a8121Smrg       return __pos->second;
7924fee23f9Smrg     }
7934fee23f9Smrg 
794b1e83836Smrg   template<typename _Key, typename _Val, typename _Alloc, typename _Equal,
795b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
79648fb7bfaSmrg 	   typename _RehashPolicy, typename _Traits>
7974d5abbe8Smrg     auto
798b1e83836Smrg     _Map_base<_Key, pair<const _Key, _Val>, _Alloc, _Select1st, _Equal,
799b1e83836Smrg 	      _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits, true>::
80048fb7bfaSmrg     operator[](key_type&& __k)
8014d5abbe8Smrg     -> mapped_type&
8024fee23f9Smrg     {
80348fb7bfaSmrg       __hashtable* __h = static_cast<__hashtable*>(this);
80448fb7bfaSmrg       __hash_code __code = __h->_M_hash_code(__k);
805b1e83836Smrg       std::size_t __bkt = __h->_M_bucket_index(__code);
806b1e83836Smrg       if (auto __node = __h->_M_find_node(__bkt, __k, __code))
807fb8a8121Smrg 	return __node->_M_v().second;
8084fee23f9Smrg 
809fb8a8121Smrg       typename __hashtable::_Scoped_node __node {
810fb8a8121Smrg 	__h,
811fb8a8121Smrg 	std::piecewise_construct,
81248fb7bfaSmrg 	std::forward_as_tuple(std::move(__k)),
813fb8a8121Smrg 	std::tuple<>()
814fb8a8121Smrg       };
815fb8a8121Smrg       auto __pos
816b1e83836Smrg 	= __h->_M_insert_unique_node(__bkt, __code, __node._M_node);
817fb8a8121Smrg       __node._M_node = nullptr;
818fb8a8121Smrg       return __pos->second;
81948fb7bfaSmrg     }
82048fb7bfaSmrg 
821b1e83836Smrg   // Partial specialization for unordered_map<const T, U>, see PR 104174.
822b1e83836Smrg   template<typename _Key, typename _Val, typename _Alloc, typename _Equal,
823b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
824b1e83836Smrg 	   typename _RehashPolicy, typename _Traits, bool __uniq>
825b1e83836Smrg     struct _Map_base<const _Key, pair<const _Key, _Val>,
826b1e83836Smrg 		     _Alloc, _Select1st, _Equal, _Hash,
827b1e83836Smrg 		     _RangeHash, _Unused, _RehashPolicy, _Traits, __uniq>
828b1e83836Smrg     : _Map_base<_Key, pair<const _Key, _Val>, _Alloc, _Select1st, _Equal, _Hash,
829b1e83836Smrg 		_RangeHash, _Unused, _RehashPolicy, _Traits, __uniq>
830b1e83836Smrg     { };
8314fee23f9Smrg 
83248fb7bfaSmrg   /**
83348fb7bfaSmrg    *  Primary class template _Insert_base.
83448fb7bfaSmrg    *
835b17d1066Smrg    *  Defines @c insert member functions appropriate to all _Hashtables.
83648fb7bfaSmrg    */
83748fb7bfaSmrg   template<typename _Key, typename _Value, typename _Alloc,
83848fb7bfaSmrg 	   typename _ExtractKey, typename _Equal,
839b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
84048fb7bfaSmrg 	   typename _RehashPolicy, typename _Traits>
84148fb7bfaSmrg     struct _Insert_base
8424fee23f9Smrg     {
8434d5abbe8Smrg     protected:
84448fb7bfaSmrg       using __hashtable_base = _Hashtable_base<_Key, _Value, _ExtractKey,
845b1e83836Smrg 					       _Equal, _Hash, _RangeHash,
846b1e83836Smrg 					       _Unused, _Traits>;
847b1e83836Smrg 
848b1e83836Smrg       using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
849b1e83836Smrg 				     _Hash, _RangeHash,
850b1e83836Smrg 				     _Unused, _RehashPolicy, _Traits>;
851b1e83836Smrg 
852b1e83836Smrg       using __hash_cached = typename _Traits::__hash_cached;
853b1e83836Smrg       using __constant_iterators = typename _Traits::__constant_iterators;
854b1e83836Smrg 
855b1e83836Smrg       using __hashtable_alloc = _Hashtable_alloc<
856b1e83836Smrg 	__alloc_rebind<_Alloc, _Hash_node<_Value,
857b1e83836Smrg 					  __hash_cached::value>>>;
85848fb7bfaSmrg 
85948fb7bfaSmrg       using value_type = typename __hashtable_base::value_type;
86048fb7bfaSmrg       using size_type = typename __hashtable_base::size_type;
86148fb7bfaSmrg 
862b1e83836Smrg       using __unique_keys = typename _Traits::__unique_keys;
863b1e83836Smrg       using __node_alloc_type = typename __hashtable_alloc::__node_alloc_type;
8644d5abbe8Smrg       using __node_gen_type = _AllocNode<__node_alloc_type>;
86548fb7bfaSmrg 
86648fb7bfaSmrg       __hashtable&
86748fb7bfaSmrg       _M_conjure_hashtable()
86848fb7bfaSmrg       { return *(static_cast<__hashtable*>(this)); }
86948fb7bfaSmrg 
8704d5abbe8Smrg       template<typename _InputIterator, typename _NodeGetter>
8714d5abbe8Smrg 	void
8724d5abbe8Smrg 	_M_insert_range(_InputIterator __first, _InputIterator __last,
873b1e83836Smrg 			const _NodeGetter&, true_type __uks);
874a3e9eb18Smrg 
875a3e9eb18Smrg       template<typename _InputIterator, typename _NodeGetter>
876a3e9eb18Smrg 	void
877a3e9eb18Smrg 	_M_insert_range(_InputIterator __first, _InputIterator __last,
878b1e83836Smrg 			const _NodeGetter&, false_type __uks);
8794d5abbe8Smrg 
8804d5abbe8Smrg     public:
881b1e83836Smrg       using iterator = _Node_iterator<_Value, __constant_iterators::value,
882b1e83836Smrg 				      __hash_cached::value>;
883b1e83836Smrg 
884b1e83836Smrg       using const_iterator = _Node_const_iterator<_Value,
885b1e83836Smrg 						  __constant_iterators::value,
886b1e83836Smrg 						  __hash_cached::value>;
887b1e83836Smrg 
888b1e83836Smrg       using __ireturn_type = __conditional_t<__unique_keys::value,
889b1e83836Smrg 					     std::pair<iterator, bool>,
890b1e83836Smrg 					     iterator>;
891b1e83836Smrg 
89248fb7bfaSmrg       __ireturn_type
89348fb7bfaSmrg       insert(const value_type& __v)
89448fb7bfaSmrg       {
89548fb7bfaSmrg 	__hashtable& __h = _M_conjure_hashtable();
8964d5abbe8Smrg 	__node_gen_type __node_gen(__h);
897b1e83836Smrg 	return __h._M_insert(__v, __node_gen, __unique_keys{});
89848fb7bfaSmrg       }
89948fb7bfaSmrg 
90048fb7bfaSmrg       iterator
9014d5abbe8Smrg       insert(const_iterator __hint, const value_type& __v)
9024d5abbe8Smrg       {
9034d5abbe8Smrg 	__hashtable& __h = _M_conjure_hashtable();
9044d5abbe8Smrg 	__node_gen_type __node_gen(__h);
905b1e83836Smrg 	return __h._M_insert(__hint, __v, __node_gen, __unique_keys{});
906b1e83836Smrg       }
907b1e83836Smrg 
908b1e83836Smrg       template<typename _KType, typename... _Args>
909b1e83836Smrg 	std::pair<iterator, bool>
910b1e83836Smrg 	try_emplace(const_iterator, _KType&& __k, _Args&&... __args)
911b1e83836Smrg 	{
912b1e83836Smrg 	  __hashtable& __h = _M_conjure_hashtable();
913b1e83836Smrg 	  auto __code = __h._M_hash_code(__k);
914b1e83836Smrg 	  std::size_t __bkt = __h._M_bucket_index(__code);
915b1e83836Smrg 	  if (auto __node = __h._M_find_node(__bkt, __k, __code))
916b1e83836Smrg 	    return { iterator(__node), false };
917b1e83836Smrg 
918b1e83836Smrg 	  typename __hashtable::_Scoped_node __node {
919b1e83836Smrg 	    &__h,
920b1e83836Smrg 	    std::piecewise_construct,
921b1e83836Smrg 	    std::forward_as_tuple(std::forward<_KType>(__k)),
922b1e83836Smrg 	    std::forward_as_tuple(std::forward<_Args>(__args)...)
923b1e83836Smrg 	    };
924b1e83836Smrg 	  auto __it
925b1e83836Smrg 	    = __h._M_insert_unique_node(__bkt, __code, __node._M_node);
926b1e83836Smrg 	  __node._M_node = nullptr;
927b1e83836Smrg 	  return { __it, true };
9284d5abbe8Smrg 	}
92948fb7bfaSmrg 
93048fb7bfaSmrg       void
93148fb7bfaSmrg       insert(initializer_list<value_type> __l)
93248fb7bfaSmrg       { this->insert(__l.begin(), __l.end()); }
93348fb7bfaSmrg 
93448fb7bfaSmrg       template<typename _InputIterator>
93548fb7bfaSmrg 	void
9364d5abbe8Smrg 	insert(_InputIterator __first, _InputIterator __last)
9374d5abbe8Smrg 	{
9384d5abbe8Smrg 	  __hashtable& __h = _M_conjure_hashtable();
9394d5abbe8Smrg 	  __node_gen_type __node_gen(__h);
940b1e83836Smrg 	  return _M_insert_range(__first, __last, __node_gen, __unique_keys{});
9414d5abbe8Smrg 	}
94248fb7bfaSmrg     };
94348fb7bfaSmrg 
94448fb7bfaSmrg   template<typename _Key, typename _Value, typename _Alloc,
94548fb7bfaSmrg 	   typename _ExtractKey, typename _Equal,
946b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
94748fb7bfaSmrg 	   typename _RehashPolicy, typename _Traits>
9484d5abbe8Smrg     template<typename _InputIterator, typename _NodeGetter>
94948fb7bfaSmrg       void
950b1e83836Smrg       _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
951b1e83836Smrg 		   _Hash, _RangeHash, _Unused,
95248fb7bfaSmrg 		   _RehashPolicy, _Traits>::
9534d5abbe8Smrg       _M_insert_range(_InputIterator __first, _InputIterator __last,
954b1e83836Smrg 		      const _NodeGetter& __node_gen, true_type __uks)
955a3e9eb18Smrg       {
956a3e9eb18Smrg 	__hashtable& __h = _M_conjure_hashtable();
957a3e9eb18Smrg 	for (; __first != __last; ++__first)
958b1e83836Smrg 	  __h._M_insert(*__first, __node_gen, __uks);
959a3e9eb18Smrg       }
960a3e9eb18Smrg 
961a3e9eb18Smrg   template<typename _Key, typename _Value, typename _Alloc,
962a3e9eb18Smrg 	   typename _ExtractKey, typename _Equal,
963b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
964a3e9eb18Smrg 	   typename _RehashPolicy, typename _Traits>
965a3e9eb18Smrg     template<typename _InputIterator, typename _NodeGetter>
966a3e9eb18Smrg       void
967b1e83836Smrg       _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
968b1e83836Smrg 		   _Hash, _RangeHash, _Unused,
969a3e9eb18Smrg 		   _RehashPolicy, _Traits>::
970a3e9eb18Smrg       _M_insert_range(_InputIterator __first, _InputIterator __last,
971b1e83836Smrg 		      const _NodeGetter& __node_gen, false_type __uks)
97248fb7bfaSmrg       {
97348fb7bfaSmrg 	using __rehash_type = typename __hashtable::__rehash_type;
97448fb7bfaSmrg 	using __rehash_state = typename __hashtable::__rehash_state;
97548fb7bfaSmrg 	using pair_type = std::pair<bool, std::size_t>;
97648fb7bfaSmrg 
97748fb7bfaSmrg 	size_type __n_elt = __detail::__distance_fw(__first, __last);
978a3e9eb18Smrg 	if (__n_elt == 0)
979a3e9eb18Smrg 	  return;
98048fb7bfaSmrg 
98148fb7bfaSmrg 	__hashtable& __h = _M_conjure_hashtable();
98248fb7bfaSmrg 	__rehash_type& __rehash = __h._M_rehash_policy;
98348fb7bfaSmrg 	const __rehash_state& __saved_state = __rehash._M_state();
98448fb7bfaSmrg 	pair_type __do_rehash = __rehash._M_need_rehash(__h._M_bucket_count,
98548fb7bfaSmrg 							__h._M_element_count,
98648fb7bfaSmrg 							__n_elt);
98748fb7bfaSmrg 
98848fb7bfaSmrg 	if (__do_rehash.first)
98948fb7bfaSmrg 	  __h._M_rehash(__do_rehash.second, __saved_state);
99048fb7bfaSmrg 
99148fb7bfaSmrg 	for (; __first != __last; ++__first)
992b1e83836Smrg 	  __h._M_insert(*__first, __node_gen, __uks);
99348fb7bfaSmrg       }
99448fb7bfaSmrg 
99548fb7bfaSmrg   /**
99648fb7bfaSmrg    *  Primary class template _Insert.
99748fb7bfaSmrg    *
998b17d1066Smrg    *  Defines @c insert member functions that depend on _Hashtable policies,
999b17d1066Smrg    *  via partial specializations.
100048fb7bfaSmrg    */
100148fb7bfaSmrg   template<typename _Key, typename _Value, typename _Alloc,
100248fb7bfaSmrg 	   typename _ExtractKey, typename _Equal,
1003b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
100448fb7bfaSmrg 	   typename _RehashPolicy, typename _Traits,
1005b17d1066Smrg 	   bool _Constant_iterators = _Traits::__constant_iterators::value>
100648fb7bfaSmrg     struct _Insert;
100748fb7bfaSmrg 
100848fb7bfaSmrg   /// Specialization.
100948fb7bfaSmrg   template<typename _Key, typename _Value, typename _Alloc,
101048fb7bfaSmrg 	   typename _ExtractKey, typename _Equal,
1011b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
101248fb7bfaSmrg 	   typename _RehashPolicy, typename _Traits>
1013b1e83836Smrg     struct _Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1014b1e83836Smrg 		   _Hash, _RangeHash, _Unused,
1015b17d1066Smrg 		   _RehashPolicy, _Traits, true>
101648fb7bfaSmrg     : public _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1017b1e83836Smrg 			  _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>
101848fb7bfaSmrg     {
101948fb7bfaSmrg       using __base_type = _Insert_base<_Key, _Value, _Alloc, _ExtractKey,
1020b1e83836Smrg 				       _Equal, _Hash, _RangeHash, _Unused,
102148fb7bfaSmrg 				       _RehashPolicy, _Traits>;
1022b17d1066Smrg 
102348fb7bfaSmrg       using value_type = typename __base_type::value_type;
102448fb7bfaSmrg       using iterator = typename __base_type::iterator;
102548fb7bfaSmrg       using const_iterator =  typename __base_type::const_iterator;
1026b1e83836Smrg       using __ireturn_type = typename __base_type::__ireturn_type;
102748fb7bfaSmrg 
102848fb7bfaSmrg       using __unique_keys = typename __base_type::__unique_keys;
102948fb7bfaSmrg       using __hashtable = typename __base_type::__hashtable;
10304d5abbe8Smrg       using __node_gen_type = typename __base_type::__node_gen_type;
103148fb7bfaSmrg 
103248fb7bfaSmrg       using __base_type::insert;
103348fb7bfaSmrg 
1034b17d1066Smrg       __ireturn_type
103548fb7bfaSmrg       insert(value_type&& __v)
103648fb7bfaSmrg       {
103748fb7bfaSmrg 	__hashtable& __h = this->_M_conjure_hashtable();
10384d5abbe8Smrg 	__node_gen_type __node_gen(__h);
1039b1e83836Smrg 	return __h._M_insert(std::move(__v), __node_gen, __unique_keys{});
104048fb7bfaSmrg       }
104148fb7bfaSmrg 
104248fb7bfaSmrg       iterator
10434d5abbe8Smrg       insert(const_iterator __hint, value_type&& __v)
10444d5abbe8Smrg       {
10454d5abbe8Smrg 	__hashtable& __h = this->_M_conjure_hashtable();
10464d5abbe8Smrg 	__node_gen_type __node_gen(__h);
10474d5abbe8Smrg 	return __h._M_insert(__hint, std::move(__v), __node_gen,
1048b1e83836Smrg 			     __unique_keys{});
10494d5abbe8Smrg       }
105048fb7bfaSmrg     };
105148fb7bfaSmrg 
105248fb7bfaSmrg   /// Specialization.
105348fb7bfaSmrg   template<typename _Key, typename _Value, typename _Alloc,
105448fb7bfaSmrg 	   typename _ExtractKey, typename _Equal,
1055b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
105648fb7bfaSmrg 	   typename _RehashPolicy, typename _Traits>
1057b1e83836Smrg     struct _Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1058b1e83836Smrg 		   _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits, false>
105948fb7bfaSmrg     : public _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1060b1e83836Smrg 			  _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>
106148fb7bfaSmrg     {
106248fb7bfaSmrg       using __base_type = _Insert_base<_Key, _Value, _Alloc, _ExtractKey,
1063b1e83836Smrg 				       _Equal, _Hash, _RangeHash, _Unused,
106448fb7bfaSmrg 				       _RehashPolicy, _Traits>;
106548fb7bfaSmrg       using value_type = typename __base_type::value_type;
106648fb7bfaSmrg       using iterator = typename __base_type::iterator;
106748fb7bfaSmrg       using const_iterator =  typename __base_type::const_iterator;
106848fb7bfaSmrg 
106948fb7bfaSmrg       using __unique_keys = typename __base_type::__unique_keys;
107048fb7bfaSmrg       using __hashtable = typename __base_type::__hashtable;
107148fb7bfaSmrg       using __ireturn_type = typename __base_type::__ireturn_type;
107248fb7bfaSmrg 
107348fb7bfaSmrg       using __base_type::insert;
107448fb7bfaSmrg 
107548fb7bfaSmrg       template<typename _Pair>
107648fb7bfaSmrg 	using __is_cons = std::is_constructible<value_type, _Pair&&>;
107748fb7bfaSmrg 
107848fb7bfaSmrg       template<typename _Pair>
107948fb7bfaSmrg 	using _IFcons = std::enable_if<__is_cons<_Pair>::value>;
108048fb7bfaSmrg 
108148fb7bfaSmrg       template<typename _Pair>
108248fb7bfaSmrg 	using _IFconsp = typename _IFcons<_Pair>::type;
108348fb7bfaSmrg 
108448fb7bfaSmrg       template<typename _Pair, typename = _IFconsp<_Pair>>
108548fb7bfaSmrg 	__ireturn_type
108648fb7bfaSmrg 	insert(_Pair&& __v)
108748fb7bfaSmrg 	{
108848fb7bfaSmrg 	  __hashtable& __h = this->_M_conjure_hashtable();
1089b1e83836Smrg 	  return __h._M_emplace(__unique_keys{}, std::forward<_Pair>(__v));
109048fb7bfaSmrg 	}
109148fb7bfaSmrg 
109248fb7bfaSmrg       template<typename _Pair, typename = _IFconsp<_Pair>>
109348fb7bfaSmrg 	iterator
10944d5abbe8Smrg 	insert(const_iterator __hint, _Pair&& __v)
10954d5abbe8Smrg 	{
10964d5abbe8Smrg 	  __hashtable& __h = this->_M_conjure_hashtable();
1097b1e83836Smrg 	  return __h._M_emplace(__hint, __unique_keys{},
10984d5abbe8Smrg 				std::forward<_Pair>(__v));
10994d5abbe8Smrg 	}
110048fb7bfaSmrg    };
110148fb7bfaSmrg 
1102b17d1066Smrg   template<typename _Policy>
1103b17d1066Smrg     using __has_load_factor = typename _Policy::__has_load_factor;
1104b17d1066Smrg 
110548fb7bfaSmrg   /**
110648fb7bfaSmrg    *  Primary class template  _Rehash_base.
110748fb7bfaSmrg    *
110848fb7bfaSmrg    *  Give hashtable the max_load_factor functions and reserve iff the
1109b17d1066Smrg    *  rehash policy supports it.
111048fb7bfaSmrg   */
111148fb7bfaSmrg   template<typename _Key, typename _Value, typename _Alloc,
111248fb7bfaSmrg 	   typename _ExtractKey, typename _Equal,
1113b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
1114b17d1066Smrg 	   typename _RehashPolicy, typename _Traits,
1115b17d1066Smrg 	   typename =
1116fb8a8121Smrg 	     __detected_or_t<false_type, __has_load_factor, _RehashPolicy>>
111748fb7bfaSmrg     struct _Rehash_base;
111848fb7bfaSmrg 
1119b17d1066Smrg   /// Specialization when rehash policy doesn't provide load factor management.
112048fb7bfaSmrg   template<typename _Key, typename _Value, typename _Alloc,
112148fb7bfaSmrg 	   typename _ExtractKey, typename _Equal,
1122b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
1123b17d1066Smrg 	   typename _RehashPolicy, typename _Traits>
112448fb7bfaSmrg     struct _Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1125b1e83836Smrg 			_Hash, _RangeHash, _Unused, _RehashPolicy, _Traits,
1126b1e83836Smrg 			false_type /* Has load factor */>
1127b17d1066Smrg     {
1128b17d1066Smrg     };
1129b17d1066Smrg 
1130b17d1066Smrg   /// Specialization when rehash policy provide load factor management.
1131b17d1066Smrg   template<typename _Key, typename _Value, typename _Alloc,
1132b17d1066Smrg 	   typename _ExtractKey, typename _Equal,
1133b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
1134b17d1066Smrg 	   typename _RehashPolicy, typename _Traits>
1135b17d1066Smrg     struct _Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1136b1e83836Smrg 			_Hash, _RangeHash, _Unused, _RehashPolicy, _Traits,
1137b1e83836Smrg 			true_type /* Has load factor */>
113848fb7bfaSmrg     {
1139b1e83836Smrg     private:
114048fb7bfaSmrg       using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
1141b1e83836Smrg 				     _Equal, _Hash, _RangeHash, _Unused,
1142b17d1066Smrg 				     _RehashPolicy, _Traits>;
114348fb7bfaSmrg 
1144b1e83836Smrg     public:
11454fee23f9Smrg       float
114648fb7bfaSmrg       max_load_factor() const noexcept
11474fee23f9Smrg       {
114848fb7bfaSmrg 	const __hashtable* __this = static_cast<const __hashtable*>(this);
11494fee23f9Smrg 	return __this->__rehash_policy().max_load_factor();
11504fee23f9Smrg       }
11514fee23f9Smrg 
11524fee23f9Smrg       void
11534fee23f9Smrg       max_load_factor(float __z)
11544fee23f9Smrg       {
115548fb7bfaSmrg 	__hashtable* __this = static_cast<__hashtable*>(this);
1156b17d1066Smrg 	__this->__rehash_policy(_RehashPolicy(__z));
11574fee23f9Smrg       }
11584fee23f9Smrg 
11594fee23f9Smrg       void
11604fee23f9Smrg       reserve(std::size_t __n)
11614fee23f9Smrg       {
116248fb7bfaSmrg 	__hashtable* __this = static_cast<__hashtable*>(this);
1163fb8a8121Smrg 	__this->rehash(__this->__rehash_policy()._M_bkt_for_elements(__n));
11644fee23f9Smrg       }
11654fee23f9Smrg     };
11664fee23f9Smrg 
116748fb7bfaSmrg   /**
116848fb7bfaSmrg    *  Primary class template _Hashtable_ebo_helper.
116948fb7bfaSmrg    *
11704d5abbe8Smrg    *  Helper class using EBO when it is not forbidden (the type is not
11714d5abbe8Smrg    *  final) and when it is worth it (the type is empty.)
117248fb7bfaSmrg    */
117348fb7bfaSmrg   template<int _Nm, typename _Tp,
117448fb7bfaSmrg 	   bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)>
117548fb7bfaSmrg     struct _Hashtable_ebo_helper;
11764fee23f9Smrg 
117748fb7bfaSmrg   /// Specialization using EBO.
117848fb7bfaSmrg   template<int _Nm, typename _Tp>
117948fb7bfaSmrg     struct _Hashtable_ebo_helper<_Nm, _Tp, true>
118048fb7bfaSmrg     : private _Tp
118148fb7bfaSmrg     {
1182a448f87cSmrg       _Hashtable_ebo_helper() noexcept(noexcept(_Tp())) : _Tp() { }
118348fb7bfaSmrg 
11844d5abbe8Smrg       template<typename _OtherTp>
11854d5abbe8Smrg 	_Hashtable_ebo_helper(_OtherTp&& __tp)
11864d5abbe8Smrg 	: _Tp(std::forward<_OtherTp>(__tp))
118748fb7bfaSmrg 	{ }
118848fb7bfaSmrg 
1189fb8a8121Smrg       const _Tp& _M_cget() const { return static_cast<const _Tp&>(*this); }
1190fb8a8121Smrg       _Tp& _M_get() { return static_cast<_Tp&>(*this); }
119148fb7bfaSmrg     };
119248fb7bfaSmrg 
119348fb7bfaSmrg   /// Specialization not using EBO.
119448fb7bfaSmrg   template<int _Nm, typename _Tp>
119548fb7bfaSmrg     struct _Hashtable_ebo_helper<_Nm, _Tp, false>
119648fb7bfaSmrg     {
119748fb7bfaSmrg       _Hashtable_ebo_helper() = default;
119848fb7bfaSmrg 
11994d5abbe8Smrg       template<typename _OtherTp>
12004d5abbe8Smrg 	_Hashtable_ebo_helper(_OtherTp&& __tp)
12014d5abbe8Smrg 	: _M_tp(std::forward<_OtherTp>(__tp))
120248fb7bfaSmrg 	{ }
120348fb7bfaSmrg 
1204fb8a8121Smrg       const _Tp& _M_cget() const { return _M_tp; }
1205fb8a8121Smrg       _Tp& _M_get() { return _M_tp; }
120648fb7bfaSmrg 
120748fb7bfaSmrg     private:
1208a448f87cSmrg       _Tp _M_tp{};
120948fb7bfaSmrg     };
121048fb7bfaSmrg 
121148fb7bfaSmrg   /**
121248fb7bfaSmrg    *  Primary class template _Local_iterator_base.
121348fb7bfaSmrg    *
121448fb7bfaSmrg    *  Base class for local iterators, used to iterate within a bucket
121548fb7bfaSmrg    *  but not between buckets.
121648fb7bfaSmrg    */
121748fb7bfaSmrg   template<typename _Key, typename _Value, typename _ExtractKey,
1218b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
121948fb7bfaSmrg 	   bool __cache_hash_code>
122048fb7bfaSmrg     struct _Local_iterator_base;
122148fb7bfaSmrg 
122248fb7bfaSmrg   /**
122348fb7bfaSmrg    *  Primary class template _Hash_code_base.
122448fb7bfaSmrg    *
122548fb7bfaSmrg    *  Encapsulates two policy issues that aren't quite orthogonal.
122648fb7bfaSmrg    *   (1) the difference between using a ranged hash function and using
122748fb7bfaSmrg    *       the combination of a hash function and a range-hashing function.
122848fb7bfaSmrg    *       In the former case we don't have such things as hash codes, so
122948fb7bfaSmrg    *       we have a dummy type as placeholder.
123048fb7bfaSmrg    *   (2) Whether or not we cache hash codes.  Caching hash codes is
123148fb7bfaSmrg    *       meaningless if we have a ranged hash function.
123248fb7bfaSmrg    *
123348fb7bfaSmrg    *  We also put the key extraction objects here, for convenience.
123448fb7bfaSmrg    *  Each specialization derives from one or more of the template
123548fb7bfaSmrg    *  parameters to benefit from Ebo. This is important as this type
123648fb7bfaSmrg    *  is inherited in some cases by the _Local_iterator_base type used
123748fb7bfaSmrg    *  to implement local_iterator and const_local_iterator. As with
123848fb7bfaSmrg    *  any iterator type we prefer to make it as small as possible.
123948fb7bfaSmrg    */
124048fb7bfaSmrg   template<typename _Key, typename _Value, typename _ExtractKey,
1241b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
12424fee23f9Smrg 	   bool __cache_hash_code>
1243b1e83836Smrg     struct _Hash_code_base
1244b1e83836Smrg     : private _Hashtable_ebo_helper<1, _Hash>
12454fee23f9Smrg     {
124648fb7bfaSmrg     private:
124748fb7bfaSmrg       using __ebo_hash = _Hashtable_ebo_helper<1, _Hash>;
124848fb7bfaSmrg 
1249b1e83836Smrg       // Gives the local iterator implementation access to _M_bucket_index().
1250b1e83836Smrg       friend struct _Local_iterator_base<_Key, _Value, _ExtractKey,
1251b1e83836Smrg 					 _Hash, _RangeHash, _Unused, false>;
1252b1e83836Smrg 
1253b1e83836Smrg     public:
1254b1e83836Smrg       typedef _Hash					hasher;
1255b1e83836Smrg 
1256b1e83836Smrg       hasher
1257b1e83836Smrg       hash_function() const
1258b1e83836Smrg       { return _M_hash(); }
1259b1e83836Smrg 
12604fee23f9Smrg     protected:
1261b1e83836Smrg       typedef std::size_t 				__hash_code;
12624fee23f9Smrg 
12634d5abbe8Smrg       // We need the default constructor for the local iterators and _Hashtable
12644d5abbe8Smrg       // default constructor.
126548fb7bfaSmrg       _Hash_code_base() = default;
12664fee23f9Smrg 
1267b1e83836Smrg       _Hash_code_base(const _Hash& __hash) : __ebo_hash(__hash) { }
126848fb7bfaSmrg 
126948fb7bfaSmrg       __hash_code
1270b1e83836Smrg       _M_hash_code(const _Key& __k) const
1271b1e83836Smrg       {
1272b1e83836Smrg 	static_assert(__is_invocable<const _Hash&, const _Key&>{},
1273b1e83836Smrg 	    "hash function must be invocable with an argument of key type");
1274b1e83836Smrg 	return _M_hash()(__k);
1275b1e83836Smrg       }
1276b1e83836Smrg 
1277b1e83836Smrg       template<typename _Kt>
1278b1e83836Smrg 	__hash_code
1279b1e83836Smrg 	_M_hash_code_tr(const _Kt& __k) const
1280b1e83836Smrg 	{
1281b1e83836Smrg 	  static_assert(__is_invocable<const _Hash&, const _Kt&>{},
1282b1e83836Smrg 	    "hash function must be invocable with an argument of key type");
1283b1e83836Smrg 	  return _M_hash()(__k);
1284b1e83836Smrg 	}
1285b1e83836Smrg 
1286b1e83836Smrg       __hash_code
1287b1e83836Smrg       _M_hash_code(const _Hash_node_value<_Value, false>& __n) const
1288b1e83836Smrg       { return _M_hash_code(_ExtractKey{}(__n._M_v())); }
1289b1e83836Smrg 
1290b1e83836Smrg       __hash_code
1291b1e83836Smrg       _M_hash_code(const _Hash_node_value<_Value, true>& __n) const
1292b1e83836Smrg       { return __n._M_hash_code; }
12934fee23f9Smrg 
12944fee23f9Smrg       std::size_t
1295b1e83836Smrg       _M_bucket_index(__hash_code __c, std::size_t __bkt_count) const
1296b1e83836Smrg       { return _RangeHash{}(__c, __bkt_count); }
1297b1e83836Smrg 
1298b1e83836Smrg       std::size_t
1299b1e83836Smrg       _M_bucket_index(const _Hash_node_value<_Value, false>& __n,
1300fb8a8121Smrg 		      std::size_t __bkt_count) const
1301b1e83836Smrg 	noexcept( noexcept(declval<const _Hash&>()(declval<const _Key&>()))
1302b1e83836Smrg 		  && noexcept(declval<const _RangeHash&>()((__hash_code)0,
1303b1e83836Smrg 							   (std::size_t)0)) )
1304b1e83836Smrg       {
1305b1e83836Smrg 	return _RangeHash{}(_M_hash_code(_ExtractKey{}(__n._M_v())),
1306b1e83836Smrg 			    __bkt_count);
1307b1e83836Smrg       }
13084fee23f9Smrg 
13094fee23f9Smrg       std::size_t
1310b1e83836Smrg       _M_bucket_index(const _Hash_node_value<_Value, true>& __n,
1311b1e83836Smrg 		      std::size_t __bkt_count) const
1312b1e83836Smrg 	noexcept( noexcept(declval<const _RangeHash&>()((__hash_code)0,
13134d5abbe8Smrg 							(std::size_t)0)) )
1314b1e83836Smrg       { return _RangeHash{}(__n._M_hash_code, __bkt_count); }
13154fee23f9Smrg 
13164fee23f9Smrg       void
1317b1e83836Smrg       _M_store_code(_Hash_node_code_cache<false>&, __hash_code) const
13184fee23f9Smrg       { }
13194fee23f9Smrg 
13204fee23f9Smrg       void
1321b1e83836Smrg       _M_copy_code(_Hash_node_code_cache<false>&,
1322b1e83836Smrg 		   const _Hash_node_code_cache<false>&) const
13234fee23f9Smrg       { }
13244fee23f9Smrg 
13254fee23f9Smrg       void
1326b1e83836Smrg       _M_store_code(_Hash_node_code_cache<true>& __n, __hash_code __c) const
1327b1e83836Smrg       { __n._M_hash_code = __c; }
1328b1e83836Smrg 
1329b1e83836Smrg       void
1330b1e83836Smrg       _M_copy_code(_Hash_node_code_cache<true>& __to,
1331b1e83836Smrg 		   const _Hash_node_code_cache<true>& __from) const
1332b1e83836Smrg       { __to._M_hash_code = __from._M_hash_code; }
1333b1e83836Smrg 
1334b1e83836Smrg       void
13354fee23f9Smrg       _M_swap(_Hash_code_base& __x)
1336b1e83836Smrg       { std::swap(__ebo_hash::_M_get(), __x.__ebo_hash::_M_get()); }
133748fb7bfaSmrg 
133848fb7bfaSmrg       const _Hash&
1339b1e83836Smrg       _M_hash() const { return __ebo_hash::_M_cget(); }
134048fb7bfaSmrg     };
134148fb7bfaSmrg 
13424d5abbe8Smrg   /// Partial specialization used when nodes contain a cached hash code.
134348fb7bfaSmrg   template<typename _Key, typename _Value, typename _ExtractKey,
1344b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused>
134548fb7bfaSmrg     struct _Local_iterator_base<_Key, _Value, _ExtractKey,
1346b1e83836Smrg 				_Hash, _RangeHash, _Unused, true>
1347b1e83836Smrg     : public _Node_iterator_base<_Value, true>
134848fb7bfaSmrg     {
134948fb7bfaSmrg     protected:
1350b1e83836Smrg       using __base_node_iter = _Node_iterator_base<_Value, true>;
135148fb7bfaSmrg       using __hash_code_base = _Hash_code_base<_Key, _Value, _ExtractKey,
1352b1e83836Smrg 					      _Hash, _RangeHash, _Unused, true>;
135348fb7bfaSmrg 
135448fb7bfaSmrg       _Local_iterator_base() = default;
1355b1e83836Smrg       _Local_iterator_base(const __hash_code_base&,
135648fb7bfaSmrg 			   _Hash_node<_Value, true>* __p,
135748fb7bfaSmrg 			   std::size_t __bkt, std::size_t __bkt_count)
1358b1e83836Smrg       : __base_node_iter(__p), _M_bucket(__bkt), _M_bucket_count(__bkt_count)
1359b1e83836Smrg       { }
136048fb7bfaSmrg 
136148fb7bfaSmrg       void
136248fb7bfaSmrg       _M_incr()
136348fb7bfaSmrg       {
1364b1e83836Smrg 	__base_node_iter::_M_incr();
1365b1e83836Smrg 	if (this->_M_cur)
136648fb7bfaSmrg 	  {
136748fb7bfaSmrg 	    std::size_t __bkt
1368b1e83836Smrg 	      = _RangeHash{}(this->_M_cur->_M_hash_code, _M_bucket_count);
136948fb7bfaSmrg 	    if (__bkt != _M_bucket)
1370b1e83836Smrg 	      this->_M_cur = nullptr;
137148fb7bfaSmrg 	  }
137248fb7bfaSmrg       }
137348fb7bfaSmrg 
137448fb7bfaSmrg       std::size_t _M_bucket;
137548fb7bfaSmrg       std::size_t _M_bucket_count;
13764d5abbe8Smrg 
13774d5abbe8Smrg     public:
13784d5abbe8Smrg       std::size_t
13794d5abbe8Smrg       _M_get_bucket() const { return _M_bucket; }  // for debug mode
138048fb7bfaSmrg     };
138148fb7bfaSmrg 
13824d5abbe8Smrg   // Uninitialized storage for a _Hash_code_base.
13834d5abbe8Smrg   // This type is DefaultConstructible and Assignable even if the
13844d5abbe8Smrg   // _Hash_code_base type isn't, so that _Local_iterator_base<..., false>
13854d5abbe8Smrg   // can be DefaultConstructible and Assignable.
13864d5abbe8Smrg   template<typename _Tp, bool _IsEmpty = std::is_empty<_Tp>::value>
13874d5abbe8Smrg     struct _Hash_code_storage
13884d5abbe8Smrg     {
13894d5abbe8Smrg       __gnu_cxx::__aligned_buffer<_Tp> _M_storage;
13904d5abbe8Smrg 
13914d5abbe8Smrg       _Tp*
13924d5abbe8Smrg       _M_h() { return _M_storage._M_ptr(); }
13934d5abbe8Smrg 
13944d5abbe8Smrg       const _Tp*
13954d5abbe8Smrg       _M_h() const { return _M_storage._M_ptr(); }
13964d5abbe8Smrg     };
13974d5abbe8Smrg 
13984d5abbe8Smrg   // Empty partial specialization for empty _Hash_code_base types.
13994d5abbe8Smrg   template<typename _Tp>
14004d5abbe8Smrg     struct _Hash_code_storage<_Tp, true>
14014d5abbe8Smrg     {
14024d5abbe8Smrg       static_assert( std::is_empty<_Tp>::value, "Type must be empty" );
14034d5abbe8Smrg 
14044d5abbe8Smrg       // As _Tp is an empty type there will be no bytes written/read through
14054d5abbe8Smrg       // the cast pointer, so no strict-aliasing violation.
14064d5abbe8Smrg       _Tp*
14074d5abbe8Smrg       _M_h() { return reinterpret_cast<_Tp*>(this); }
14084d5abbe8Smrg 
14094d5abbe8Smrg       const _Tp*
14104d5abbe8Smrg       _M_h() const { return reinterpret_cast<const _Tp*>(this); }
14114d5abbe8Smrg     };
14124d5abbe8Smrg 
14134d5abbe8Smrg   template<typename _Key, typename _Value, typename _ExtractKey,
1414b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused>
14154d5abbe8Smrg     using __hash_code_for_local_iter
14164d5abbe8Smrg       = _Hash_code_storage<_Hash_code_base<_Key, _Value, _ExtractKey,
1417b1e83836Smrg 					   _Hash, _RangeHash, _Unused, false>>;
14184d5abbe8Smrg 
14194d5abbe8Smrg   // Partial specialization used when hash codes are not cached
142048fb7bfaSmrg   template<typename _Key, typename _Value, typename _ExtractKey,
1421b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused>
142248fb7bfaSmrg     struct _Local_iterator_base<_Key, _Value, _ExtractKey,
1423b1e83836Smrg 				_Hash, _RangeHash, _Unused, false>
1424b1e83836Smrg     : __hash_code_for_local_iter<_Key, _Value, _ExtractKey, _Hash, _RangeHash,
1425b1e83836Smrg 				 _Unused>
1426b1e83836Smrg     , _Node_iterator_base<_Value, false>
142748fb7bfaSmrg     {
142848fb7bfaSmrg     protected:
142948fb7bfaSmrg       using __hash_code_base = _Hash_code_base<_Key, _Value, _ExtractKey,
1430b1e83836Smrg 					     _Hash, _RangeHash, _Unused, false>;
1431b1e83836Smrg       using __node_iter_base = _Node_iterator_base<_Value, false>;
143248fb7bfaSmrg 
14334d5abbe8Smrg       _Local_iterator_base() : _M_bucket_count(-1) { }
14344d5abbe8Smrg 
143548fb7bfaSmrg       _Local_iterator_base(const __hash_code_base& __base,
143648fb7bfaSmrg 			   _Hash_node<_Value, false>* __p,
143748fb7bfaSmrg 			   std::size_t __bkt, std::size_t __bkt_count)
1438b1e83836Smrg       : __node_iter_base(__p), _M_bucket(__bkt), _M_bucket_count(__bkt_count)
14394d5abbe8Smrg       { _M_init(__base); }
14404d5abbe8Smrg 
14414d5abbe8Smrg       ~_Local_iterator_base()
14424d5abbe8Smrg       {
1443b1e83836Smrg 	if (_M_bucket_count != size_t(-1))
14444d5abbe8Smrg 	  _M_destroy();
14454d5abbe8Smrg       }
14464d5abbe8Smrg 
14474d5abbe8Smrg       _Local_iterator_base(const _Local_iterator_base& __iter)
1448b1e83836Smrg       : __node_iter_base(__iter._M_cur), _M_bucket(__iter._M_bucket)
1449b1e83836Smrg       , _M_bucket_count(__iter._M_bucket_count)
14504d5abbe8Smrg       {
1451b1e83836Smrg 	if (_M_bucket_count != size_t(-1))
14524d5abbe8Smrg 	  _M_init(*__iter._M_h());
14534d5abbe8Smrg       }
14544d5abbe8Smrg 
14554d5abbe8Smrg       _Local_iterator_base&
14564d5abbe8Smrg       operator=(const _Local_iterator_base& __iter)
14574d5abbe8Smrg       {
14584d5abbe8Smrg 	if (_M_bucket_count != -1)
14594d5abbe8Smrg 	  _M_destroy();
1460b1e83836Smrg 	this->_M_cur = __iter._M_cur;
14614d5abbe8Smrg 	_M_bucket = __iter._M_bucket;
14624d5abbe8Smrg 	_M_bucket_count = __iter._M_bucket_count;
14634d5abbe8Smrg 	if (_M_bucket_count != -1)
14644d5abbe8Smrg 	  _M_init(*__iter._M_h());
14654d5abbe8Smrg 	return *this;
14664d5abbe8Smrg       }
146748fb7bfaSmrg 
146848fb7bfaSmrg       void
146948fb7bfaSmrg       _M_incr()
147048fb7bfaSmrg       {
1471b1e83836Smrg 	__node_iter_base::_M_incr();
1472b1e83836Smrg 	if (this->_M_cur)
147348fb7bfaSmrg 	  {
1474b1e83836Smrg 	    std::size_t __bkt = this->_M_h()->_M_bucket_index(*this->_M_cur,
14754d5abbe8Smrg 							      _M_bucket_count);
147648fb7bfaSmrg 	    if (__bkt != _M_bucket)
1477b1e83836Smrg 	      this->_M_cur = nullptr;
147848fb7bfaSmrg 	  }
147948fb7bfaSmrg       }
148048fb7bfaSmrg 
148148fb7bfaSmrg       std::size_t _M_bucket;
148248fb7bfaSmrg       std::size_t _M_bucket_count;
14834d5abbe8Smrg 
14844d5abbe8Smrg       void
14854d5abbe8Smrg       _M_init(const __hash_code_base& __base)
14864d5abbe8Smrg       { ::new(this->_M_h()) __hash_code_base(__base); }
14874d5abbe8Smrg 
14884d5abbe8Smrg       void
14894d5abbe8Smrg       _M_destroy() { this->_M_h()->~__hash_code_base(); }
14904d5abbe8Smrg 
14914d5abbe8Smrg     public:
14924d5abbe8Smrg       std::size_t
14934d5abbe8Smrg       _M_get_bucket() const { return _M_bucket; }  // for debug mode
149448fb7bfaSmrg     };
149548fb7bfaSmrg 
149648fb7bfaSmrg   /// local iterators
149748fb7bfaSmrg   template<typename _Key, typename _Value, typename _ExtractKey,
1498b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
149948fb7bfaSmrg 	   bool __constant_iterators, bool __cache>
150048fb7bfaSmrg     struct _Local_iterator
150148fb7bfaSmrg     : public _Local_iterator_base<_Key, _Value, _ExtractKey,
1502b1e83836Smrg 				  _Hash, _RangeHash, _Unused, __cache>
150348fb7bfaSmrg     {
150448fb7bfaSmrg     private:
150548fb7bfaSmrg       using __base_type = _Local_iterator_base<_Key, _Value, _ExtractKey,
1506b1e83836Smrg 					   _Hash, _RangeHash, _Unused, __cache>;
150748fb7bfaSmrg       using __hash_code_base = typename __base_type::__hash_code_base;
1508b1e83836Smrg 
150948fb7bfaSmrg     public:
1510b1e83836Smrg       using value_type = _Value;
1511b1e83836Smrg       using pointer = __conditional_t<__constant_iterators,
1512b1e83836Smrg 				      const value_type*, value_type*>;
1513b1e83836Smrg       using reference = __conditional_t<__constant_iterators,
1514b1e83836Smrg 					const value_type&, value_type&>;
1515b1e83836Smrg       using difference_type = ptrdiff_t;
1516b1e83836Smrg       using iterator_category = forward_iterator_tag;
151748fb7bfaSmrg 
151848fb7bfaSmrg       _Local_iterator() = default;
151948fb7bfaSmrg 
152048fb7bfaSmrg       _Local_iterator(const __hash_code_base& __base,
1521fb8a8121Smrg 		      _Hash_node<_Value, __cache>* __n,
152248fb7bfaSmrg 		      std::size_t __bkt, std::size_t __bkt_count)
1523fb8a8121Smrg       : __base_type(__base, __n, __bkt, __bkt_count)
152448fb7bfaSmrg       { }
152548fb7bfaSmrg 
152648fb7bfaSmrg       reference
152748fb7bfaSmrg       operator*() const
15284d5abbe8Smrg       { return this->_M_cur->_M_v(); }
152948fb7bfaSmrg 
153048fb7bfaSmrg       pointer
153148fb7bfaSmrg       operator->() const
15324d5abbe8Smrg       { return this->_M_cur->_M_valptr(); }
153348fb7bfaSmrg 
153448fb7bfaSmrg       _Local_iterator&
153548fb7bfaSmrg       operator++()
153648fb7bfaSmrg       {
153748fb7bfaSmrg 	this->_M_incr();
153848fb7bfaSmrg 	return *this;
153948fb7bfaSmrg       }
154048fb7bfaSmrg 
154148fb7bfaSmrg       _Local_iterator
154248fb7bfaSmrg       operator++(int)
154348fb7bfaSmrg       {
154448fb7bfaSmrg 	_Local_iterator __tmp(*this);
154548fb7bfaSmrg 	this->_M_incr();
154648fb7bfaSmrg 	return __tmp;
154748fb7bfaSmrg       }
154848fb7bfaSmrg     };
154948fb7bfaSmrg 
155048fb7bfaSmrg   /// local const_iterators
155148fb7bfaSmrg   template<typename _Key, typename _Value, typename _ExtractKey,
1552b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
155348fb7bfaSmrg 	   bool __constant_iterators, bool __cache>
155448fb7bfaSmrg     struct _Local_const_iterator
155548fb7bfaSmrg     : public _Local_iterator_base<_Key, _Value, _ExtractKey,
1556b1e83836Smrg 				  _Hash, _RangeHash, _Unused, __cache>
155748fb7bfaSmrg     {
155848fb7bfaSmrg     private:
155948fb7bfaSmrg       using __base_type = _Local_iterator_base<_Key, _Value, _ExtractKey,
1560b1e83836Smrg 					   _Hash, _RangeHash, _Unused, __cache>;
156148fb7bfaSmrg       using __hash_code_base = typename __base_type::__hash_code_base;
156248fb7bfaSmrg 
156348fb7bfaSmrg     public:
156448fb7bfaSmrg       typedef _Value					value_type;
1565b1e83836Smrg       typedef const value_type*				pointer;
1566b1e83836Smrg       typedef const value_type&				reference;
156748fb7bfaSmrg       typedef std::ptrdiff_t				difference_type;
156848fb7bfaSmrg       typedef std::forward_iterator_tag			iterator_category;
156948fb7bfaSmrg 
157048fb7bfaSmrg       _Local_const_iterator() = default;
157148fb7bfaSmrg 
157248fb7bfaSmrg       _Local_const_iterator(const __hash_code_base& __base,
1573fb8a8121Smrg 			    _Hash_node<_Value, __cache>* __n,
157448fb7bfaSmrg 			    std::size_t __bkt, std::size_t __bkt_count)
1575fb8a8121Smrg       : __base_type(__base, __n, __bkt, __bkt_count)
157648fb7bfaSmrg       { }
157748fb7bfaSmrg 
157848fb7bfaSmrg       _Local_const_iterator(const _Local_iterator<_Key, _Value, _ExtractKey,
1579b1e83836Smrg 						  _Hash, _RangeHash, _Unused,
158048fb7bfaSmrg 						  __constant_iterators,
158148fb7bfaSmrg 						  __cache>& __x)
158248fb7bfaSmrg       : __base_type(__x)
158348fb7bfaSmrg       { }
158448fb7bfaSmrg 
158548fb7bfaSmrg       reference
158648fb7bfaSmrg       operator*() const
15874d5abbe8Smrg       { return this->_M_cur->_M_v(); }
158848fb7bfaSmrg 
158948fb7bfaSmrg       pointer
159048fb7bfaSmrg       operator->() const
15914d5abbe8Smrg       { return this->_M_cur->_M_valptr(); }
159248fb7bfaSmrg 
159348fb7bfaSmrg       _Local_const_iterator&
159448fb7bfaSmrg       operator++()
159548fb7bfaSmrg       {
159648fb7bfaSmrg 	this->_M_incr();
159748fb7bfaSmrg 	return *this;
159848fb7bfaSmrg       }
159948fb7bfaSmrg 
160048fb7bfaSmrg       _Local_const_iterator
160148fb7bfaSmrg       operator++(int)
160248fb7bfaSmrg       {
160348fb7bfaSmrg 	_Local_const_iterator __tmp(*this);
160448fb7bfaSmrg 	this->_M_incr();
160548fb7bfaSmrg 	return __tmp;
160648fb7bfaSmrg       }
160748fb7bfaSmrg     };
160848fb7bfaSmrg 
160948fb7bfaSmrg   /**
161048fb7bfaSmrg    *  Primary class template _Hashtable_base.
161148fb7bfaSmrg    *
161248fb7bfaSmrg    *  Helper class adding management of _Equal functor to
161348fb7bfaSmrg    *  _Hash_code_base type.
161448fb7bfaSmrg    *
161548fb7bfaSmrg    *  Base class templates are:
161648fb7bfaSmrg    *    - __detail::_Hash_code_base
161748fb7bfaSmrg    *    - __detail::_Hashtable_ebo_helper
161848fb7bfaSmrg    */
1619b1e83836Smrg   template<typename _Key, typename _Value, typename _ExtractKey,
1620b1e83836Smrg 	   typename _Equal, typename _Hash, typename _RangeHash,
1621b1e83836Smrg 	   typename _Unused, typename _Traits>
162248fb7bfaSmrg     struct _Hashtable_base
1623b1e83836Smrg     : public _Hash_code_base<_Key, _Value, _ExtractKey, _Hash, _RangeHash,
1624b1e83836Smrg 			     _Unused, _Traits::__hash_cached::value>,
162548fb7bfaSmrg       private _Hashtable_ebo_helper<0, _Equal>
162648fb7bfaSmrg     {
162748fb7bfaSmrg     public:
162848fb7bfaSmrg       typedef _Key					key_type;
162948fb7bfaSmrg       typedef _Value					value_type;
163048fb7bfaSmrg       typedef _Equal					key_equal;
163148fb7bfaSmrg       typedef std::size_t				size_type;
163248fb7bfaSmrg       typedef std::ptrdiff_t				difference_type;
163348fb7bfaSmrg 
163448fb7bfaSmrg       using __traits_type = _Traits;
163548fb7bfaSmrg       using __hash_cached = typename __traits_type::__hash_cached;
163648fb7bfaSmrg 
163748fb7bfaSmrg       using __hash_code_base = _Hash_code_base<_Key, _Value, _ExtractKey,
1638b1e83836Smrg 					       _Hash, _RangeHash, _Unused,
163948fb7bfaSmrg 					       __hash_cached::value>;
164048fb7bfaSmrg 
164148fb7bfaSmrg       using __hash_code = typename __hash_code_base::__hash_code;
164248fb7bfaSmrg 
164348fb7bfaSmrg     private:
164448fb7bfaSmrg       using _EqualEBO = _Hashtable_ebo_helper<0, _Equal>;
1645fb8a8121Smrg 
1646fb8a8121Smrg       static bool
1647b1e83836Smrg       _S_equals(__hash_code, const _Hash_node_code_cache<false>&)
1648fb8a8121Smrg       { return true; }
1649fb8a8121Smrg 
1650fb8a8121Smrg       static bool
1651b1e83836Smrg       _S_node_equals(const _Hash_node_code_cache<false>&,
1652b1e83836Smrg 		     const _Hash_node_code_cache<false>&)
1653b1e83836Smrg       { return true; }
1654b1e83836Smrg 
1655b1e83836Smrg       static bool
1656b1e83836Smrg       _S_equals(__hash_code __c, const _Hash_node_code_cache<true>& __n)
1657fb8a8121Smrg       { return __c == __n._M_hash_code; }
1658b1e83836Smrg 
1659b1e83836Smrg       static bool
1660b1e83836Smrg       _S_node_equals(const _Hash_node_code_cache<true>& __lhn,
1661b1e83836Smrg 		     const _Hash_node_code_cache<true>& __rhn)
1662b1e83836Smrg       { return __lhn._M_hash_code == __rhn._M_hash_code; }
166348fb7bfaSmrg 
16644fee23f9Smrg     protected:
16654d5abbe8Smrg       _Hashtable_base() = default;
1666a448f87cSmrg 
1667b1e83836Smrg       _Hashtable_base(const _Hash& __hash, const _Equal& __eq)
1668b1e83836Smrg       : __hash_code_base(__hash), _EqualEBO(__eq)
166948fb7bfaSmrg       { }
16704fee23f9Smrg 
16714fee23f9Smrg       bool
1672b1e83836Smrg       _M_key_equals(const _Key& __k,
1673b1e83836Smrg 		    const _Hash_node_value<_Value,
1674b1e83836Smrg 					   __hash_cached::value>& __n) const
16754fee23f9Smrg       {
1676a3e9eb18Smrg 	static_assert(__is_invocable<const _Equal&, const _Key&, const _Key&>{},
1677a3e9eb18Smrg 	  "key equality predicate must be invocable with two arguments of "
1678a3e9eb18Smrg 	  "key type");
1679b1e83836Smrg 	return _M_eq()(__k, _ExtractKey{}(__n._M_v()));
1680b1e83836Smrg       }
1681b1e83836Smrg 
1682b1e83836Smrg       template<typename _Kt>
1683b1e83836Smrg 	bool
1684b1e83836Smrg 	_M_key_equals_tr(const _Kt& __k,
1685b1e83836Smrg 			 const _Hash_node_value<_Value,
1686b1e83836Smrg 					     __hash_cached::value>& __n) const
1687b1e83836Smrg 	{
1688b1e83836Smrg 	  static_assert(
1689b1e83836Smrg 	    __is_invocable<const _Equal&, const _Kt&, const _Key&>{},
1690b1e83836Smrg 	    "key equality predicate must be invocable with two arguments of "
1691b1e83836Smrg 	    "key type");
1692b1e83836Smrg 	  return _M_eq()(__k, _ExtractKey{}(__n._M_v()));
1693b1e83836Smrg 	}
1694b1e83836Smrg 
1695b1e83836Smrg       bool
1696b1e83836Smrg       _M_equals(const _Key& __k, __hash_code __c,
1697b1e83836Smrg 		const _Hash_node_value<_Value, __hash_cached::value>& __n) const
1698b1e83836Smrg       { return _S_equals(__c, __n) && _M_key_equals(__k, __n); }
1699b1e83836Smrg 
1700b1e83836Smrg       template<typename _Kt>
1701b1e83836Smrg 	bool
1702b1e83836Smrg 	_M_equals_tr(const _Kt& __k, __hash_code __c,
1703b1e83836Smrg 		     const _Hash_node_value<_Value,
1704b1e83836Smrg 					    __hash_cached::value>& __n) const
1705b1e83836Smrg 	{ return _S_equals(__c, __n) && _M_key_equals_tr(__k, __n); }
1706b1e83836Smrg 
1707b1e83836Smrg       bool
1708b1e83836Smrg       _M_node_equals(
1709b1e83836Smrg 	const _Hash_node_value<_Value, __hash_cached::value>& __lhn,
1710b1e83836Smrg 	const _Hash_node_value<_Value, __hash_cached::value>& __rhn) const
1711b1e83836Smrg       {
1712b1e83836Smrg 	return _S_node_equals(__lhn, __rhn)
1713b1e83836Smrg 	  && _M_key_equals(_ExtractKey{}(__lhn._M_v()), __rhn);
17144fee23f9Smrg       }
17154fee23f9Smrg 
171648fb7bfaSmrg       void
171748fb7bfaSmrg       _M_swap(_Hashtable_base& __x)
17184fee23f9Smrg       {
171948fb7bfaSmrg 	__hash_code_base::_M_swap(__x);
1720fb8a8121Smrg 	std::swap(_EqualEBO::_M_get(), __x._EqualEBO::_M_get());
172148fb7bfaSmrg       }
17224fee23f9Smrg 
172348fb7bfaSmrg       const _Equal&
1724fb8a8121Smrg       _M_eq() const { return _EqualEBO::_M_cget(); }
172548fb7bfaSmrg     };
172648fb7bfaSmrg 
172748fb7bfaSmrg   /**
172848fb7bfaSmrg    *  Primary class template  _Equality.
172948fb7bfaSmrg    *
173048fb7bfaSmrg    *  This is for implementing equality comparison for unordered
173148fb7bfaSmrg    *  containers, per N3068, by John Lakos and Pablo Halpern.
173248fb7bfaSmrg    *  Algorithmically, we follow closely the reference implementations
173348fb7bfaSmrg    *  therein.
173448fb7bfaSmrg    */
173548fb7bfaSmrg   template<typename _Key, typename _Value, typename _Alloc,
173648fb7bfaSmrg 	   typename _ExtractKey, typename _Equal,
1737b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
173848fb7bfaSmrg 	   typename _RehashPolicy, typename _Traits,
173948fb7bfaSmrg 	   bool _Unique_keys = _Traits::__unique_keys::value>
174048fb7bfaSmrg     struct _Equality;
174148fb7bfaSmrg 
1742fb8a8121Smrg   /// unordered_map and unordered_set specializations.
174348fb7bfaSmrg   template<typename _Key, typename _Value, typename _Alloc,
174448fb7bfaSmrg 	   typename _ExtractKey, typename _Equal,
1745b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
174648fb7bfaSmrg 	   typename _RehashPolicy, typename _Traits>
174748fb7bfaSmrg     struct _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1748b1e83836Smrg 		     _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits, true>
17494fee23f9Smrg     {
175048fb7bfaSmrg       using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1751b1e83836Smrg 				     _Hash, _RangeHash, _Unused,
1752b1e83836Smrg 				     _RehashPolicy, _Traits>;
175348fb7bfaSmrg 
175448fb7bfaSmrg       bool
175548fb7bfaSmrg       _M_equal(const __hashtable&) const;
175648fb7bfaSmrg     };
175748fb7bfaSmrg 
175848fb7bfaSmrg   template<typename _Key, typename _Value, typename _Alloc,
175948fb7bfaSmrg 	   typename _ExtractKey, typename _Equal,
1760b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
176148fb7bfaSmrg 	   typename _RehashPolicy, typename _Traits>
176248fb7bfaSmrg     bool
176348fb7bfaSmrg     _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1764b1e83836Smrg 	      _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits, true>::
176548fb7bfaSmrg     _M_equal(const __hashtable& __other) const
176648fb7bfaSmrg     {
1767fb8a8121Smrg       using __node_type = typename __hashtable::__node_type;
176848fb7bfaSmrg       const __hashtable* __this = static_cast<const __hashtable*>(this);
176948fb7bfaSmrg       if (__this->size() != __other.size())
177048fb7bfaSmrg 	return false;
177148fb7bfaSmrg 
177248fb7bfaSmrg       for (auto __itx = __this->begin(); __itx != __this->end(); ++__itx)
177348fb7bfaSmrg 	{
1774b1e83836Smrg 	  std::size_t __ybkt = __other._M_bucket_index(*__itx._M_cur);
1775b1e83836Smrg 	  auto __prev_n = __other._M_buckets[__ybkt];
1776fb8a8121Smrg 	  if (!__prev_n)
1777fb8a8121Smrg 	    return false;
1778fb8a8121Smrg 
1779fb8a8121Smrg 	  for (__node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt);;
1780fb8a8121Smrg 	       __n = __n->_M_next())
1781fb8a8121Smrg 	    {
1782fb8a8121Smrg 	      if (__n->_M_v() == *__itx)
1783fb8a8121Smrg 		break;
1784fb8a8121Smrg 
1785fb8a8121Smrg 	      if (!__n->_M_nxt
1786b1e83836Smrg 		  || __other._M_bucket_index(*__n->_M_next()) != __ybkt)
178748fb7bfaSmrg 		return false;
178848fb7bfaSmrg 	    }
1789fb8a8121Smrg 	}
1790fb8a8121Smrg 
179148fb7bfaSmrg       return true;
179248fb7bfaSmrg     }
179348fb7bfaSmrg 
1794fb8a8121Smrg   /// unordered_multiset and unordered_multimap specializations.
179548fb7bfaSmrg   template<typename _Key, typename _Value, typename _Alloc,
179648fb7bfaSmrg 	   typename _ExtractKey, typename _Equal,
1797b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
179848fb7bfaSmrg 	   typename _RehashPolicy, typename _Traits>
179948fb7bfaSmrg     struct _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1800b1e83836Smrg 		     _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits, false>
180148fb7bfaSmrg     {
180248fb7bfaSmrg       using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1803b1e83836Smrg 				     _Hash, _RangeHash, _Unused,
1804b1e83836Smrg 				     _RehashPolicy, _Traits>;
180548fb7bfaSmrg 
180648fb7bfaSmrg       bool
180748fb7bfaSmrg       _M_equal(const __hashtable&) const;
180848fb7bfaSmrg     };
180948fb7bfaSmrg 
181048fb7bfaSmrg   template<typename _Key, typename _Value, typename _Alloc,
181148fb7bfaSmrg 	   typename _ExtractKey, typename _Equal,
1812b1e83836Smrg 	   typename _Hash, typename _RangeHash, typename _Unused,
181348fb7bfaSmrg 	   typename _RehashPolicy, typename _Traits>
181448fb7bfaSmrg     bool
181548fb7bfaSmrg     _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1816b1e83836Smrg 	      _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits, false>::
181748fb7bfaSmrg     _M_equal(const __hashtable& __other) const
181848fb7bfaSmrg     {
1819fb8a8121Smrg       using __node_type = typename __hashtable::__node_type;
182048fb7bfaSmrg       const __hashtable* __this = static_cast<const __hashtable*>(this);
18214fee23f9Smrg       if (__this->size() != __other.size())
18224fee23f9Smrg 	return false;
18234fee23f9Smrg 
18244fee23f9Smrg       for (auto __itx = __this->begin(); __itx != __this->end();)
18254fee23f9Smrg 	{
1826fb8a8121Smrg 	  std::size_t __x_count = 1;
1827fb8a8121Smrg 	  auto __itx_end = __itx;
1828fb8a8121Smrg 	  for (++__itx_end; __itx_end != __this->end()
1829b1e83836Smrg 		 && __this->key_eq()(_ExtractKey{}(*__itx),
1830b1e83836Smrg 				     _ExtractKey{}(*__itx_end));
1831fb8a8121Smrg 	       ++__itx_end)
1832fb8a8121Smrg 	    ++__x_count;
18334fee23f9Smrg 
1834b1e83836Smrg 	  std::size_t __ybkt = __other._M_bucket_index(*__itx._M_cur);
1835b1e83836Smrg 	  auto __y_prev_n = __other._M_buckets[__ybkt];
1836fb8a8121Smrg 	  if (!__y_prev_n)
18374fee23f9Smrg 	    return false;
18384fee23f9Smrg 
1839fb8a8121Smrg 	  __node_type* __y_n = static_cast<__node_type*>(__y_prev_n->_M_nxt);
1840b1e83836Smrg 	  for (;;)
1841fb8a8121Smrg 	    {
1842b1e83836Smrg 	      if (__this->key_eq()(_ExtractKey{}(__y_n->_M_v()),
1843b1e83836Smrg 				   _ExtractKey{}(*__itx)))
1844fb8a8121Smrg 		break;
1845fb8a8121Smrg 
1846b1e83836Smrg 	      auto __y_ref_n = __y_n;
1847b1e83836Smrg 	      for (__y_n = __y_n->_M_next(); __y_n; __y_n = __y_n->_M_next())
1848b1e83836Smrg 		if (!__other._M_node_equals(*__y_ref_n, *__y_n))
1849b1e83836Smrg 		  break;
1850b1e83836Smrg 
1851b1e83836Smrg 	      if (!__y_n || __other._M_bucket_index(*__y_n) != __ybkt)
1852fb8a8121Smrg 		return false;
1853fb8a8121Smrg 	    }
1854fb8a8121Smrg 
1855fb8a8121Smrg 	  typename __hashtable::const_iterator __ity(__y_n);
1856fb8a8121Smrg 	  for (auto __ity_end = __ity; __ity_end != __other.end(); ++__ity_end)
1857fb8a8121Smrg 	    if (--__x_count == 0)
1858fb8a8121Smrg 	      break;
1859fb8a8121Smrg 
1860fb8a8121Smrg 	  if (__x_count != 0)
18614fee23f9Smrg 	    return false;
18624fee23f9Smrg 
1863fb8a8121Smrg 	  if (!std::is_permutation(__itx, __itx_end, __ity))
1864fb8a8121Smrg 	    return false;
1865fb8a8121Smrg 
1866fb8a8121Smrg 	  __itx = __itx_end;
18674fee23f9Smrg 	}
18684fee23f9Smrg       return true;
18694fee23f9Smrg     }
187048fb7bfaSmrg 
187148fb7bfaSmrg   /**
1872fb8a8121Smrg    * This type deals with all allocation and keeps an allocator instance
1873fb8a8121Smrg    * through inheritance to benefit from EBO when possible.
187448fb7bfaSmrg    */
187548fb7bfaSmrg   template<typename _NodeAlloc>
18764d5abbe8Smrg     struct _Hashtable_alloc : private _Hashtable_ebo_helper<0, _NodeAlloc>
187748fb7bfaSmrg     {
18784d5abbe8Smrg     private:
18794d5abbe8Smrg       using __ebo_node_alloc = _Hashtable_ebo_helper<0, _NodeAlloc>;
1880b1e83836Smrg 
1881b1e83836Smrg       template<typename>
1882b1e83836Smrg 	struct __get_value_type;
1883b1e83836Smrg       template<typename _Val, bool _Cache_hash_code>
1884b1e83836Smrg 	struct __get_value_type<_Hash_node<_Val, _Cache_hash_code>>
1885b1e83836Smrg 	{ using type = _Val; };
1886b1e83836Smrg 
18874d5abbe8Smrg     public:
18884d5abbe8Smrg       using __node_type = typename _NodeAlloc::value_type;
18894d5abbe8Smrg       using __node_alloc_type = _NodeAlloc;
18904d5abbe8Smrg       // Use __gnu_cxx to benefit from _S_always_equal and al.
18914d5abbe8Smrg       using __node_alloc_traits = __gnu_cxx::__alloc_traits<__node_alloc_type>;
189248fb7bfaSmrg 
1893a3e9eb18Smrg       using __value_alloc_traits = typename __node_alloc_traits::template
1894b1e83836Smrg 	rebind_traits<typename __get_value_type<__node_type>::type>;
18954d5abbe8Smrg 
1896b1e83836Smrg       using __node_ptr = __node_type*;
1897b1e83836Smrg       using __node_base = _Hash_node_base;
1898b1e83836Smrg       using __node_base_ptr = __node_base*;
1899b1e83836Smrg       using __buckets_alloc_type =
1900b1e83836Smrg 	__alloc_rebind<__node_alloc_type, __node_base_ptr>;
1901b1e83836Smrg       using __buckets_alloc_traits = std::allocator_traits<__buckets_alloc_type>;
1902b1e83836Smrg       using __buckets_ptr = __node_base_ptr*;
19034d5abbe8Smrg 
19044d5abbe8Smrg       _Hashtable_alloc() = default;
19054d5abbe8Smrg       _Hashtable_alloc(const _Hashtable_alloc&) = default;
19064d5abbe8Smrg       _Hashtable_alloc(_Hashtable_alloc&&) = default;
190748fb7bfaSmrg 
190848fb7bfaSmrg       template<typename _Alloc>
19094d5abbe8Smrg 	_Hashtable_alloc(_Alloc&& __a)
19104d5abbe8Smrg 	: __ebo_node_alloc(std::forward<_Alloc>(__a))
191148fb7bfaSmrg 	{ }
19124d5abbe8Smrg 
19134d5abbe8Smrg       __node_alloc_type&
19144d5abbe8Smrg       _M_node_allocator()
1915fb8a8121Smrg       { return __ebo_node_alloc::_M_get(); }
19164d5abbe8Smrg 
19174d5abbe8Smrg       const __node_alloc_type&
19184d5abbe8Smrg       _M_node_allocator() const
1919fb8a8121Smrg       { return __ebo_node_alloc::_M_cget(); }
19204d5abbe8Smrg 
1921fb8a8121Smrg       // Allocate a node and construct an element within it.
19224d5abbe8Smrg       template<typename... _Args>
1923b1e83836Smrg 	__node_ptr
19244d5abbe8Smrg 	_M_allocate_node(_Args&&... __args);
19254d5abbe8Smrg 
1926fb8a8121Smrg       // Destroy the element within a node and deallocate the node.
19274d5abbe8Smrg       void
1928b1e83836Smrg       _M_deallocate_node(__node_ptr __n);
19294d5abbe8Smrg 
1930fb8a8121Smrg       // Deallocate a node.
1931181254a7Smrg       void
1932b1e83836Smrg       _M_deallocate_node_ptr(__node_ptr __n);
1933181254a7Smrg 
1934fb8a8121Smrg       // Deallocate the linked list of nodes pointed to by __n.
1935fb8a8121Smrg       // The elements within the nodes are destroyed.
19364d5abbe8Smrg       void
1937b1e83836Smrg       _M_deallocate_nodes(__node_ptr __n);
19384d5abbe8Smrg 
1939b1e83836Smrg       __buckets_ptr
1940fb8a8121Smrg       _M_allocate_buckets(std::size_t __bkt_count);
19414d5abbe8Smrg 
19424d5abbe8Smrg       void
1943b1e83836Smrg       _M_deallocate_buckets(__buckets_ptr, std::size_t __bkt_count);
194448fb7bfaSmrg     };
194548fb7bfaSmrg 
19464d5abbe8Smrg   // Definitions of class template _Hashtable_alloc's out-of-line member
19474d5abbe8Smrg   // functions.
19484d5abbe8Smrg   template<typename _NodeAlloc>
19494d5abbe8Smrg     template<typename... _Args>
1950fb8a8121Smrg       auto
19514d5abbe8Smrg       _Hashtable_alloc<_NodeAlloc>::_M_allocate_node(_Args&&... __args)
1952b1e83836Smrg       -> __node_ptr
19534d5abbe8Smrg       {
19544d5abbe8Smrg 	auto __nptr = __node_alloc_traits::allocate(_M_node_allocator(), 1);
1955b1e83836Smrg 	__node_ptr __n = std::__to_address(__nptr);
19564d5abbe8Smrg 	__try
19574d5abbe8Smrg 	  {
19584d5abbe8Smrg 	    ::new ((void*)__n) __node_type;
1959a3e9eb18Smrg 	    __node_alloc_traits::construct(_M_node_allocator(),
1960a3e9eb18Smrg 					   __n->_M_valptr(),
19614d5abbe8Smrg 					   std::forward<_Args>(__args)...);
19624d5abbe8Smrg 	    return __n;
19634d5abbe8Smrg 	  }
19644d5abbe8Smrg 	__catch(...)
19654d5abbe8Smrg 	  {
19664d5abbe8Smrg 	    __node_alloc_traits::deallocate(_M_node_allocator(), __nptr, 1);
19674d5abbe8Smrg 	    __throw_exception_again;
19684d5abbe8Smrg 	  }
19694d5abbe8Smrg       }
19704d5abbe8Smrg 
19714d5abbe8Smrg   template<typename _NodeAlloc>
19724d5abbe8Smrg     void
1973b1e83836Smrg     _Hashtable_alloc<_NodeAlloc>::_M_deallocate_node(__node_ptr __n)
19744d5abbe8Smrg     {
1975181254a7Smrg       __node_alloc_traits::destroy(_M_node_allocator(), __n->_M_valptr());
1976181254a7Smrg       _M_deallocate_node_ptr(__n);
1977181254a7Smrg     }
1978181254a7Smrg 
1979181254a7Smrg   template<typename _NodeAlloc>
1980181254a7Smrg     void
1981b1e83836Smrg     _Hashtable_alloc<_NodeAlloc>::_M_deallocate_node_ptr(__node_ptr __n)
1982181254a7Smrg     {
19834d5abbe8Smrg       typedef typename __node_alloc_traits::pointer _Ptr;
19844d5abbe8Smrg       auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__n);
19854d5abbe8Smrg       __n->~__node_type();
19864d5abbe8Smrg       __node_alloc_traits::deallocate(_M_node_allocator(), __ptr, 1);
19874d5abbe8Smrg     }
19884d5abbe8Smrg 
19894d5abbe8Smrg   template<typename _NodeAlloc>
19904d5abbe8Smrg     void
1991b1e83836Smrg     _Hashtable_alloc<_NodeAlloc>::_M_deallocate_nodes(__node_ptr __n)
19924d5abbe8Smrg     {
19934d5abbe8Smrg       while (__n)
19944d5abbe8Smrg 	{
1995b1e83836Smrg 	  __node_ptr __tmp = __n;
19964d5abbe8Smrg 	  __n = __n->_M_next();
19974d5abbe8Smrg 	  _M_deallocate_node(__tmp);
19984d5abbe8Smrg 	}
19994d5abbe8Smrg     }
20004d5abbe8Smrg 
20014d5abbe8Smrg   template<typename _NodeAlloc>
2002b1e83836Smrg     auto
2003fb8a8121Smrg     _Hashtable_alloc<_NodeAlloc>::_M_allocate_buckets(std::size_t __bkt_count)
2004b1e83836Smrg     -> __buckets_ptr
20054d5abbe8Smrg     {
2006b1e83836Smrg       __buckets_alloc_type __alloc(_M_node_allocator());
20074d5abbe8Smrg 
2008b1e83836Smrg       auto __ptr = __buckets_alloc_traits::allocate(__alloc, __bkt_count);
2009b1e83836Smrg       __buckets_ptr __p = std::__to_address(__ptr);
2010b1e83836Smrg       __builtin_memset(__p, 0, __bkt_count * sizeof(__node_base_ptr));
20114d5abbe8Smrg       return __p;
20124d5abbe8Smrg     }
20134d5abbe8Smrg 
20144d5abbe8Smrg   template<typename _NodeAlloc>
20154d5abbe8Smrg     void
2016b1e83836Smrg     _Hashtable_alloc<_NodeAlloc>::
2017b1e83836Smrg     _M_deallocate_buckets(__buckets_ptr __bkts,
2018fb8a8121Smrg 			  std::size_t __bkt_count)
20194d5abbe8Smrg     {
2020b1e83836Smrg       typedef typename __buckets_alloc_traits::pointer _Ptr;
20214d5abbe8Smrg       auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__bkts);
2022b1e83836Smrg       __buckets_alloc_type __alloc(_M_node_allocator());
2023b1e83836Smrg       __buckets_alloc_traits::deallocate(__alloc, __ptr, __bkt_count);
20244d5abbe8Smrg     }
20254d5abbe8Smrg 
2026a448f87cSmrg  ///@} hashtable-detail
20278b6133e5Smrg } // namespace __detail
2028b1e83836Smrg /// @endcond
2029a3e9eb18Smrg _GLIBCXX_END_NAMESPACE_VERSION
203048fb7bfaSmrg } // namespace std
20314fee23f9Smrg 
20324fee23f9Smrg #endif // _HASHTABLE_POLICY_H
2033