libstdc++
bits/hashtable.h
Go to the documentation of this file.
1 // hashtable.h header -*- C++ -*-
2 
3 // Copyright (C) 2007-2013 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /** @file bits/hashtable.h
26  * This is an internal header file, included by other library headers.
27  * Do not attempt to use it directly. @headername{unordered_map, unordered_set}
28  */
29 
30 #ifndef _HASHTABLE_H
31 #define _HASHTABLE_H 1
32 
33 #pragma GCC system_header
34 
35 #include <bits/hashtable_policy.h>
36 
37 namespace std _GLIBCXX_VISIBILITY(default)
38 {
39 _GLIBCXX_BEGIN_NAMESPACE_VERSION
40 
41  template<typename _Tp, typename _Hash>
42  using __cache_default
43  = __not_<__and_<// Do not cache for fast hasher.
44  __is_fast_hash<_Hash>,
45  // Mandatory to make local_iterator default
46  // constructible and assignable.
47  is_default_constructible<_Hash>,
48  is_copy_assignable<_Hash>,
49  // Mandatory to have erase not throwing.
50  __detail::__is_noexcept_hash<_Tp, _Hash>>>;
51 
52  /**
53  * Primary class template _Hashtable.
54  *
55  * @ingroup hashtable-detail
56  *
57  * @tparam _Value CopyConstructible type.
58  *
59  * @tparam _Key CopyConstructible type.
60  *
61  * @tparam _Alloc An allocator type
62  * ([lib.allocator.requirements]) whose _Alloc::value_type is
63  * _Value. As a conforming extension, we allow for
64  * _Alloc::value_type != _Value.
65  *
66  * @tparam _ExtractKey Function object that takes an object of type
67  * _Value and returns a value of type _Key.
68  *
69  * @tparam _Equal Function object that takes two objects of type k
70  * and returns a bool-like value that is true if the two objects
71  * are considered equal.
72  *
73  * @tparam _H1 The hash function. A unary function object with
74  * argument type _Key and result type size_t. Return values should
75  * be distributed over the entire range [0, numeric_limits<size_t>:::max()].
76  *
77  * @tparam _H2 The range-hashing function (in the terminology of
78  * Tavori and Dreizin). A binary function object whose argument
79  * types and result type are all size_t. Given arguments r and N,
80  * the return value is in the range [0, N).
81  *
82  * @tparam _Hash The ranged hash function (Tavori and Dreizin). A
83  * binary function whose argument types are _Key and size_t and
84  * whose result type is size_t. Given arguments k and N, the
85  * return value is in the range [0, N). Default: hash(k, N) =
86  * h2(h1(k), N). If _Hash is anything other than the default, _H1
87  * and _H2 are ignored.
88  *
89  * @tparam _RehashPolicy Policy class with three members, all of
90  * which govern the bucket count. _M_next_bkt(n) returns a bucket
91  * count no smaller than n. _M_bkt_for_elements(n) returns a
92  * bucket count appropriate for an element count of n.
93  * _M_need_rehash(n_bkt, n_elt, n_ins) determines whether, if the
94  * current bucket count is n_bkt and the current element count is
95  * n_elt, we need to increase the bucket count. If so, returns
96  * make_pair(true, n), where n is the new bucket count. If not,
97  * returns make_pair(false, <anything>)
98  *
99  * @tparam _Traits Compile-time class with three boolean
100  * std::integral_constant members: __cache_hash_code, __constant_iterators,
101  * __unique_keys.
102  *
103  * Each _Hashtable data structure has:
104  *
105  * - _Bucket[] _M_buckets
106  * - _Hash_node_base _M_bbegin
107  * - size_type _M_bucket_count
108  * - size_type _M_element_count
109  *
110  * with _Bucket being _Hash_node* and _Hash_node containing:
111  *
112  * - _Hash_node* _M_next
113  * - Tp _M_value
114  * - size_t _M_hash_code if cache_hash_code is true
115  *
116  * In terms of Standard containers the hashtable is like the aggregation of:
117  *
118  * - std::forward_list<_Node> containing the elements
119  * - std::vector<std::forward_list<_Node>::iterator> representing the buckets
120  *
121  * The non-empty buckets contain the node before the first node in the
122  * bucket. This design makes it possible to implement something like a
123  * std::forward_list::insert_after on container insertion and
124  * std::forward_list::erase_after on container erase
125  * calls. _M_before_begin is equivalent to
126  * std::forward_list::before_begin. Empty buckets contain
127  * nullptr. Note that one of the non-empty buckets contains
128  * &_M_before_begin which is not a dereferenceable node so the
129  * node pointer in a bucket shall never be dereferenced, only its
130  * next node can be.
131  *
132  * Walking through a bucket's nodes requires a check on the hash code to
133  * see if each node is still in the bucket. Such a design assumes a
134  * quite efficient hash functor and is one of the reasons it is
135  * highly advisable to set __cache_hash_code to true.
136  *
137  * The container iterators are simply built from nodes. This way
138  * incrementing the iterator is perfectly efficient independent of
139  * how many empty buckets there are in the container.
140  *
141  * On insert we compute the element's hash code and use it to find the
142  * bucket index. If the element must be inserted in an empty bucket
143  * we add it at the beginning of the singly linked list and make the
144  * bucket point to _M_before_begin. The bucket that used to point to
145  * _M_before_begin, if any, is updated to point to its new before
146  * begin node.
147  *
148  * On erase, the simple iterator design requires using the hash
149  * functor to get the index of the bucket to update. For this
150  * reason, when __cache_hash_code is set to false the hash functor must
151  * not throw and this is enforced by a static assertion.
152  *
153  * Functionality is implemented by decomposition into base classes,
154  * where the derived _Hashtable class is used in _Map_base,
155  * _Insert, _Rehash_base, and _Equality base classes to access the
156  * "this" pointer. _Hashtable_base is used in the base classes as a
157  * non-recursive, fully-completed-type so that detailed nested type
158  * information, such as iterator type and node type, can be
159  * used. This is similar to the "Curiously Recurring Template
160  * Pattern" (CRTP) technique, but uses a reconstructed, not
161  * explicitly passed, template pattern.
162  *
163  * Base class templates are:
164  * - __detail::_Hashtable_base
165  * - __detail::_Map_base
166  * - __detail::_Insert
167  * - __detail::_Rehash_base
168  * - __detail::_Equality
169  */
170  template<typename _Key, typename _Value, typename _Alloc,
171  typename _ExtractKey, typename _Equal,
172  typename _H1, typename _H2, typename _Hash,
173  typename _RehashPolicy, typename _Traits>
175  : public __detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal,
176  _H1, _H2, _Hash, _Traits>,
177  public __detail::_Map_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
178  _H1, _H2, _Hash, _RehashPolicy, _Traits>,
179  public __detail::_Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal,
180  _H1, _H2, _Hash, _RehashPolicy, _Traits>,
181  public __detail::_Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
182  _H1, _H2, _Hash, _RehashPolicy, _Traits>,
183  public __detail::_Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal,
184  _H1, _H2, _Hash, _RehashPolicy, _Traits>
185  {
187  typedef typename _Alloc_traits::template rebind_alloc<_Value>
188  _Value_alloc_type;
190 
191  public:
192  typedef _Key key_type;
193  typedef _Value value_type;
194  typedef _Alloc allocator_type;
195  typedef _Equal key_equal;
196 
197  // mapped_type, if present, comes from _Map_base.
198  // hasher, if present, comes from _Hash_code_base/_Hashtable_base.
199  typedef typename _Value_alloc_traits::pointer pointer;
200  typedef typename _Value_alloc_traits::const_pointer const_pointer;
201  typedef value_type& reference;
202  typedef const value_type& const_reference;
203 
204  private:
205  using __rehash_type = _RehashPolicy;
206  using __rehash_state = typename __rehash_type::_State;
207 
208  using __traits_type = _Traits;
209  using __hash_cached = typename __traits_type::__hash_cached;
210  using __constant_iterators = typename __traits_type::__constant_iterators;
211  using __unique_keys = typename __traits_type::__unique_keys;
212 
213  using __key_extract = typename std::conditional<
214  __constant_iterators::value,
215  __detail::_Identity,
216  __detail::_Select1st>::type;
217 
219  _Hashtable_base<_Key, _Value, _ExtractKey,
220  _Equal, _H1, _H2, _Hash, _Traits>;
221 
222  using __hash_code_base = typename __hashtable_base::__hash_code_base;
223  using __hash_code = typename __hashtable_base::__hash_code;
224  using __node_type = typename __hashtable_base::__node_type;
225  using __node_base = typename __hashtable_base::__node_base;
226  using __bucket_type = typename __hashtable_base::__bucket_type;
227  using __ireturn_type = typename __hashtable_base::__ireturn_type;
228 
229  using __map_base = __detail::_Map_base<_Key, _Value, _Alloc, _ExtractKey,
230  _Equal, _H1, _H2, _Hash,
231  _RehashPolicy, _Traits>;
232 
233  using __rehash_base = __detail::_Rehash_base<_Key, _Value, _Alloc,
234  _ExtractKey, _Equal,
235  _H1, _H2, _Hash,
236  _RehashPolicy, _Traits>;
237 
238  using __eq_base = __detail::_Equality<_Key, _Value, _Alloc, _ExtractKey,
239  _Equal, _H1, _H2, _Hash,
240  _RehashPolicy, _Traits>;
241 
242  // Metaprogramming for picking apart hash caching.
243  template<typename _Cond>
244  using __if_hash_cached = __or_<__not_<__hash_cached>, _Cond>;
245 
246  template<typename _Cond>
247  using __if_hash_not_cached = __or_<__hash_cached, _Cond>;
248 
249  // Compile-time diagnostics.
250 
251  // Getting a bucket index from a node shall not throw because it is used
252  // in methods (erase, swap...) that shall not throw.
253  static_assert(noexcept(declval<const _Hashtable&>()
254  ._M_bucket_index((const __node_type*)nullptr,
255  (std::size_t)0)),
256  "Cache the hash code or qualify your functors involved"
257  " in hash code and bucket index computation with noexcept");
258 
259  // Following two static assertions are necessary to guarantee
260  // that local_iterator will be default constructible.
261 
262  // When hash codes are cached local iterator inherits from H2 functor
263  // which must then be default constructible.
264  static_assert(__if_hash_cached<is_default_constructible<_H2>>::value,
265  "Functor used to map hash code to bucket index"
266  " must be default constructible");
267 
268  // When hash codes are not cached local iterator inherits from
269  // __hash_code_base above to compute node bucket index so it has to be
270  // default constructible.
271  static_assert(__if_hash_not_cached<
272  is_default_constructible<
273  // We use _Hashtable_ebo_helper to access the protected
274  // default constructor.
276  "Cache the hash code or make functors involved in hash code"
277  " and bucket index computation default constructible");
278 
279  // When hash codes are not cached local iterator inherits from
280  // __hash_code_base above to compute node bucket index so it has to be
281  // assignable.
282  static_assert(__if_hash_not_cached<
283  is_copy_assignable<__hash_code_base>>::value,
284  "Cache the hash code or make functors involved in hash code"
285  " and bucket index computation copy assignable");
286 
287  public:
288  template<typename _Keya, typename _Valuea, typename _Alloca,
289  typename _ExtractKeya, typename _Equala,
290  typename _H1a, typename _H2a, typename _Hasha,
291  typename _RehashPolicya, typename _Traitsa,
292  bool _Unique_keysa>
293  friend struct __detail::_Map_base;
294 
295  template<typename _Keya, typename _Valuea, typename _Alloca,
296  typename _ExtractKeya, typename _Equala,
297  typename _H1a, typename _H2a, typename _Hasha,
298  typename _RehashPolicya, typename _Traitsa>
299  friend struct __detail::_Insert_base;
300 
301  template<typename _Keya, typename _Valuea, typename _Alloca,
302  typename _ExtractKeya, typename _Equala,
303  typename _H1a, typename _H2a, typename _Hasha,
304  typename _RehashPolicya, typename _Traitsa,
305  bool _Constant_iteratorsa, bool _Unique_keysa>
306  friend struct __detail::_Insert;
307 
308  template<typename _Keya, typename _Valuea, typename _Alloca,
309  typename _ExtractKeya, typename _Equala,
310  typename _H1a, typename _H2a, typename _Hasha,
311  typename _RehashPolicya, typename _Traitsa,
312  bool _IsCopyAssignable>
313  friend struct __detail::_ReuseOrAllocNode;
314 
315  template<typename _Keya, typename _Valuea, typename _Alloca,
316  typename _ExtractKeya, typename _Equala,
317  typename _H1a, typename _H2a, typename _Hasha,
318  typename _RehashPolicya, typename _Traitsa,
319  bool _IsMoveAssignable>
320  friend struct __detail::_MoveReuseOrAllocNode;
321 
322  using size_type = typename __hashtable_base::size_type;
323  using difference_type = typename __hashtable_base::difference_type;
324 
325  using iterator = typename __hashtable_base::iterator;
326  using const_iterator = typename __hashtable_base::const_iterator;
327 
328  using local_iterator = typename __hashtable_base::local_iterator;
329  using const_local_iterator = typename __hashtable_base::
331 
332  private:
333  typedef typename _Alloc_traits::template rebind_alloc<__node_type>
334  _Node_alloc_type;
335  // Use __gnu_cxx to benefit from _S_always_equal and al.
337 
338  typedef
339  typename _Alloc_traits::template rebind_alloc<__bucket_type>
340  _Bucket_alloc_type;
342 
344 
345  __bucket_type* _M_buckets;
346  size_type _M_bucket_count;
347  __before_begin _M_bbegin;
348  size_type _M_element_count;
349  _RehashPolicy _M_rehash_policy;
350 
351  _Node_alloc_type&
352  _M_node_allocator()
353  { return _M_bbegin; }
354 
355  const _Node_alloc_type&
356  _M_node_allocator() const
357  { return _M_bbegin; }
358 
359  __node_base&
360  _M_before_begin()
361  { return _M_bbegin._M_node; }
362 
363  const __node_base&
364  _M_before_begin() const
365  { return _M_bbegin._M_node; }
366 
367  template<typename... _Args>
368  __node_type*
369  _M_allocate_node(_Args&&... __args);
370 
371  void
372  _M_deallocate_node(__node_type* __n);
373 
374  // Deallocate the linked list of nodes pointed to by __n
375  void
376  _M_deallocate_nodes(__node_type* __n);
377 
378  __bucket_type*
379  _M_allocate_buckets(size_type __n);
380 
381  void
382  _M_deallocate_buckets(__bucket_type*, size_type __n);
383 
384  void
385  _M_deallocate_buckets()
386  { _M_deallocate_buckets(_M_buckets, _M_bucket_count); }
387 
388  // Gets bucket begin, deals with the fact that non-empty buckets contain
389  // their before begin node.
390  __node_type*
391  _M_bucket_begin(size_type __bkt) const;
392 
393  __node_type*
394  _M_begin() const
395  { return static_cast<__node_type*>(_M_before_begin()._M_nxt); }
396 
397  template<typename _UnaryOp>
398  void
399  _M_assign(const _Hashtable&, const _UnaryOp&);
400 
401  void
402  _M_move_assign(_Hashtable&&, std::true_type);
403 
404  void
405  _M_move_assign(_Hashtable&&, std::false_type);
406 
407  void
408  _M_reset() noexcept;
409 
410  public:
411  // Constructor, destructor, assignment, swap
412  _Hashtable(size_type __bucket_hint,
413  const _H1&, const _H2&, const _Hash&,
414  const _Equal&, const _ExtractKey&,
415  const allocator_type&);
416 
417  template<typename _InputIterator>
418  _Hashtable(_InputIterator __first, _InputIterator __last,
419  size_type __bucket_hint,
420  const _H1&, const _H2&, const _Hash&,
421  const _Equal&, const _ExtractKey&,
422  const allocator_type&);
423 
424  _Hashtable(const _Hashtable&);
425 
426  _Hashtable(_Hashtable&&) noexcept;
427 
428  _Hashtable(const _Hashtable&, const allocator_type&);
429 
430  _Hashtable(_Hashtable&&, const allocator_type&);
431 
432  // Use delegating constructors.
433  explicit
434  _Hashtable(const allocator_type& __a)
436  __detail::_Default_ranged_hash(), key_equal(),
437  __key_extract(), __a)
438  { }
439 
440  explicit
441  _Hashtable(size_type __n = 10,
442  const _H1& __hf = _H1(),
443  const key_equal& __eql = key_equal(),
444  const allocator_type& __a = allocator_type())
447  __key_extract(), __a)
448  { }
449 
450  template<typename _InputIterator>
451  _Hashtable(_InputIterator __f, _InputIterator __l,
452  size_type __n = 0,
453  const _H1& __hf = _H1(),
454  const key_equal& __eql = key_equal(),
455  const allocator_type& __a = allocator_type())
456  : _Hashtable(__f, __l, __n, __hf, __detail::_Mod_range_hashing(),
458  __key_extract(), __a)
459  { }
460 
462  size_type __n = 0,
463  const _H1& __hf = _H1(),
464  const key_equal& __eql = key_equal(),
465  const allocator_type& __a = allocator_type())
466  : _Hashtable(__l.begin(), __l.end(), __n, __hf,
469  __key_extract(), __a)
470  { }
471 
472  _Hashtable&
473  operator=(const _Hashtable& __ht);
474 
475  _Hashtable&
476  operator=(_Hashtable&& __ht)
477  noexcept(_Node_alloc_traits::_S_nothrow_move())
478  {
479  constexpr bool __move_storage =
480  _Node_alloc_traits::_S_propagate_on_move_assign()
481  || _Node_alloc_traits::_S_always_equal();
482  _M_move_assign(std::move(__ht),
484  return *this;
485  }
486 
487  _Hashtable&
488  operator=(initializer_list<value_type> __l)
489  {
490  clear();
491  this->insert(__l.begin(), __l.end());
492  return *this;
493  }
494 
495  ~_Hashtable() noexcept;
496 
497  void
498  swap(_Hashtable&)
499  noexcept(_Node_alloc_traits::_S_nothrow_swap());
500 
501  // Basic container operations
502  iterator
503  begin() noexcept
504  { return iterator(_M_begin()); }
505 
506  const_iterator
507  begin() const noexcept
508  { return const_iterator(_M_begin()); }
509 
510  iterator
511  end() noexcept
512  { return iterator(nullptr); }
513 
514  const_iterator
515  end() const noexcept
516  { return const_iterator(nullptr); }
517 
518  const_iterator
519  cbegin() const noexcept
520  { return const_iterator(_M_begin()); }
521 
522  const_iterator
523  cend() const noexcept
524  { return const_iterator(nullptr); }
525 
526  size_type
527  size() const noexcept
528  { return _M_element_count; }
529 
530  bool
531  empty() const noexcept
532  { return size() == 0; }
533 
534  allocator_type
535  get_allocator() const noexcept
536  { return allocator_type(_M_node_allocator()); }
537 
538  size_type
539  max_size() const noexcept
540  { return _Node_alloc_traits::max_size(_M_node_allocator()); }
541 
542  // Observers
543  key_equal
544  key_eq() const
545  { return this->_M_eq(); }
546 
547  // hash_function, if present, comes from _Hash_code_base.
548 
549  // Bucket operations
550  size_type
551  bucket_count() const noexcept
552  { return _M_bucket_count; }
553 
554  size_type
555  max_bucket_count() const noexcept
556  { return max_size(); }
557 
558  size_type
559  bucket_size(size_type __n) const
560  { return std::distance(begin(__n), end(__n)); }
561 
562  size_type
563  bucket(const key_type& __k) const
564  { return _M_bucket_index(__k, this->_M_hash_code(__k)); }
565 
566  local_iterator
567  begin(size_type __n)
568  {
569  return local_iterator(*this, _M_bucket_begin(__n),
570  __n, _M_bucket_count);
571  }
572 
573  local_iterator
574  end(size_type __n)
575  { return local_iterator(*this, nullptr, __n, _M_bucket_count); }
576 
577  const_local_iterator
578  begin(size_type __n) const
579  {
580  return const_local_iterator(*this, _M_bucket_begin(__n),
581  __n, _M_bucket_count);
582  }
583 
584  const_local_iterator
585  end(size_type __n) const
586  { return const_local_iterator(*this, nullptr, __n, _M_bucket_count); }
587 
588  // DR 691.
589  const_local_iterator
590  cbegin(size_type __n) const
591  {
592  return const_local_iterator(*this, _M_bucket_begin(__n),
593  __n, _M_bucket_count);
594  }
595 
596  const_local_iterator
597  cend(size_type __n) const
598  { return const_local_iterator(*this, nullptr, __n, _M_bucket_count); }
599 
600  float
601  load_factor() const noexcept
602  {
603  return static_cast<float>(size()) / static_cast<float>(bucket_count());
604  }
605 
606  // max_load_factor, if present, comes from _Rehash_base.
607 
608  // Generalization of max_load_factor. Extension, not found in
609  // TR1. Only useful if _RehashPolicy is something other than
610  // the default.
611  const _RehashPolicy&
612  __rehash_policy() const
613  { return _M_rehash_policy; }
614 
615  void
616  __rehash_policy(const _RehashPolicy&);
617 
618  // Lookup.
619  iterator
620  find(const key_type& __k);
621 
622  const_iterator
623  find(const key_type& __k) const;
624 
625  size_type
626  count(const key_type& __k) const;
627 
629  equal_range(const key_type& __k);
630 
632  equal_range(const key_type& __k) const;
633 
634  protected:
635  // Bucket index computation helpers.
636  size_type
637  _M_bucket_index(__node_type* __n) const noexcept
638  { return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); }
639 
640  size_type
641  _M_bucket_index(const key_type& __k, __hash_code __c) const
642  { return __hash_code_base::_M_bucket_index(__k, __c, _M_bucket_count); }
643 
644  // Find and insert helper functions and types
645  // Find the node before the one matching the criteria.
646  __node_base*
647  _M_find_before_node(size_type, const key_type&, __hash_code) const;
648 
649  __node_type*
650  _M_find_node(size_type __bkt, const key_type& __key,
651  __hash_code __c) const
652  {
653  __node_base* __before_n = _M_find_before_node(__bkt, __key, __c);
654  if (__before_n)
655  return static_cast<__node_type*>(__before_n->_M_nxt);
656  return nullptr;
657  }
658 
659  // Insert a node at the beginning of a bucket.
660  void
661  _M_insert_bucket_begin(size_type, __node_type*);
662 
663  // Remove the bucket first node
664  void
665  _M_remove_bucket_begin(size_type __bkt, __node_type* __next_n,
666  size_type __next_bkt);
667 
668  // Get the node before __n in the bucket __bkt
669  __node_base*
670  _M_get_previous_node(size_type __bkt, __node_base* __n);
671 
672  // Insert node with hash code __code, in bucket bkt if no rehash (assumes
673  // no element with its key already present). Take ownership of the node,
674  // deallocate it on exception.
675  iterator
676  _M_insert_unique_node(size_type __bkt, __hash_code __code,
677  __node_type* __n);
678 
679  // Insert node with hash code __code. Take ownership of the node,
680  // deallocate it on exception.
681  iterator
682  _M_insert_multi_node(__node_type* __hint,
683  __hash_code __code, __node_type* __n);
684 
685  template<typename... _Args>
687  _M_emplace(std::true_type, _Args&&... __args);
688 
689  template<typename... _Args>
690  iterator
691  _M_emplace(std::false_type __uk, _Args&&... __args)
692  { return _M_emplace(cend(), __uk, std::forward<_Args>(__args)...); }
693 
694  // Emplace with hint, useless when keys are unique.
695  template<typename... _Args>
696  iterator
697  _M_emplace(const_iterator, std::true_type __uk, _Args&&... __args)
698  { return _M_emplace(__uk, std::forward<_Args>(__args)...).first; }
699 
700  template<typename... _Args>
701  iterator
702  _M_emplace(const_iterator, std::false_type, _Args&&... __args);
703 
704  template<typename _Arg>
706  _M_insert(_Arg&&, std::true_type);
707 
708  template<typename _Arg>
709  iterator
710  _M_insert(_Arg&& __arg, std::false_type __uk)
711  { return _M_insert(cend(), std::forward<_Arg>(__arg), __uk); }
712 
713  // Insert with hint, not used when keys are unique.
714  template<typename _Arg>
715  iterator
716  _M_insert(const_iterator, _Arg&& __arg, std::true_type __uk)
717  { return _M_insert(std::forward<_Arg>(__arg), __uk).first; }
718 
719  // Insert with hint when keys are not unique.
720  template<typename _Arg>
721  iterator
722  _M_insert(const_iterator, _Arg&&, std::false_type);
723 
724  size_type
725  _M_erase(std::true_type, const key_type&);
726 
727  size_type
728  _M_erase(std::false_type, const key_type&);
729 
730  iterator
731  _M_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n);
732 
733  public:
734  // Emplace
735  template<typename... _Args>
736  __ireturn_type
737  emplace(_Args&&... __args)
738  { return _M_emplace(__unique_keys(), std::forward<_Args>(__args)...); }
739 
740  template<typename... _Args>
741  iterator
742  emplace_hint(const_iterator __hint, _Args&&... __args)
743  {
744  return _M_emplace(__hint, __unique_keys(),
745  std::forward<_Args>(__args)...);
746  }
747 
748  // Insert member functions via inheritance.
749 
750  // Erase
751  iterator
752  erase(const_iterator);
753 
754  // LWG 2059.
755  iterator
756  erase(iterator __it)
757  { return erase(const_iterator(__it)); }
758 
759  size_type
760  erase(const key_type& __k)
761  {
762  if (__builtin_expect(_M_bucket_count == 0, false))
763  return 0;
764  return _M_erase(__unique_keys(), __k);
765  }
766 
767  iterator
768  erase(const_iterator, const_iterator);
769 
770  void
771  clear() noexcept;
772 
773  // Set number of buckets to be appropriate for container of n element.
774  void rehash(size_type __n);
775 
776  // DR 1189.
777  // reserve, if present, comes from _Rehash_base.
778 
779  private:
780  // Helper rehash method used when keys are unique.
781  void _M_rehash_aux(size_type __n, std::true_type);
782 
783  // Helper rehash method used when keys can be non-unique.
784  void _M_rehash_aux(size_type __n, std::false_type);
785 
786  // Unconditionally change size of bucket array to n, restore
787  // hash policy state to __state on exception.
788  void _M_rehash(size_type __n, const __rehash_state& __state);
789  };
790 
791 
792  // Definitions of class template _Hashtable's out-of-line member functions.
793  template<typename _Key, typename _Value,
794  typename _Alloc, typename _ExtractKey, typename _Equal,
795  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
796  typename _Traits>
797  template<typename... _Args>
798  typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
799  _H1, _H2, _Hash, _RehashPolicy, _Traits>::__node_type*
800  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
801  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
802  _M_allocate_node(_Args&&... __args)
803  {
804  auto __nptr = _Node_alloc_traits::allocate(_M_node_allocator(), 1);
805  __node_type* __n = std::__addressof(*__nptr);
806  __try
807  {
808  _Value_alloc_type __a(_M_node_allocator());
809  ::new ((void*)__n) __node_type();
810  _Value_alloc_traits::construct(__a, __n->_M_valptr(),
811  std::forward<_Args>(__args)...);
812  return __n;
813  }
814  __catch(...)
815  {
816  _Node_alloc_traits::deallocate(_M_node_allocator(), __nptr, 1);
817  __throw_exception_again;
818  }
819  }
820 
821  template<typename _Key, typename _Value,
822  typename _Alloc, typename _ExtractKey, typename _Equal,
823  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
824  typename _Traits>
825  void
826  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
827  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
828  _M_deallocate_node(__node_type* __n)
829  {
830  typedef typename _Node_alloc_traits::pointer _Ptr;
831  auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__n);
832  _Value_alloc_type __a(_M_node_allocator());
833  _Value_alloc_traits::destroy(__a, __n->_M_valptr());
834  __n->~__node_type();
835  _Node_alloc_traits::deallocate(_M_node_allocator(), __ptr, 1);
836  }
837 
838  template<typename _Key, typename _Value,
839  typename _Alloc, typename _ExtractKey, typename _Equal,
840  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
841  typename _Traits>
842  void
843  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
844  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
845  _M_deallocate_nodes(__node_type* __n)
846  {
847  while (__n)
848  {
849  __node_type* __tmp = __n;
850  __n = __n->_M_next();
851  _M_deallocate_node(__tmp);
852  }
853  }
854 
855  template<typename _Key, typename _Value,
856  typename _Alloc, typename _ExtractKey, typename _Equal,
857  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
858  typename _Traits>
859  typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
860  _H1, _H2, _Hash, _RehashPolicy, _Traits>::__bucket_type*
861  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
862  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
863  _M_allocate_buckets(size_type __n)
864  {
865  _Bucket_alloc_type __alloc(_M_node_allocator());
866 
867  auto __ptr = _Bucket_alloc_traits::allocate(__alloc, __n);
868  __bucket_type* __p = std::__addressof(*__ptr);
869  __builtin_memset(__p, 0, __n * sizeof(__bucket_type));
870  return __p;
871  }
872 
873  template<typename _Key, typename _Value,
874  typename _Alloc, typename _ExtractKey, typename _Equal,
875  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
876  typename _Traits>
877  void
878  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
879  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
880  _M_deallocate_buckets(__bucket_type* __bkts, size_type __n)
881  {
882  typedef typename _Bucket_alloc_traits::pointer _Ptr;
883  auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__bkts);
884  _Bucket_alloc_type __alloc(_M_node_allocator());
885  _Bucket_alloc_traits::deallocate(__alloc, __ptr, __n);
886  }
887 
888  template<typename _Key, typename _Value,
889  typename _Alloc, typename _ExtractKey, typename _Equal,
890  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
891  typename _Traits>
892  typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
893  _Equal, _H1, _H2, _Hash, _RehashPolicy,
894  _Traits>::__node_type*
895  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
896  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
897  _M_bucket_begin(size_type __bkt) const
898  {
899  __node_base* __n = _M_buckets[__bkt];
900  return __n ? static_cast<__node_type*>(__n->_M_nxt) : nullptr;
901  }
902 
903  template<typename _Key, typename _Value,
904  typename _Alloc, typename _ExtractKey, typename _Equal,
905  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
906  typename _Traits>
907  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
908  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
909  _Hashtable(size_type __bucket_hint,
910  const _H1& __h1, const _H2& __h2, const _Hash& __h,
911  const _Equal& __eq, const _ExtractKey& __exk,
912  const allocator_type& __a)
913  : __hashtable_base(__exk, __h1, __h2, __h, __eq),
914  __map_base(),
915  __rehash_base(),
916  _M_bbegin(__a),
917  _M_element_count(0),
918  _M_rehash_policy()
919  {
920  _M_bucket_count = _M_rehash_policy._M_next_bkt(__bucket_hint);
921  _M_buckets = _M_allocate_buckets(_M_bucket_count);
922  }
923 
924  template<typename _Key, typename _Value,
925  typename _Alloc, typename _ExtractKey, typename _Equal,
926  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
927  typename _Traits>
928  template<typename _InputIterator>
929  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
930  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
931  _Hashtable(_InputIterator __f, _InputIterator __l,
932  size_type __bucket_hint,
933  const _H1& __h1, const _H2& __h2, const _Hash& __h,
934  const _Equal& __eq, const _ExtractKey& __exk,
935  const allocator_type& __a)
936  : __hashtable_base(__exk, __h1, __h2, __h, __eq),
937  __map_base(),
938  __rehash_base(),
939  _M_bbegin(__a),
940  _M_element_count(0),
941  _M_rehash_policy()
942  {
943  auto __nb_elems = __detail::__distance_fw(__f, __l);
944  _M_bucket_count =
945  _M_rehash_policy._M_next_bkt(
946  std::max(_M_rehash_policy._M_bkt_for_elements(__nb_elems),
947  __bucket_hint));
948 
949  _M_buckets = _M_allocate_buckets(_M_bucket_count);
950  __try
951  {
952  for (; __f != __l; ++__f)
953  this->insert(*__f);
954  }
955  __catch(...)
956  {
957  clear();
958  _M_deallocate_buckets();
959  __throw_exception_again;
960  }
961  }
962 
963  template<typename _Key, typename _Value,
964  typename _Alloc, typename _ExtractKey, typename _Equal,
965  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
966  typename _Traits>
967  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
968  _H1, _H2, _Hash, _RehashPolicy, _Traits>&
969  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
970  _H1, _H2, _Hash, _RehashPolicy, _Traits>::operator=(
971  const _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
972  _H1, _H2, _Hash, _RehashPolicy, _Traits>& __ht)
973  {
974  if (&__ht == this)
975  return *this;
976 
977  if (_Node_alloc_traits::_S_propagate_on_copy_assign())
978  {
979  auto& __this_alloc = this->_M_node_allocator();
980  auto& __that_alloc = __ht._M_node_allocator();
981  if (!_Node_alloc_traits::_S_always_equal()
982  && __this_alloc != __that_alloc)
983  {
984  // Replacement allocator cannot free existing storage.
985  _M_deallocate_nodes(_M_begin());
986  if (__builtin_expect(_M_bucket_count != 0, true))
987  _M_deallocate_buckets();
988  _M_reset();
989  std::__alloc_on_copy(__this_alloc, __that_alloc);
990  __hashtable_base::operator=(__ht);
991  _M_bucket_count = __ht._M_bucket_count;
992  _M_element_count = __ht._M_element_count;
993  _M_rehash_policy = __ht._M_rehash_policy;
994  __try
995  {
996  _M_assign(__ht,
997  [this](const __node_type* __n)
998  { return _M_allocate_node(__n->_M_v()); });
999  }
1000  __catch(...)
1001  {
1002  // _M_assign took care of deallocating all memory. Now we
1003  // must make sure this instance remains in a usable state.
1004  _M_reset();
1005  __throw_exception_again;
1006  }
1007  return *this;
1008  }
1009  std::__alloc_on_copy(__this_alloc, __that_alloc);
1010  }
1011 
1012  // Reuse allocated buckets and nodes.
1013  __bucket_type* __former_buckets = nullptr;
1014  std::size_t __former_bucket_count = _M_bucket_count;
1015  const __rehash_state& __former_state = _M_rehash_policy._M_state();
1016 
1017  if (_M_bucket_count != __ht._M_bucket_count)
1018  {
1019  __former_buckets = _M_buckets;
1020  _M_buckets = _M_allocate_buckets(__ht._M_bucket_count);
1021  _M_bucket_count = __ht._M_bucket_count;
1022  }
1023  else
1024  __builtin_memset(_M_buckets, 0,
1025  _M_bucket_count * sizeof(__bucket_type));
1026 
1027  __try
1028  {
1029  __hashtable_base::operator=(__ht);
1030  _M_element_count = __ht._M_element_count;
1031  _M_rehash_policy = __ht._M_rehash_policy;
1032  __detail::_ReuseOrAllocNode<_Key, _Value, _Alloc, _ExtractKey,
1033  _Equal, _H1, _H2, _Hash,
1034  _RehashPolicy, _Traits>
1035  __roan(_M_begin(), *this);
1036  _M_before_begin()._M_nxt = nullptr;
1037  _M_assign(__ht, __roan);
1038  if (__former_buckets)
1039  _M_deallocate_buckets(__former_buckets, __former_bucket_count);
1040  }
1041  __catch(...)
1042  {
1043  if (__former_buckets)
1044  {
1045  // Restore previous buckets.
1046  _M_deallocate_buckets();
1047  _M_rehash_policy._M_reset(__former_state);
1048  _M_buckets = __former_buckets;
1049  _M_bucket_count = __former_bucket_count;
1050  }
1051  __builtin_memset(_M_buckets, 0,
1052  _M_bucket_count * sizeof(__bucket_type));
1053  __throw_exception_again;
1054  }
1055  return *this;
1056  }
1057 
1058  template<typename _Key, typename _Value,
1059  typename _Alloc, typename _ExtractKey, typename _Equal,
1060  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1061  typename _Traits>
1062  template<typename _UnaryOp>
1063  void
1064  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1065  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1066  _M_assign(const _Hashtable& __ht, const _UnaryOp& __node_getter)
1067  {
1068  __bucket_type* __buckets = nullptr;
1069  if (!_M_buckets)
1070  _M_buckets = __buckets = _M_allocate_buckets(_M_bucket_count);
1071 
1072  __try
1073  {
1074  if (!__ht._M_before_begin()._M_nxt)
1075  return;
1076 
1077  // First deal with the special first node pointed to by
1078  // _M_before_begin.
1079  __node_type* __ht_n = __ht._M_begin();
1080  __node_type* __this_n = __node_getter(__ht_n);
1081  this->_M_copy_code(__this_n, __ht_n);
1082  _M_before_begin()._M_nxt = __this_n;
1083  _M_buckets[_M_bucket_index(__this_n)] = &_M_before_begin();
1084 
1085  // Then deal with other nodes.
1086  __node_base* __prev_n = __this_n;
1087  for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next())
1088  {
1089  __this_n = __node_getter(__ht_n);
1090  __prev_n->_M_nxt = __this_n;
1091  this->_M_copy_code(__this_n, __ht_n);
1092  size_type __bkt = _M_bucket_index(__this_n);
1093  if (!_M_buckets[__bkt])
1094  _M_buckets[__bkt] = __prev_n;
1095  __prev_n = __this_n;
1096  }
1097  }
1098  __catch(...)
1099  {
1100  clear();
1101  if (__buckets)
1102  _M_deallocate_buckets();
1103  __throw_exception_again;
1104  }
1105  }
1106 
1107  template<typename _Key, typename _Value,
1108  typename _Alloc, typename _ExtractKey, typename _Equal,
1109  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1110  typename _Traits>
1111  void
1112  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1113  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1114  _M_reset() noexcept
1115  {
1116  _M_rehash_policy._M_reset();
1117  _M_bucket_count = 0;
1118  _M_buckets = nullptr;
1119  _M_before_begin()._M_nxt = nullptr;
1120  _M_element_count = 0;
1121  }
1122 
1123  template<typename _Key, typename _Value,
1124  typename _Alloc, typename _ExtractKey, typename _Equal,
1125  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1126  typename _Traits>
1127  void
1128  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1129  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1130  _M_move_assign(_Hashtable&& __ht, std::true_type)
1131  {
1132  _M_deallocate_nodes(_M_begin());
1133  if (__builtin_expect(_M_bucket_count != 0, true))
1134  _M_deallocate_buckets();
1135 
1136  __hashtable_base::operator=(std::move(__ht));
1137  _M_rehash_policy = __ht._M_rehash_policy;
1138  _M_buckets = __ht._M_buckets;
1139  _M_bucket_count = __ht._M_bucket_count;
1140  _M_before_begin()._M_nxt = __ht._M_before_begin()._M_nxt;
1141  _M_element_count = __ht._M_element_count;
1142  std::__alloc_on_move(_M_node_allocator(), __ht._M_node_allocator());
1143 
1144  // Fix buckets containing the _M_before_begin pointers that can't be
1145  // moved.
1146  if (_M_begin())
1147  _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin();
1148  __ht._M_reset();
1149  }
1150 
1151  template<typename _Key, typename _Value,
1152  typename _Alloc, typename _ExtractKey, typename _Equal,
1153  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1154  typename _Traits>
1155  void
1156  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1157  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1158  _M_move_assign(_Hashtable&& __ht, std::false_type)
1159  {
1160  if (__ht._M_node_allocator() == _M_node_allocator())
1161  _M_move_assign(std::move(__ht), std::true_type());
1162  else
1163  {
1164  // Can't move memory, move elements then.
1165  __bucket_type* __former_buckets = nullptr;
1166  size_type __former_bucket_count = _M_bucket_count;
1167  const __rehash_state& __former_state = _M_rehash_policy._M_state();
1168 
1169  if (_M_bucket_count != __ht._M_bucket_count)
1170  {
1171  __former_buckets = _M_buckets;
1172  _M_buckets = _M_allocate_buckets(__ht._M_bucket_count);
1173  _M_bucket_count = __ht._M_bucket_count;
1174  }
1175  else
1176  __builtin_memset(_M_buckets, 0,
1177  _M_bucket_count * sizeof(__bucket_type));
1178 
1179  __try
1180  {
1181  __hashtable_base::operator=(std::move(__ht));
1182  _M_element_count = __ht._M_element_count;
1183  _M_rehash_policy = __ht._M_rehash_policy;
1184  __detail::_MoveReuseOrAllocNode<_Key, _Value, _Alloc, _ExtractKey,
1185  _Equal, _H1, _H2, _Hash,
1186  _RehashPolicy, _Traits>
1187  __mroan(_M_begin(), *this);
1188  _M_before_begin()._M_nxt = nullptr;
1189  _M_assign(__ht, __mroan);
1190  __ht.clear();
1191  }
1192  __catch(...)
1193  {
1194  if (__former_buckets)
1195  {
1196  _M_deallocate_buckets();
1197  _M_rehash_policy._M_reset(__former_state);
1198  _M_buckets = __former_buckets;
1199  _M_bucket_count = __former_bucket_count;
1200  }
1201  __builtin_memset(_M_buckets, 0,
1202  _M_bucket_count * sizeof(__bucket_type));
1203  __throw_exception_again;
1204  }
1205  }
1206  }
1207 
1208  template<typename _Key, typename _Value,
1209  typename _Alloc, typename _ExtractKey, typename _Equal,
1210  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1211  typename _Traits>
1212  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1213  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1214  _Hashtable(const _Hashtable& __ht)
1215  : __hashtable_base(__ht),
1216  __map_base(__ht),
1217  __rehash_base(__ht),
1218  _M_buckets(),
1219  _M_bucket_count(__ht._M_bucket_count),
1220  _M_bbegin(_Node_alloc_traits::_S_select_on_copy(
1221  __ht._M_node_allocator())),
1222  _M_element_count(__ht._M_element_count),
1223  _M_rehash_policy(__ht._M_rehash_policy)
1224  {
1225  _M_assign(__ht,
1226  [this](const __node_type* __n)
1227  { return _M_allocate_node(__n->_M_v()); });
1228  }
1229 
1230  template<typename _Key, typename _Value,
1231  typename _Alloc, typename _ExtractKey, typename _Equal,
1232  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1233  typename _Traits>
1234  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1235  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1236  _Hashtable(_Hashtable&& __ht) noexcept
1237  : __hashtable_base(__ht),
1238  __map_base(__ht),
1239  __rehash_base(__ht),
1240  _M_buckets(__ht._M_buckets),
1241  _M_bucket_count(__ht._M_bucket_count),
1242  _M_bbegin(std::move(__ht._M_bbegin)),
1243  _M_element_count(__ht._M_element_count),
1244  _M_rehash_policy(__ht._M_rehash_policy)
1245  {
1246  // Update, if necessary, bucket pointing to before begin that hasn't
1247  // moved.
1248  if (_M_begin())
1249  _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin();
1250  __ht._M_reset();
1251  }
1252 
1253  template<typename _Key, typename _Value,
1254  typename _Alloc, typename _ExtractKey, typename _Equal,
1255  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1256  typename _Traits>
1257  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1258  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1259  _Hashtable(const _Hashtable& __ht, const allocator_type& __a)
1260  : __hashtable_base(__ht),
1261  __map_base(__ht),
1262  __rehash_base(__ht),
1263  _M_buckets(),
1264  _M_bucket_count(__ht._M_bucket_count),
1265  _M_bbegin(_Node_alloc_type(__a)),
1266  _M_element_count(__ht._M_element_count),
1267  _M_rehash_policy(__ht._M_rehash_policy)
1268  {
1269  _M_assign(__ht,
1270  [this](const __node_type* __n)
1271  { return _M_allocate_node(__n->_M_v()); });
1272  }
1273 
1274  template<typename _Key, typename _Value,
1275  typename _Alloc, typename _ExtractKey, typename _Equal,
1276  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1277  typename _Traits>
1278  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1279  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1280  _Hashtable(_Hashtable&& __ht, const allocator_type& __a)
1281  : __hashtable_base(__ht),
1282  __map_base(__ht),
1283  __rehash_base(__ht),
1284  _M_buckets(),
1285  _M_bucket_count(__ht._M_bucket_count),
1286  _M_bbegin(_Node_alloc_type(__a)),
1287  _M_element_count(__ht._M_element_count),
1288  _M_rehash_policy(__ht._M_rehash_policy)
1289  {
1290  if (__ht._M_node_allocator() == _M_node_allocator())
1291  {
1292  _M_buckets = __ht._M_buckets;
1293  _M_before_begin()._M_nxt = __ht._M_before_begin()._M_nxt;
1294  // Update, if necessary, bucket pointing to before begin that hasn't
1295  // moved.
1296  if (_M_begin())
1297  _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin();
1298  __ht._M_reset();
1299  }
1300  else
1301  {
1302  _M_assign(__ht,
1303  [this](__node_type* __n)
1304  {
1305  return _M_allocate_node(
1306  std::move_if_noexcept(__n->_M_v()));
1307  });
1308  __ht.clear();
1309  }
1310  }
1311 
1312  template<typename _Key, typename _Value,
1313  typename _Alloc, typename _ExtractKey, typename _Equal,
1314  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1315  typename _Traits>
1316  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1317  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1318  ~_Hashtable() noexcept
1319  {
1320  clear();
1321  if (_M_buckets)
1322  _M_deallocate_buckets();
1323  }
1324 
1325  template<typename _Key, typename _Value,
1326  typename _Alloc, typename _ExtractKey, typename _Equal,
1327  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1328  typename _Traits>
1329  void
1330  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1331  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1332  swap(_Hashtable& __x)
1333  noexcept(_Node_alloc_traits::_S_nothrow_swap())
1334  {
1335  // The only base class with member variables is hash_code_base.
1336  // We define _Hash_code_base::_M_swap because different
1337  // specializations have different members.
1338  this->_M_swap(__x);
1339 
1340  std::__alloc_on_swap(_M_node_allocator(), __x._M_node_allocator());
1341  std::swap(_M_rehash_policy, __x._M_rehash_policy);
1342  std::swap(_M_buckets, __x._M_buckets);
1343  std::swap(_M_bucket_count, __x._M_bucket_count);
1344  std::swap(_M_before_begin()._M_nxt, __x._M_before_begin()._M_nxt);
1345  std::swap(_M_element_count, __x._M_element_count);
1346 
1347  // Fix buckets containing the _M_before_begin pointers that can't be
1348  // swapped.
1349  if (_M_begin())
1350  _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin();
1351  if (__x._M_begin())
1352  __x._M_buckets[__x._M_bucket_index(__x._M_begin())]
1353  = &(__x._M_before_begin());
1354  }
1355 
1356  template<typename _Key, typename _Value,
1357  typename _Alloc, typename _ExtractKey, typename _Equal,
1358  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1359  typename _Traits>
1360  void
1361  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1362  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1363  __rehash_policy(const _RehashPolicy& __pol)
1364  {
1365  size_type __n_bkt = __pol._M_bkt_for_elements(_M_element_count);
1366  __n_bkt = __pol._M_next_bkt(__n_bkt);
1367  if (__n_bkt != _M_bucket_count)
1368  _M_rehash(__n_bkt, _M_rehash_policy._M_state());
1369  _M_rehash_policy = __pol;
1370  }
1371 
1372  template<typename _Key, typename _Value,
1373  typename _Alloc, typename _ExtractKey, typename _Equal,
1374  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1375  typename _Traits>
1376  typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1377  _H1, _H2, _Hash, _RehashPolicy,
1378  _Traits>::iterator
1379  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1380  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1381  find(const key_type& __k)
1382  {
1383  if (__builtin_expect(_M_bucket_count == 0, false))
1384  return end();
1385 
1386  __hash_code __code = this->_M_hash_code(__k);
1387  std::size_t __n = _M_bucket_index(__k, __code);
1388  __node_type* __p = _M_find_node(__n, __k, __code);
1389  return __p ? iterator(__p) : end();
1390  }
1391 
1392  template<typename _Key, typename _Value,
1393  typename _Alloc, typename _ExtractKey, typename _Equal,
1394  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1395  typename _Traits>
1396  typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1397  _H1, _H2, _Hash, _RehashPolicy,
1398  _Traits>::const_iterator
1399  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1400  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1401  find(const key_type& __k) const
1402  {
1403  if (__builtin_expect(_M_bucket_count == 0, false))
1404  return end();
1405 
1406  __hash_code __code = this->_M_hash_code(__k);
1407  std::size_t __n = _M_bucket_index(__k, __code);
1408  __node_type* __p = _M_find_node(__n, __k, __code);
1409  return __p ? const_iterator(__p) : end();
1410  }
1411 
1412  template<typename _Key, typename _Value,
1413  typename _Alloc, typename _ExtractKey, typename _Equal,
1414  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1415  typename _Traits>
1416  typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1417  _H1, _H2, _Hash, _RehashPolicy,
1418  _Traits>::size_type
1419  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1420  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1421  count(const key_type& __k) const
1422  {
1423  if (__builtin_expect(_M_bucket_count == 0, false))
1424  return 0;
1425 
1426  __hash_code __code = this->_M_hash_code(__k);
1427  std::size_t __n = _M_bucket_index(__k, __code);
1428  __node_type* __p = _M_bucket_begin(__n);
1429  if (!__p)
1430  return 0;
1431 
1432  std::size_t __result = 0;
1433  for (;; __p = __p->_M_next())
1434  {
1435  if (this->_M_equals(__k, __code, __p))
1436  ++__result;
1437  else if (__result)
1438  // All equivalent values are next to each other, if we
1439  // found a non-equivalent value after an equivalent one it
1440  // means that we won't find any more equivalent values.
1441  break;
1442  if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n)
1443  break;
1444  }
1445  return __result;
1446  }
1447 
1448  template<typename _Key, typename _Value,
1449  typename _Alloc, typename _ExtractKey, typename _Equal,
1450  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1451  typename _Traits>
1452  std::pair<typename _Hashtable<_Key, _Value, _Alloc,
1453  _ExtractKey, _Equal, _H1,
1454  _H2, _Hash, _RehashPolicy,
1455  _Traits>::iterator,
1456  typename _Hashtable<_Key, _Value, _Alloc,
1457  _ExtractKey, _Equal, _H1,
1458  _H2, _Hash, _RehashPolicy,
1459  _Traits>::iterator>
1460  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1461  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1462  equal_range(const key_type& __k)
1463  {
1464  if (__builtin_expect(_M_bucket_count == 0, false))
1465  return std::make_pair(end(), end());
1466 
1467  __hash_code __code = this->_M_hash_code(__k);
1468  std::size_t __n = _M_bucket_index(__k, __code);
1469  __node_type* __p = _M_find_node(__n, __k, __code);
1470 
1471  if (__p)
1472  {
1473  __node_type* __p1 = __p->_M_next();
1474  while (__p1 && _M_bucket_index(__p1) == __n
1475  && this->_M_equals(__k, __code, __p1))
1476  __p1 = __p1->_M_next();
1477 
1478  return std::make_pair(iterator(__p), iterator(__p1));
1479  }
1480  else
1481  return std::make_pair(end(), end());
1482  }
1483 
1484  template<typename _Key, typename _Value,
1485  typename _Alloc, typename _ExtractKey, typename _Equal,
1486  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1487  typename _Traits>
1488  std::pair<typename _Hashtable<_Key, _Value, _Alloc,
1489  _ExtractKey, _Equal, _H1,
1490  _H2, _Hash, _RehashPolicy,
1491  _Traits>::const_iterator,
1492  typename _Hashtable<_Key, _Value, _Alloc,
1493  _ExtractKey, _Equal, _H1,
1494  _H2, _Hash, _RehashPolicy,
1495  _Traits>::const_iterator>
1496  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1497  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1498  equal_range(const key_type& __k) const
1499  {
1500  if (__builtin_expect(_M_bucket_count == 0, false))
1501  return std::make_pair(end(), end());
1502 
1503  __hash_code __code = this->_M_hash_code(__k);
1504  std::size_t __n = _M_bucket_index(__k, __code);
1505  __node_type* __p = _M_find_node(__n, __k, __code);
1506 
1507  if (__p)
1508  {
1509  __node_type* __p1 = __p->_M_next();
1510  while (__p1 && _M_bucket_index(__p1) == __n
1511  && this->_M_equals(__k, __code, __p1))
1512  __p1 = __p1->_M_next();
1513 
1514  return std::make_pair(const_iterator(__p), const_iterator(__p1));
1515  }
1516  else
1517  return std::make_pair(end(), end());
1518  }
1519 
1520  // Find the node whose key compares equal to k in the bucket n.
1521  // Return nullptr if no node is found.
1522  template<typename _Key, typename _Value,
1523  typename _Alloc, typename _ExtractKey, typename _Equal,
1524  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1525  typename _Traits>
1526  typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
1527  _Equal, _H1, _H2, _Hash, _RehashPolicy,
1528  _Traits>::__node_base*
1529  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1530  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1531  _M_find_before_node(size_type __n, const key_type& __k,
1532  __hash_code __code) const
1533  {
1534  __node_base* __prev_p = _M_buckets[__n];
1535  if (!__prev_p)
1536  return nullptr;
1537  __node_type* __p = static_cast<__node_type*>(__prev_p->_M_nxt);
1538  for (;; __p = __p->_M_next())
1539  {
1540  if (this->_M_equals(__k, __code, __p))
1541  return __prev_p;
1542  if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n)
1543  break;
1544  __prev_p = __p;
1545  }
1546  return nullptr;
1547  }
1548 
1549  template<typename _Key, typename _Value,
1550  typename _Alloc, typename _ExtractKey, typename _Equal,
1551  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1552  typename _Traits>
1553  void
1554  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1555  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1556  _M_insert_bucket_begin(size_type __bkt, __node_type* __node)
1557  {
1558  if (_M_buckets[__bkt])
1559  {
1560  // Bucket is not empty, we just need to insert the new node
1561  // after the bucket before begin.
1562  __node->_M_nxt = _M_buckets[__bkt]->_M_nxt;
1563  _M_buckets[__bkt]->_M_nxt = __node;
1564  }
1565  else
1566  {
1567  // The bucket is empty, the new node is inserted at the
1568  // beginning of the singly-linked list and the bucket will
1569  // contain _M_before_begin pointer.
1570  __node->_M_nxt = _M_before_begin()._M_nxt;
1571  _M_before_begin()._M_nxt = __node;
1572  if (__node->_M_nxt)
1573  // We must update former begin bucket that is pointing to
1574  // _M_before_begin.
1575  _M_buckets[_M_bucket_index(__node->_M_next())] = __node;
1576  _M_buckets[__bkt] = &_M_before_begin();
1577  }
1578  }
1579 
1580  template<typename _Key, typename _Value,
1581  typename _Alloc, typename _ExtractKey, typename _Equal,
1582  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1583  typename _Traits>
1584  void
1585  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1586  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1587  _M_remove_bucket_begin(size_type __bkt, __node_type* __next,
1588  size_type __next_bkt)
1589  {
1590  if (!__next || __next_bkt != __bkt)
1591  {
1592  // Bucket is now empty
1593  // First update next bucket if any
1594  if (__next)
1595  _M_buckets[__next_bkt] = _M_buckets[__bkt];
1596 
1597  // Second update before begin node if necessary
1598  if (&_M_before_begin() == _M_buckets[__bkt])
1599  _M_before_begin()._M_nxt = __next;
1600  _M_buckets[__bkt] = nullptr;
1601  }
1602  }
1603 
1604  template<typename _Key, typename _Value,
1605  typename _Alloc, typename _ExtractKey, typename _Equal,
1606  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1607  typename _Traits>
1608  typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
1609  _Equal, _H1, _H2, _Hash, _RehashPolicy,
1610  _Traits>::__node_base*
1611  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1612  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1613  _M_get_previous_node(size_type __bkt, __node_base* __n)
1614  {
1615  __node_base* __prev_n = _M_buckets[__bkt];
1616  while (__prev_n->_M_nxt != __n)
1617  __prev_n = __prev_n->_M_nxt;
1618  return __prev_n;
1619  }
1620 
1621  template<typename _Key, typename _Value,
1622  typename _Alloc, typename _ExtractKey, typename _Equal,
1623  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1624  typename _Traits>
1625  template<typename... _Args>
1626  std::pair<typename _Hashtable<_Key, _Value, _Alloc,
1627  _ExtractKey, _Equal, _H1,
1628  _H2, _Hash, _RehashPolicy,
1629  _Traits>::iterator, bool>
1630  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1631  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1632  _M_emplace(std::true_type, _Args&&... __args)
1633  {
1634  // First build the node to get access to the hash code
1635  __node_type* __node = _M_allocate_node(std::forward<_Args>(__args)...);
1636  const key_type& __k = this->_M_extract()(__node->_M_v());
1637  __hash_code __code;
1638  __try
1639  {
1640  __code = this->_M_hash_code(__k);
1641  }
1642  __catch(...)
1643  {
1644  _M_deallocate_node(__node);
1645  __throw_exception_again;
1646  }
1647 
1648  size_type __bkt = _M_bucket_index(__k, __code);
1649  if (__node_type* __p = _M_find_node(__bkt, __k, __code))
1650  {
1651  // There is already an equivalent node, no insertion
1652  _M_deallocate_node(__node);
1653  return std::make_pair(iterator(__p), false);
1654  }
1655 
1656  // Insert the node
1657  return std::make_pair(_M_insert_unique_node(__bkt, __code, __node),
1658  true);
1659  }
1660 
1661  template<typename _Key, typename _Value,
1662  typename _Alloc, typename _ExtractKey, typename _Equal,
1663  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1664  typename _Traits>
1665  template<typename... _Args>
1666  typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1667  _H1, _H2, _Hash, _RehashPolicy,
1668  _Traits>::iterator
1669  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1670  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1671  _M_emplace(const_iterator __hint, std::false_type, _Args&&... __args)
1672  {
1673  // First build the node to get its hash code.
1674  __node_type* __node = _M_allocate_node(std::forward<_Args>(__args)...);
1675 
1676  __hash_code __code;
1677  __try
1678  {
1679  __code = this->_M_hash_code(this->_M_extract()(__node->_M_v()));
1680  }
1681  __catch(...)
1682  {
1683  _M_deallocate_node(__node);
1684  __throw_exception_again;
1685  }
1686 
1687  return _M_insert_multi_node(__hint._M_cur, __code, __node);
1688  }
1689 
1690  template<typename _Key, typename _Value,
1691  typename _Alloc, typename _ExtractKey, typename _Equal,
1692  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1693  typename _Traits>
1694  typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1695  _H1, _H2, _Hash, _RehashPolicy,
1696  _Traits>::iterator
1697  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1698  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1699  _M_insert_unique_node(size_type __bkt, __hash_code __code,
1700  __node_type* __node)
1701  {
1702  const __rehash_state& __saved_state = _M_rehash_policy._M_state();
1703  std::pair<bool, std::size_t> __do_rehash
1704  = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1);
1705 
1706  __try
1707  {
1708  if (__do_rehash.first)
1709  {
1710  _M_rehash(__do_rehash.second, __saved_state);
1711  __bkt = _M_bucket_index(this->_M_extract()(__node->_M_v()), __code);
1712  }
1713 
1714  this->_M_store_code(__node, __code);
1715 
1716  // Always insert at the begining of the bucket.
1717  _M_insert_bucket_begin(__bkt, __node);
1718  ++_M_element_count;
1719  return iterator(__node);
1720  }
1721  __catch(...)
1722  {
1723  _M_deallocate_node(__node);
1724  __throw_exception_again;
1725  }
1726  }
1727 
1728  // Insert node, in bucket bkt if no rehash (assumes no element with its key
1729  // already present). Take ownership of the node, deallocate it on exception.
1730  template<typename _Key, typename _Value,
1731  typename _Alloc, typename _ExtractKey, typename _Equal,
1732  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1733  typename _Traits>
1734  typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1735  _H1, _H2, _Hash, _RehashPolicy,
1736  _Traits>::iterator
1737  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1738  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1739  _M_insert_multi_node(__node_type* __hint, __hash_code __code,
1740  __node_type* __node)
1741  {
1742  const __rehash_state& __saved_state = _M_rehash_policy._M_state();
1743  std::pair<bool, std::size_t> __do_rehash
1744  = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1);
1745 
1746  __try
1747  {
1748  if (__do_rehash.first)
1749  _M_rehash(__do_rehash.second, __saved_state);
1750 
1751  this->_M_store_code(__node, __code);
1752  const key_type& __k = this->_M_extract()(__node->_M_v());
1753  size_type __bkt = _M_bucket_index(__k, __code);
1754 
1755  // Find the node before an equivalent one or use hint if it exists and
1756  // if it is equivalent.
1757  __node_base* __prev
1758  = __builtin_expect(__hint != nullptr, false)
1759  && this->_M_equals(__k, __code, __hint)
1760  ? __hint
1761  : _M_find_before_node(__bkt, __k, __code);
1762  if (__prev)
1763  {
1764  // Insert after the node before the equivalent one.
1765  __node->_M_nxt = __prev->_M_nxt;
1766  __prev->_M_nxt = __node;
1767  if (__builtin_expect(__prev == __hint, false))
1768  // hint might be the last bucket node, in this case we need to
1769  // update next bucket.
1770  if (__node->_M_nxt
1771  && !this->_M_equals(__k, __code, __node->_M_next()))
1772  {
1773  size_type __next_bkt = _M_bucket_index(__node->_M_next());
1774  if (__next_bkt != __bkt)
1775  _M_buckets[__next_bkt] = __node;
1776  }
1777  }
1778  else
1779  // The inserted node has no equivalent in the
1780  // hashtable. We must insert the new node at the
1781  // beginning of the bucket to preserve equivalent
1782  // elements' relative positions.
1783  _M_insert_bucket_begin(__bkt, __node);
1784  ++_M_element_count;
1785  return iterator(__node);
1786  }
1787  __catch(...)
1788  {
1789  _M_deallocate_node(__node);
1790  __throw_exception_again;
1791  }
1792  }
1793 
1794  // Insert v if no element with its key is already present.
1795  template<typename _Key, typename _Value,
1796  typename _Alloc, typename _ExtractKey, typename _Equal,
1797  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1798  typename _Traits>
1799  template<typename _Arg>
1800  std::pair<typename _Hashtable<_Key, _Value, _Alloc,
1801  _ExtractKey, _Equal, _H1,
1802  _H2, _Hash, _RehashPolicy,
1803  _Traits>::iterator, bool>
1804  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1805  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1806  _M_insert(_Arg&& __v, std::true_type)
1807  {
1808  const key_type& __k = this->_M_extract()(__v);
1809  __hash_code __code = this->_M_hash_code(__k);
1810  size_type __bkt = _M_bucket_index(__k, __code);
1811 
1812  __node_type* __n = _M_find_node(__bkt, __k, __code);
1813  if (__n)
1814  return std::make_pair(iterator(__n), false);
1815 
1816  __n = _M_allocate_node(std::forward<_Arg>(__v));
1817  return std::make_pair(_M_insert_unique_node(__bkt, __code, __n), true);
1818  }
1819 
1820  // Insert v unconditionally.
1821  template<typename _Key, typename _Value,
1822  typename _Alloc, typename _ExtractKey, typename _Equal,
1823  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1824  typename _Traits>
1825  template<typename _Arg>
1826  typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1827  _H1, _H2, _Hash, _RehashPolicy,
1828  _Traits>::iterator
1829  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1830  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1831  _M_insert(const_iterator __hint, _Arg&& __v, std::false_type)
1832  {
1833  // First compute the hash code so that we don't do anything if it
1834  // throws.
1835  __hash_code __code = this->_M_hash_code(this->_M_extract()(__v));
1836 
1837  // Second allocate new node so that we don't rehash if it throws.
1838  __node_type* __node = _M_allocate_node(std::forward<_Arg>(__v));
1839 
1840  return _M_insert_multi_node(__hint._M_cur, __code, __node);
1841  }
1842 
1843  template<typename _Key, typename _Value,
1844  typename _Alloc, typename _ExtractKey, typename _Equal,
1845  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1846  typename _Traits>
1847  typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1848  _H1, _H2, _Hash, _RehashPolicy,
1849  _Traits>::iterator
1850  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1851  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1852  erase(const_iterator __it)
1853  {
1854  __node_type* __n = __it._M_cur;
1855  std::size_t __bkt = _M_bucket_index(__n);
1856 
1857  // Look for previous node to unlink it from the erased one, this
1858  // is why we need buckets to contain the before begin to make
1859  // this search fast.
1860  __node_base* __prev_n = _M_get_previous_node(__bkt, __n);
1861  return _M_erase(__bkt, __prev_n, __n);
1862  }
1863 
1864  template<typename _Key, typename _Value,
1865  typename _Alloc, typename _ExtractKey, typename _Equal,
1866  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1867  typename _Traits>
1868  typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1869  _H1, _H2, _Hash, _RehashPolicy,
1870  _Traits>::iterator
1871  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1872  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1873  _M_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n)
1874  {
1875  if (__prev_n == _M_buckets[__bkt])
1876  _M_remove_bucket_begin(__bkt, __n->_M_next(),
1877  __n->_M_nxt ? _M_bucket_index(__n->_M_next()) : 0);
1878  else if (__n->_M_nxt)
1879  {
1880  size_type __next_bkt = _M_bucket_index(__n->_M_next());
1881  if (__next_bkt != __bkt)
1882  _M_buckets[__next_bkt] = __prev_n;
1883  }
1884 
1885  __prev_n->_M_nxt = __n->_M_nxt;
1886  iterator __result(__n->_M_next());
1887  _M_deallocate_node(__n);
1888  --_M_element_count;
1889 
1890  return __result;
1891  }
1892 
1893  template<typename _Key, typename _Value,
1894  typename _Alloc, typename _ExtractKey, typename _Equal,
1895  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1896  typename _Traits>
1897  typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1898  _H1, _H2, _Hash, _RehashPolicy,
1899  _Traits>::size_type
1900  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1901  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1902  _M_erase(std::true_type, const key_type& __k)
1903  {
1904  __hash_code __code = this->_M_hash_code(__k);
1905  std::size_t __bkt = _M_bucket_index(__k, __code);
1906 
1907  // Look for the node before the first matching node.
1908  __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code);
1909  if (!__prev_n)
1910  return 0;
1911 
1912  // We found a matching node, erase it.
1913  __node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt);
1914  _M_erase(__bkt, __prev_n, __n);
1915  return 1;
1916  }
1917 
1918  template<typename _Key, typename _Value,
1919  typename _Alloc, typename _ExtractKey, typename _Equal,
1920  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1921  typename _Traits>
1922  typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1923  _H1, _H2, _Hash, _RehashPolicy,
1924  _Traits>::size_type
1925  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1926  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1927  _M_erase(std::false_type, const key_type& __k)
1928  {
1929  __hash_code __code = this->_M_hash_code(__k);
1930  std::size_t __bkt = _M_bucket_index(__k, __code);
1931 
1932  // Look for the node before the first matching node.
1933  __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code);
1934  if (!__prev_n)
1935  return 0;
1936 
1937  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1938  // 526. Is it undefined if a function in the standard changes
1939  // in parameters?
1940  // We use one loop to find all matching nodes and another to deallocate
1941  // them so that the key stays valid during the first loop. It might be
1942  // invalidated indirectly when destroying nodes.
1943  __node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt);
1944  __node_type* __n_last = __n;
1945  std::size_t __n_last_bkt = __bkt;
1946  do
1947  {
1948  __n_last = __n_last->_M_next();
1949  if (!__n_last)
1950  break;
1951  __n_last_bkt = _M_bucket_index(__n_last);
1952  }
1953  while (__n_last_bkt == __bkt && this->_M_equals(__k, __code, __n_last));
1954 
1955  // Deallocate nodes.
1956  size_type __result = 0;
1957  do
1958  {
1959  __node_type* __p = __n->_M_next();
1960  _M_deallocate_node(__n);
1961  __n = __p;
1962  ++__result;
1963  --_M_element_count;
1964  }
1965  while (__n != __n_last);
1966 
1967  if (__prev_n == _M_buckets[__bkt])
1968  _M_remove_bucket_begin(__bkt, __n_last, __n_last_bkt);
1969  else if (__n_last && __n_last_bkt != __bkt)
1970  _M_buckets[__n_last_bkt] = __prev_n;
1971  __prev_n->_M_nxt = __n_last;
1972  return __result;
1973  }
1974 
1975  template<typename _Key, typename _Value,
1976  typename _Alloc, typename _ExtractKey, typename _Equal,
1977  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1978  typename _Traits>
1979  typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1980  _H1, _H2, _Hash, _RehashPolicy,
1981  _Traits>::iterator
1982  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1983  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1984  erase(const_iterator __first, const_iterator __last)
1985  {
1986  __node_type* __n = __first._M_cur;
1987  __node_type* __last_n = __last._M_cur;
1988  if (__n == __last_n)
1989  return iterator(__n);
1990 
1991  std::size_t __bkt = _M_bucket_index(__n);
1992 
1993  __node_base* __prev_n = _M_get_previous_node(__bkt, __n);
1994  bool __is_bucket_begin = __n == _M_bucket_begin(__bkt);
1995  std::size_t __n_bkt = __bkt;
1996  for (;;)
1997  {
1998  do
1999  {
2000  __node_type* __tmp = __n;
2001  __n = __n->_M_next();
2002  _M_deallocate_node(__tmp);
2003  --_M_element_count;
2004  if (!__n)
2005  break;
2006  __n_bkt = _M_bucket_index(__n);
2007  }
2008  while (__n != __last_n && __n_bkt == __bkt);
2009  if (__is_bucket_begin)
2010  _M_remove_bucket_begin(__bkt, __n, __n_bkt);
2011  if (__n == __last_n)
2012  break;
2013  __is_bucket_begin = true;
2014  __bkt = __n_bkt;
2015  }
2016 
2017  if (__n && (__n_bkt != __bkt || __is_bucket_begin))
2018  _M_buckets[__n_bkt] = __prev_n;
2019  __prev_n->_M_nxt = __n;
2020  return iterator(__n);
2021  }
2022 
2023  template<typename _Key, typename _Value,
2024  typename _Alloc, typename _ExtractKey, typename _Equal,
2025  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
2026  typename _Traits>
2027  void
2028  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2029  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2030  clear() noexcept
2031  {
2032  _M_deallocate_nodes(_M_begin());
2033  __builtin_memset(_M_buckets, 0, _M_bucket_count * sizeof(__bucket_type));
2034  _M_element_count = 0;
2035  _M_before_begin()._M_nxt = nullptr;
2036  }
2037 
2038  template<typename _Key, typename _Value,
2039  typename _Alloc, typename _ExtractKey, typename _Equal,
2040  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
2041  typename _Traits>
2042  void
2043  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2044  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2045  rehash(size_type __n)
2046  {
2047  const __rehash_state& __saved_state = _M_rehash_policy._M_state();
2048  std::size_t __buckets
2049  = std::max(_M_rehash_policy._M_bkt_for_elements(_M_element_count + 1),
2050  __n);
2051  __buckets = _M_rehash_policy._M_next_bkt(__buckets);
2052 
2053  if (__buckets != _M_bucket_count)
2054  _M_rehash(__buckets, __saved_state);
2055  else
2056  // No rehash, restore previous state to keep a consistent state.
2057  _M_rehash_policy._M_reset(__saved_state);
2058  }
2059 
2060  template<typename _Key, typename _Value,
2061  typename _Alloc, typename _ExtractKey, typename _Equal,
2062  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
2063  typename _Traits>
2064  void
2065  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2066  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2067  _M_rehash(size_type __n, const __rehash_state& __state)
2068  {
2069  __try
2070  {
2071  _M_rehash_aux(__n, __unique_keys());
2072  }
2073  __catch(...)
2074  {
2075  // A failure here means that buckets allocation failed. We only
2076  // have to restore hash policy previous state.
2077  _M_rehash_policy._M_reset(__state);
2078  __throw_exception_again;
2079  }
2080  }
2081 
2082  // Rehash when there is no equivalent elements.
2083  template<typename _Key, typename _Value,
2084  typename _Alloc, typename _ExtractKey, typename _Equal,
2085  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
2086  typename _Traits>
2087  void
2088  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2089  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2090  _M_rehash_aux(size_type __n, std::true_type)
2091  {
2092  __bucket_type* __new_buckets = _M_allocate_buckets(__n);
2093  __node_type* __p = _M_begin();
2094  _M_before_begin()._M_nxt = nullptr;
2095  std::size_t __bbegin_bkt = 0;
2096  while (__p)
2097  {
2098  __node_type* __next = __p->_M_next();
2099  std::size_t __bkt = __hash_code_base::_M_bucket_index(__p, __n);
2100  if (!__new_buckets[__bkt])
2101  {
2102  __p->_M_nxt = _M_before_begin()._M_nxt;
2103  _M_before_begin()._M_nxt = __p;
2104  __new_buckets[__bkt] = &_M_before_begin();
2105  if (__p->_M_nxt)
2106  __new_buckets[__bbegin_bkt] = __p;
2107  __bbegin_bkt = __bkt;
2108  }
2109  else
2110  {
2111  __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2112  __new_buckets[__bkt]->_M_nxt = __p;
2113  }
2114  __p = __next;
2115  }
2116 
2117  if (__builtin_expect(_M_bucket_count != 0, true))
2118  _M_deallocate_buckets();
2119  _M_bucket_count = __n;
2120  _M_buckets = __new_buckets;
2121  }
2122 
2123  // Rehash when there can be equivalent elements, preserve their relative
2124  // order.
2125  template<typename _Key, typename _Value,
2126  typename _Alloc, typename _ExtractKey, typename _Equal,
2127  typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
2128  typename _Traits>
2129  void
2130  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2131  _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2132  _M_rehash_aux(size_type __n, std::false_type)
2133  {
2134  __bucket_type* __new_buckets = _M_allocate_buckets(__n);
2135 
2136  __node_type* __p = _M_begin();
2137  _M_before_begin()._M_nxt = nullptr;
2138  std::size_t __bbegin_bkt = 0;
2139  std::size_t __prev_bkt = 0;
2140  __node_type* __prev_p = nullptr;
2141  bool __check_bucket = false;
2142 
2143  while (__p)
2144  {
2145  __node_type* __next = __p->_M_next();
2146  std::size_t __bkt = __hash_code_base::_M_bucket_index(__p, __n);
2147 
2148  if (__prev_p && __prev_bkt == __bkt)
2149  {
2150  // Previous insert was already in this bucket, we insert after
2151  // the previously inserted one to preserve equivalent elements
2152  // relative order.
2153  __p->_M_nxt = __prev_p->_M_nxt;
2154  __prev_p->_M_nxt = __p;
2155 
2156  // Inserting after a node in a bucket require to check that we
2157  // haven't change the bucket last node, in this case next
2158  // bucket containing its before begin node must be updated. We
2159  // schedule a check as soon as we move out of the sequence of
2160  // equivalent nodes to limit the number of checks.
2161  __check_bucket = true;
2162  }
2163  else
2164  {
2165  if (__check_bucket)
2166  {
2167  // Check if we shall update the next bucket because of
2168  // insertions into __prev_bkt bucket.
2169  if (__prev_p->_M_nxt)
2170  {
2171  std::size_t __next_bkt
2172  = __hash_code_base::_M_bucket_index(__prev_p->_M_next(),
2173  __n);
2174  if (__next_bkt != __prev_bkt)
2175  __new_buckets[__next_bkt] = __prev_p;
2176  }
2177  __check_bucket = false;
2178  }
2179 
2180  if (!__new_buckets[__bkt])
2181  {
2182  __p->_M_nxt = _M_before_begin()._M_nxt;
2183  _M_before_begin()._M_nxt = __p;
2184  __new_buckets[__bkt] = &_M_before_begin();
2185  if (__p->_M_nxt)
2186  __new_buckets[__bbegin_bkt] = __p;
2187  __bbegin_bkt = __bkt;
2188  }
2189  else
2190  {
2191  __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2192  __new_buckets[__bkt]->_M_nxt = __p;
2193  }
2194  }
2195  __prev_p = __p;
2196  __prev_bkt = __bkt;
2197  __p = __next;
2198  }
2199 
2200  if (__check_bucket && __prev_p->_M_nxt)
2201  {
2202  std::size_t __next_bkt
2203  = __hash_code_base::_M_bucket_index(__prev_p->_M_next(), __n);
2204  if (__next_bkt != __prev_bkt)
2205  __new_buckets[__next_bkt] = __prev_p;
2206  }
2207 
2208  if (__builtin_expect(_M_bucket_count != 0, true))
2209  _M_deallocate_buckets();
2210  _M_bucket_count = __n;
2211  _M_buckets = __new_buckets;
2212  }
2213 
2214 _GLIBCXX_END_NAMESPACE_VERSION
2215 } // namespace std
2216 
2217 #endif // _HASHTABLE_H