hashtable.h 89 KB

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