You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2229 lines
73KB

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