hashtable.h 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181
  1. // TR1 hashtable.h header -*- C++ -*-
  2. // Copyright (C) 2007-2015 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 tr1/hashtable.h
  21. * This is an internal header file, included by other library headers.
  22. * Do not attempt to use it directly.
  23. * @headername{tr1/unordered_set, tr1/unordered_map}
  24. */
  25. #ifndef _GLIBCXX_TR1_HASHTABLE_H
  26. #define _GLIBCXX_TR1_HASHTABLE_H 1
  27. #pragma GCC system_header
  28. #include <tr1/hashtable_policy.h>
  29. namespace std _GLIBCXX_VISIBILITY(default)
  30. {
  31. namespace tr1
  32. {
  33. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  34. // Class template _Hashtable, class definition.
  35. // Meaning of class template _Hashtable's template parameters
  36. // _Key and _Value: arbitrary CopyConstructible types.
  37. // _Allocator: an allocator type ([lib.allocator.requirements]) whose
  38. // value type is Value. As a conforming extension, we allow for
  39. // value type != Value.
  40. // _ExtractKey: function object that takes a object of type Value
  41. // and returns a value of type _Key.
  42. // _Equal: function object that takes two objects of type k and returns
  43. // a bool-like value that is true if the two objects are considered equal.
  44. // _H1: the hash function. A unary function object with argument type
  45. // Key and result type size_t. Return values should be distributed
  46. // over the entire range [0, numeric_limits<size_t>:::max()].
  47. // _H2: the range-hashing function (in the terminology of Tavori and
  48. // Dreizin). A binary function object whose argument types and result
  49. // type are all size_t. Given arguments r and N, the return value is
  50. // in the range [0, N).
  51. // _Hash: the ranged hash function (Tavori and Dreizin). A binary function
  52. // whose argument types are _Key and size_t and whose result type is
  53. // size_t. Given arguments k and N, the return value is in the range
  54. // [0, N). Default: hash(k, N) = h2(h1(k), N). If _Hash is anything other
  55. // than the default, _H1 and _H2 are ignored.
  56. // _RehashPolicy: Policy class with three members, all of which govern
  57. // the bucket count. _M_next_bkt(n) returns a bucket count no smaller
  58. // than n. _M_bkt_for_elements(n) returns a bucket count appropriate
  59. // for an element count of n. _M_need_rehash(n_bkt, n_elt, n_ins)
  60. // determines whether, if the current bucket count is n_bkt and the
  61. // current element count is n_elt, we need to increase the bucket
  62. // count. If so, returns make_pair(true, n), where n is the new
  63. // bucket count. If not, returns make_pair(false, <anything>).
  64. // ??? Right now it is hard-wired that the number of buckets never
  65. // shrinks. Should we allow _RehashPolicy to change that?
  66. // __cache_hash_code: bool. true if we store the value of the hash
  67. // function along with the value. This is a time-space tradeoff.
  68. // Storing it may improve lookup speed by reducing the number of times
  69. // we need to call the Equal function.
  70. // __constant_iterators: bool. true if iterator and const_iterator are
  71. // both constant iterator types. This is true for unordered_set and
  72. // unordered_multiset, false for unordered_map and unordered_multimap.
  73. // __unique_keys: bool. true if the return value of _Hashtable::count(k)
  74. // is always at most one, false if it may be an arbitrary number. This
  75. // true for unordered_set and unordered_map, false for unordered_multiset
  76. // and unordered_multimap.
  77. template<typename _Key, typename _Value, typename _Allocator,
  78. typename _ExtractKey, typename _Equal,
  79. typename _H1, typename _H2, typename _Hash,
  80. typename _RehashPolicy,
  81. bool __cache_hash_code,
  82. bool __constant_iterators,
  83. bool __unique_keys>
  84. class _Hashtable
  85. : public __detail::_Rehash_base<_RehashPolicy,
  86. _Hashtable<_Key, _Value, _Allocator,
  87. _ExtractKey,
  88. _Equal, _H1, _H2, _Hash,
  89. _RehashPolicy,
  90. __cache_hash_code,
  91. __constant_iterators,
  92. __unique_keys> >,
  93. public __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
  94. _H1, _H2, _Hash, __cache_hash_code>,
  95. public __detail::_Map_base<_Key, _Value, _ExtractKey, __unique_keys,
  96. _Hashtable<_Key, _Value, _Allocator,
  97. _ExtractKey,
  98. _Equal, _H1, _H2, _Hash,
  99. _RehashPolicy,
  100. __cache_hash_code,
  101. __constant_iterators,
  102. __unique_keys> >
  103. {
  104. public:
  105. typedef _Allocator allocator_type;
  106. typedef _Value value_type;
  107. typedef _Key key_type;
  108. typedef _Equal key_equal;
  109. // mapped_type, if present, comes from _Map_base.
  110. // hasher, if present, comes from _Hash_code_base.
  111. typedef typename _Allocator::difference_type difference_type;
  112. typedef typename _Allocator::size_type size_type;
  113. typedef typename _Allocator::pointer pointer;
  114. typedef typename _Allocator::const_pointer const_pointer;
  115. typedef typename _Allocator::reference reference;
  116. typedef typename _Allocator::const_reference const_reference;
  117. typedef __detail::_Node_iterator<value_type, __constant_iterators,
  118. __cache_hash_code>
  119. local_iterator;
  120. typedef __detail::_Node_const_iterator<value_type,
  121. __constant_iterators,
  122. __cache_hash_code>
  123. const_local_iterator;
  124. typedef __detail::_Hashtable_iterator<value_type, __constant_iterators,
  125. __cache_hash_code>
  126. iterator;
  127. typedef __detail::_Hashtable_const_iterator<value_type,
  128. __constant_iterators,
  129. __cache_hash_code>
  130. const_iterator;
  131. template<typename _Key2, typename _Value2, typename _Ex2, bool __unique2,
  132. typename _Hashtable2>
  133. friend struct __detail::_Map_base;
  134. private:
  135. typedef __detail::_Hash_node<_Value, __cache_hash_code> _Node;
  136. typedef typename _Allocator::template rebind<_Node>::other
  137. _Node_allocator_type;
  138. typedef typename _Allocator::template rebind<_Node*>::other
  139. _Bucket_allocator_type;
  140. typedef typename _Allocator::template rebind<_Value>::other
  141. _Value_allocator_type;
  142. _Node_allocator_type _M_node_allocator;
  143. _Node** _M_buckets;
  144. size_type _M_bucket_count;
  145. size_type _M_element_count;
  146. _RehashPolicy _M_rehash_policy;
  147. _Node*
  148. _M_allocate_node(const value_type& __v);
  149. void
  150. _M_deallocate_node(_Node* __n);
  151. void
  152. _M_deallocate_nodes(_Node**, size_type);
  153. _Node**
  154. _M_allocate_buckets(size_type __n);
  155. void
  156. _M_deallocate_buckets(_Node**, size_type __n);
  157. public:
  158. // Constructor, destructor, assignment, swap
  159. _Hashtable(size_type __bucket_hint,
  160. const _H1&, const _H2&, const _Hash&,
  161. const _Equal&, const _ExtractKey&,
  162. const allocator_type&);
  163. template<typename _InputIterator>
  164. _Hashtable(_InputIterator __first, _InputIterator __last,
  165. size_type __bucket_hint,
  166. const _H1&, const _H2&, const _Hash&,
  167. const _Equal&, const _ExtractKey&,
  168. const allocator_type&);
  169. _Hashtable(const _Hashtable&);
  170. _Hashtable&
  171. operator=(const _Hashtable&);
  172. ~_Hashtable();
  173. void swap(_Hashtable&);
  174. // Basic container operations
  175. iterator
  176. begin()
  177. {
  178. iterator __i(_M_buckets);
  179. if (!__i._M_cur_node)
  180. __i._M_incr_bucket();
  181. return __i;
  182. }
  183. const_iterator
  184. begin() const
  185. {
  186. const_iterator __i(_M_buckets);
  187. if (!__i._M_cur_node)
  188. __i._M_incr_bucket();
  189. return __i;
  190. }
  191. iterator
  192. end()
  193. { return iterator(_M_buckets + _M_bucket_count); }
  194. const_iterator
  195. end() const
  196. { return const_iterator(_M_buckets + _M_bucket_count); }
  197. size_type
  198. size() const
  199. { return _M_element_count; }
  200. bool
  201. empty() const
  202. { return size() == 0; }
  203. allocator_type
  204. get_allocator() const
  205. { return allocator_type(_M_node_allocator); }
  206. _Value_allocator_type
  207. _M_get_Value_allocator() const
  208. { return _Value_allocator_type(_M_node_allocator); }
  209. size_type
  210. max_size() const
  211. { return _M_node_allocator.max_size(); }
  212. // Observers
  213. key_equal
  214. key_eq() const
  215. { return this->_M_eq; }
  216. // hash_function, if present, comes from _Hash_code_base.
  217. // Bucket operations
  218. size_type
  219. bucket_count() const
  220. { return _M_bucket_count; }
  221. size_type
  222. max_bucket_count() const
  223. { return max_size(); }
  224. size_type
  225. bucket_size(size_type __n) const
  226. { return std::distance(begin(__n), end(__n)); }
  227. size_type
  228. bucket(const key_type& __k) const
  229. {
  230. return this->_M_bucket_index(__k, this->_M_hash_code(__k),
  231. bucket_count());
  232. }
  233. local_iterator
  234. begin(size_type __n)
  235. { return local_iterator(_M_buckets[__n]); }
  236. local_iterator
  237. end(size_type)
  238. { return local_iterator(0); }
  239. const_local_iterator
  240. begin(size_type __n) const
  241. { return const_local_iterator(_M_buckets[__n]); }
  242. const_local_iterator
  243. end(size_type) const
  244. { return const_local_iterator(0); }
  245. float
  246. load_factor() const
  247. {
  248. return static_cast<float>(size()) / static_cast<float>(bucket_count());
  249. }
  250. // max_load_factor, if present, comes from _Rehash_base.
  251. // Generalization of max_load_factor. Extension, not found in TR1. Only
  252. // useful if _RehashPolicy is something other than the default.
  253. const _RehashPolicy&
  254. __rehash_policy() const
  255. { return _M_rehash_policy; }
  256. void
  257. __rehash_policy(const _RehashPolicy&);
  258. // Lookup.
  259. iterator
  260. find(const key_type& __k);
  261. const_iterator
  262. find(const key_type& __k) const;
  263. size_type
  264. count(const key_type& __k) const;
  265. std::pair<iterator, iterator>
  266. equal_range(const key_type& __k);
  267. std::pair<const_iterator, const_iterator>
  268. equal_range(const key_type& __k) const;
  269. private: // Find, insert and erase helper functions
  270. // ??? This dispatching is a workaround for the fact that we don't
  271. // have partial specialization of member templates; it would be
  272. // better to just specialize insert on __unique_keys. There may be a
  273. // cleaner workaround.
  274. typedef typename __gnu_cxx::__conditional_type<__unique_keys,
  275. std::pair<iterator, bool>, iterator>::__type
  276. _Insert_Return_Type;
  277. typedef typename __gnu_cxx::__conditional_type<__unique_keys,
  278. std::_Select1st<_Insert_Return_Type>,
  279. std::_Identity<_Insert_Return_Type>
  280. >::__type
  281. _Insert_Conv_Type;
  282. _Node*
  283. _M_find_node(_Node*, const key_type&,
  284. typename _Hashtable::_Hash_code_type) const;
  285. iterator
  286. _M_insert_bucket(const value_type&, size_type,
  287. typename _Hashtable::_Hash_code_type);
  288. std::pair<iterator, bool>
  289. _M_insert(const value_type&, std::tr1::true_type);
  290. iterator
  291. _M_insert(const value_type&, std::tr1::false_type);
  292. void
  293. _M_erase_node(_Node*, _Node**);
  294. public:
  295. // Insert and erase
  296. _Insert_Return_Type
  297. insert(const value_type& __v)
  298. { return _M_insert(__v, std::tr1::integral_constant<bool,
  299. __unique_keys>()); }
  300. iterator
  301. insert(iterator, const value_type& __v)
  302. { return iterator(_Insert_Conv_Type()(this->insert(__v))); }
  303. const_iterator
  304. insert(const_iterator, const value_type& __v)
  305. { return const_iterator(_Insert_Conv_Type()(this->insert(__v))); }
  306. template<typename _InputIterator>
  307. void
  308. insert(_InputIterator __first, _InputIterator __last);
  309. iterator
  310. erase(iterator);
  311. const_iterator
  312. erase(const_iterator);
  313. size_type
  314. erase(const key_type&);
  315. iterator
  316. erase(iterator, iterator);
  317. const_iterator
  318. erase(const_iterator, const_iterator);
  319. void
  320. clear();
  321. // Set number of buckets to be appropriate for container of n element.
  322. void rehash(size_type __n);
  323. private:
  324. // Unconditionally change size of bucket array to n.
  325. void _M_rehash(size_type __n);
  326. };
  327. // Definitions of class template _Hashtable's out-of-line member functions.
  328. template<typename _Key, typename _Value,
  329. typename _Allocator, typename _ExtractKey, typename _Equal,
  330. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  331. bool __chc, bool __cit, bool __uk>
  332. typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  333. _H1, _H2, _Hash, _RehashPolicy,
  334. __chc, __cit, __uk>::_Node*
  335. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  336. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  337. _M_allocate_node(const value_type& __v)
  338. {
  339. _Node* __n = _M_node_allocator.allocate(1);
  340. __try
  341. {
  342. _M_get_Value_allocator().construct(&__n->_M_v, __v);
  343. __n->_M_next = 0;
  344. return __n;
  345. }
  346. __catch(...)
  347. {
  348. _M_node_allocator.deallocate(__n, 1);
  349. __throw_exception_again;
  350. }
  351. }
  352. template<typename _Key, typename _Value,
  353. typename _Allocator, typename _ExtractKey, typename _Equal,
  354. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  355. bool __chc, bool __cit, bool __uk>
  356. void
  357. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  358. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  359. _M_deallocate_node(_Node* __n)
  360. {
  361. _M_get_Value_allocator().destroy(&__n->_M_v);
  362. _M_node_allocator.deallocate(__n, 1);
  363. }
  364. template<typename _Key, typename _Value,
  365. typename _Allocator, typename _ExtractKey, typename _Equal,
  366. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  367. bool __chc, bool __cit, bool __uk>
  368. void
  369. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  370. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  371. _M_deallocate_nodes(_Node** __array, size_type __n)
  372. {
  373. for (size_type __i = 0; __i < __n; ++__i)
  374. {
  375. _Node* __p = __array[__i];
  376. while (__p)
  377. {
  378. _Node* __tmp = __p;
  379. __p = __p->_M_next;
  380. _M_deallocate_node(__tmp);
  381. }
  382. __array[__i] = 0;
  383. }
  384. }
  385. template<typename _Key, typename _Value,
  386. typename _Allocator, typename _ExtractKey, typename _Equal,
  387. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  388. bool __chc, bool __cit, bool __uk>
  389. typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  390. _H1, _H2, _Hash, _RehashPolicy,
  391. __chc, __cit, __uk>::_Node**
  392. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  393. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  394. _M_allocate_buckets(size_type __n)
  395. {
  396. _Bucket_allocator_type __alloc(_M_node_allocator);
  397. // We allocate one extra bucket to hold a sentinel, an arbitrary
  398. // non-null pointer. Iterator increment relies on this.
  399. _Node** __p = __alloc.allocate(__n + 1);
  400. std::fill(__p, __p + __n, (_Node*) 0);
  401. __p[__n] = reinterpret_cast<_Node*>(0x1000);
  402. return __p;
  403. }
  404. template<typename _Key, typename _Value,
  405. typename _Allocator, typename _ExtractKey, typename _Equal,
  406. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  407. bool __chc, bool __cit, bool __uk>
  408. void
  409. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  410. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  411. _M_deallocate_buckets(_Node** __p, size_type __n)
  412. {
  413. _Bucket_allocator_type __alloc(_M_node_allocator);
  414. __alloc.deallocate(__p, __n + 1);
  415. }
  416. template<typename _Key, typename _Value,
  417. typename _Allocator, typename _ExtractKey, typename _Equal,
  418. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  419. bool __chc, bool __cit, bool __uk>
  420. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  421. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  422. _Hashtable(size_type __bucket_hint,
  423. const _H1& __h1, const _H2& __h2, const _Hash& __h,
  424. const _Equal& __eq, const _ExtractKey& __exk,
  425. const allocator_type& __a)
  426. : __detail::_Rehash_base<_RehashPolicy, _Hashtable>(),
  427. __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
  428. _H1, _H2, _Hash, __chc>(__exk, __eq,
  429. __h1, __h2, __h),
  430. __detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(),
  431. _M_node_allocator(__a),
  432. _M_bucket_count(0),
  433. _M_element_count(0),
  434. _M_rehash_policy()
  435. {
  436. _M_bucket_count = _M_rehash_policy._M_next_bkt(__bucket_hint);
  437. _M_buckets = _M_allocate_buckets(_M_bucket_count);
  438. }
  439. template<typename _Key, typename _Value,
  440. typename _Allocator, typename _ExtractKey, typename _Equal,
  441. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  442. bool __chc, bool __cit, bool __uk>
  443. template<typename _InputIterator>
  444. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  445. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  446. _Hashtable(_InputIterator __f, _InputIterator __l,
  447. size_type __bucket_hint,
  448. const _H1& __h1, const _H2& __h2, const _Hash& __h,
  449. const _Equal& __eq, const _ExtractKey& __exk,
  450. const allocator_type& __a)
  451. : __detail::_Rehash_base<_RehashPolicy, _Hashtable>(),
  452. __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
  453. _H1, _H2, _Hash, __chc>(__exk, __eq,
  454. __h1, __h2, __h),
  455. __detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(),
  456. _M_node_allocator(__a),
  457. _M_bucket_count(0),
  458. _M_element_count(0),
  459. _M_rehash_policy()
  460. {
  461. _M_bucket_count = std::max(_M_rehash_policy._M_next_bkt(__bucket_hint),
  462. _M_rehash_policy.
  463. _M_bkt_for_elements(__detail::
  464. __distance_fw(__f,
  465. __l)));
  466. _M_buckets = _M_allocate_buckets(_M_bucket_count);
  467. __try
  468. {
  469. for (; __f != __l; ++__f)
  470. this->insert(*__f);
  471. }
  472. __catch(...)
  473. {
  474. clear();
  475. _M_deallocate_buckets(_M_buckets, _M_bucket_count);
  476. __throw_exception_again;
  477. }
  478. }
  479. template<typename _Key, typename _Value,
  480. typename _Allocator, typename _ExtractKey, typename _Equal,
  481. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  482. bool __chc, bool __cit, bool __uk>
  483. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  484. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  485. _Hashtable(const _Hashtable& __ht)
  486. : __detail::_Rehash_base<_RehashPolicy, _Hashtable>(__ht),
  487. __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
  488. _H1, _H2, _Hash, __chc>(__ht),
  489. __detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(__ht),
  490. _M_node_allocator(__ht._M_node_allocator),
  491. _M_bucket_count(__ht._M_bucket_count),
  492. _M_element_count(__ht._M_element_count),
  493. _M_rehash_policy(__ht._M_rehash_policy)
  494. {
  495. _M_buckets = _M_allocate_buckets(_M_bucket_count);
  496. __try
  497. {
  498. for (size_type __i = 0; __i < __ht._M_bucket_count; ++__i)
  499. {
  500. _Node* __n = __ht._M_buckets[__i];
  501. _Node** __tail = _M_buckets + __i;
  502. while (__n)
  503. {
  504. *__tail = _M_allocate_node(__n->_M_v);
  505. this->_M_copy_code(*__tail, __n);
  506. __tail = &((*__tail)->_M_next);
  507. __n = __n->_M_next;
  508. }
  509. }
  510. }
  511. __catch(...)
  512. {
  513. clear();
  514. _M_deallocate_buckets(_M_buckets, _M_bucket_count);
  515. __throw_exception_again;
  516. }
  517. }
  518. template<typename _Key, typename _Value,
  519. typename _Allocator, typename _ExtractKey, typename _Equal,
  520. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  521. bool __chc, bool __cit, bool __uk>
  522. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  523. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>&
  524. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  525. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  526. operator=(const _Hashtable& __ht)
  527. {
  528. _Hashtable __tmp(__ht);
  529. this->swap(__tmp);
  530. return *this;
  531. }
  532. template<typename _Key, typename _Value,
  533. typename _Allocator, typename _ExtractKey, typename _Equal,
  534. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  535. bool __chc, bool __cit, bool __uk>
  536. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  537. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  538. ~_Hashtable()
  539. {
  540. clear();
  541. _M_deallocate_buckets(_M_buckets, _M_bucket_count);
  542. }
  543. template<typename _Key, typename _Value,
  544. typename _Allocator, typename _ExtractKey, typename _Equal,
  545. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  546. bool __chc, bool __cit, bool __uk>
  547. void
  548. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  549. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  550. swap(_Hashtable& __x)
  551. {
  552. // The only base class with member variables is hash_code_base. We
  553. // define _Hash_code_base::_M_swap because different specializations
  554. // have different members.
  555. __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
  556. _H1, _H2, _Hash, __chc>::_M_swap(__x);
  557. // _GLIBCXX_RESOLVE_LIB_DEFECTS
  558. // 431. Swapping containers with unequal allocators.
  559. std::__alloc_swap<_Node_allocator_type>::_S_do_it(_M_node_allocator,
  560. __x._M_node_allocator);
  561. std::swap(_M_rehash_policy, __x._M_rehash_policy);
  562. std::swap(_M_buckets, __x._M_buckets);
  563. std::swap(_M_bucket_count, __x._M_bucket_count);
  564. std::swap(_M_element_count, __x._M_element_count);
  565. }
  566. template<typename _Key, typename _Value,
  567. typename _Allocator, typename _ExtractKey, typename _Equal,
  568. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  569. bool __chc, bool __cit, bool __uk>
  570. void
  571. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  572. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  573. __rehash_policy(const _RehashPolicy& __pol)
  574. {
  575. _M_rehash_policy = __pol;
  576. size_type __n_bkt = __pol._M_bkt_for_elements(_M_element_count);
  577. if (__n_bkt > _M_bucket_count)
  578. _M_rehash(__n_bkt);
  579. }
  580. template<typename _Key, typename _Value,
  581. typename _Allocator, typename _ExtractKey, typename _Equal,
  582. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  583. bool __chc, bool __cit, bool __uk>
  584. typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  585. _H1, _H2, _Hash, _RehashPolicy,
  586. __chc, __cit, __uk>::iterator
  587. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  588. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  589. find(const key_type& __k)
  590. {
  591. typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
  592. std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
  593. _Node* __p = _M_find_node(_M_buckets[__n], __k, __code);
  594. return __p ? iterator(__p, _M_buckets + __n) : this->end();
  595. }
  596. template<typename _Key, typename _Value,
  597. typename _Allocator, typename _ExtractKey, typename _Equal,
  598. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  599. bool __chc, bool __cit, bool __uk>
  600. typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  601. _H1, _H2, _Hash, _RehashPolicy,
  602. __chc, __cit, __uk>::const_iterator
  603. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  604. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  605. find(const key_type& __k) const
  606. {
  607. typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
  608. std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
  609. _Node* __p = _M_find_node(_M_buckets[__n], __k, __code);
  610. return __p ? const_iterator(__p, _M_buckets + __n) : this->end();
  611. }
  612. template<typename _Key, typename _Value,
  613. typename _Allocator, typename _ExtractKey, typename _Equal,
  614. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  615. bool __chc, bool __cit, bool __uk>
  616. typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  617. _H1, _H2, _Hash, _RehashPolicy,
  618. __chc, __cit, __uk>::size_type
  619. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  620. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  621. count(const key_type& __k) const
  622. {
  623. typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
  624. std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
  625. std::size_t __result = 0;
  626. for (_Node* __p = _M_buckets[__n]; __p; __p = __p->_M_next)
  627. if (this->_M_compare(__k, __code, __p))
  628. ++__result;
  629. return __result;
  630. }
  631. template<typename _Key, typename _Value,
  632. typename _Allocator, typename _ExtractKey, typename _Equal,
  633. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  634. bool __chc, bool __cit, bool __uk>
  635. std::pair<typename _Hashtable<_Key, _Value, _Allocator,
  636. _ExtractKey, _Equal, _H1,
  637. _H2, _Hash, _RehashPolicy,
  638. __chc, __cit, __uk>::iterator,
  639. typename _Hashtable<_Key, _Value, _Allocator,
  640. _ExtractKey, _Equal, _H1,
  641. _H2, _Hash, _RehashPolicy,
  642. __chc, __cit, __uk>::iterator>
  643. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  644. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  645. equal_range(const key_type& __k)
  646. {
  647. typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
  648. std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
  649. _Node** __head = _M_buckets + __n;
  650. _Node* __p = _M_find_node(*__head, __k, __code);
  651. if (__p)
  652. {
  653. _Node* __p1 = __p->_M_next;
  654. for (; __p1; __p1 = __p1->_M_next)
  655. if (!this->_M_compare(__k, __code, __p1))
  656. break;
  657. iterator __first(__p, __head);
  658. iterator __last(__p1, __head);
  659. if (!__p1)
  660. __last._M_incr_bucket();
  661. return std::make_pair(__first, __last);
  662. }
  663. else
  664. return std::make_pair(this->end(), this->end());
  665. }
  666. template<typename _Key, typename _Value,
  667. typename _Allocator, typename _ExtractKey, typename _Equal,
  668. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  669. bool __chc, bool __cit, bool __uk>
  670. std::pair<typename _Hashtable<_Key, _Value, _Allocator,
  671. _ExtractKey, _Equal, _H1,
  672. _H2, _Hash, _RehashPolicy,
  673. __chc, __cit, __uk>::const_iterator,
  674. typename _Hashtable<_Key, _Value, _Allocator,
  675. _ExtractKey, _Equal, _H1,
  676. _H2, _Hash, _RehashPolicy,
  677. __chc, __cit, __uk>::const_iterator>
  678. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  679. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  680. equal_range(const key_type& __k) const
  681. {
  682. typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
  683. std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
  684. _Node** __head = _M_buckets + __n;
  685. _Node* __p = _M_find_node(*__head, __k, __code);
  686. if (__p)
  687. {
  688. _Node* __p1 = __p->_M_next;
  689. for (; __p1; __p1 = __p1->_M_next)
  690. if (!this->_M_compare(__k, __code, __p1))
  691. break;
  692. const_iterator __first(__p, __head);
  693. const_iterator __last(__p1, __head);
  694. if (!__p1)
  695. __last._M_incr_bucket();
  696. return std::make_pair(__first, __last);
  697. }
  698. else
  699. return std::make_pair(this->end(), this->end());
  700. }
  701. // Find the node whose key compares equal to k, beginning the search
  702. // at p (usually the head of a bucket). Return zero if no node is found.
  703. template<typename _Key, typename _Value,
  704. typename _Allocator, typename _ExtractKey, typename _Equal,
  705. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  706. bool __chc, bool __cit, bool __uk>
  707. typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey,
  708. _Equal, _H1, _H2, _Hash, _RehashPolicy,
  709. __chc, __cit, __uk>::_Node*
  710. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  711. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  712. _M_find_node(_Node* __p, const key_type& __k,
  713. typename _Hashtable::_Hash_code_type __code) const
  714. {
  715. for (; __p; __p = __p->_M_next)
  716. if (this->_M_compare(__k, __code, __p))
  717. return __p;
  718. return 0;
  719. }
  720. // Insert v in bucket n (assumes no element with its key already present).
  721. template<typename _Key, typename _Value,
  722. typename _Allocator, typename _ExtractKey, typename _Equal,
  723. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  724. bool __chc, bool __cit, bool __uk>
  725. typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  726. _H1, _H2, _Hash, _RehashPolicy,
  727. __chc, __cit, __uk>::iterator
  728. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  729. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  730. _M_insert_bucket(const value_type& __v, size_type __n,
  731. typename _Hashtable::_Hash_code_type __code)
  732. {
  733. std::pair<bool, std::size_t> __do_rehash
  734. = _M_rehash_policy._M_need_rehash(_M_bucket_count,
  735. _M_element_count, 1);
  736. // Allocate the new node before doing the rehash so that we don't
  737. // do a rehash if the allocation throws.
  738. _Node* __new_node = _M_allocate_node(__v);
  739. __try
  740. {
  741. if (__do_rehash.first)
  742. {
  743. const key_type& __k = this->_M_extract(__v);
  744. __n = this->_M_bucket_index(__k, __code, __do_rehash.second);
  745. _M_rehash(__do_rehash.second);
  746. }
  747. __new_node->_M_next = _M_buckets[__n];
  748. this->_M_store_code(__new_node, __code);
  749. _M_buckets[__n] = __new_node;
  750. ++_M_element_count;
  751. return iterator(__new_node, _M_buckets + __n);
  752. }
  753. __catch(...)
  754. {
  755. _M_deallocate_node(__new_node);
  756. __throw_exception_again;
  757. }
  758. }
  759. // Insert v if no element with its key is already present.
  760. template<typename _Key, typename _Value,
  761. typename _Allocator, typename _ExtractKey, typename _Equal,
  762. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  763. bool __chc, bool __cit, bool __uk>
  764. std::pair<typename _Hashtable<_Key, _Value, _Allocator,
  765. _ExtractKey, _Equal, _H1,
  766. _H2, _Hash, _RehashPolicy,
  767. __chc, __cit, __uk>::iterator, bool>
  768. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  769. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  770. _M_insert(const value_type& __v, std::tr1::true_type)
  771. {
  772. const key_type& __k = this->_M_extract(__v);
  773. typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
  774. size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
  775. if (_Node* __p = _M_find_node(_M_buckets[__n], __k, __code))
  776. return std::make_pair(iterator(__p, _M_buckets + __n), false);
  777. return std::make_pair(_M_insert_bucket(__v, __n, __code), true);
  778. }
  779. // Insert v unconditionally.
  780. template<typename _Key, typename _Value,
  781. typename _Allocator, typename _ExtractKey, typename _Equal,
  782. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  783. bool __chc, bool __cit, bool __uk>
  784. typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  785. _H1, _H2, _Hash, _RehashPolicy,
  786. __chc, __cit, __uk>::iterator
  787. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  788. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  789. _M_insert(const value_type& __v, std::tr1::false_type)
  790. {
  791. std::pair<bool, std::size_t> __do_rehash
  792. = _M_rehash_policy._M_need_rehash(_M_bucket_count,
  793. _M_element_count, 1);
  794. if (__do_rehash.first)
  795. _M_rehash(__do_rehash.second);
  796. const key_type& __k = this->_M_extract(__v);
  797. typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
  798. size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
  799. // First find the node, avoid leaking new_node if compare throws.
  800. _Node* __prev = _M_find_node(_M_buckets[__n], __k, __code);
  801. _Node* __new_node = _M_allocate_node(__v);
  802. if (__prev)
  803. {
  804. __new_node->_M_next = __prev->_M_next;
  805. __prev->_M_next = __new_node;
  806. }
  807. else
  808. {
  809. __new_node->_M_next = _M_buckets[__n];
  810. _M_buckets[__n] = __new_node;
  811. }
  812. this->_M_store_code(__new_node, __code);
  813. ++_M_element_count;
  814. return iterator(__new_node, _M_buckets + __n);
  815. }
  816. // For erase(iterator) and erase(const_iterator).
  817. template<typename _Key, typename _Value,
  818. typename _Allocator, typename _ExtractKey, typename _Equal,
  819. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  820. bool __chc, bool __cit, bool __uk>
  821. void
  822. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  823. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  824. _M_erase_node(_Node* __p, _Node** __b)
  825. {
  826. _Node* __cur = *__b;
  827. if (__cur == __p)
  828. *__b = __cur->_M_next;
  829. else
  830. {
  831. _Node* __next = __cur->_M_next;
  832. while (__next != __p)
  833. {
  834. __cur = __next;
  835. __next = __cur->_M_next;
  836. }
  837. __cur->_M_next = __next->_M_next;
  838. }
  839. _M_deallocate_node(__p);
  840. --_M_element_count;
  841. }
  842. template<typename _Key, typename _Value,
  843. typename _Allocator, typename _ExtractKey, typename _Equal,
  844. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  845. bool __chc, bool __cit, bool __uk>
  846. template<typename _InputIterator>
  847. void
  848. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  849. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  850. insert(_InputIterator __first, _InputIterator __last)
  851. {
  852. size_type __n_elt = __detail::__distance_fw(__first, __last);
  853. std::pair<bool, std::size_t> __do_rehash
  854. = _M_rehash_policy._M_need_rehash(_M_bucket_count,
  855. _M_element_count, __n_elt);
  856. if (__do_rehash.first)
  857. _M_rehash(__do_rehash.second);
  858. for (; __first != __last; ++__first)
  859. this->insert(*__first);
  860. }
  861. template<typename _Key, typename _Value,
  862. typename _Allocator, typename _ExtractKey, typename _Equal,
  863. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  864. bool __chc, bool __cit, bool __uk>
  865. typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  866. _H1, _H2, _Hash, _RehashPolicy,
  867. __chc, __cit, __uk>::iterator
  868. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  869. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  870. erase(iterator __it)
  871. {
  872. iterator __result = __it;
  873. ++__result;
  874. _M_erase_node(__it._M_cur_node, __it._M_cur_bucket);
  875. return __result;
  876. }
  877. template<typename _Key, typename _Value,
  878. typename _Allocator, typename _ExtractKey, typename _Equal,
  879. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  880. bool __chc, bool __cit, bool __uk>
  881. typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  882. _H1, _H2, _Hash, _RehashPolicy,
  883. __chc, __cit, __uk>::const_iterator
  884. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  885. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  886. erase(const_iterator __it)
  887. {
  888. const_iterator __result = __it;
  889. ++__result;
  890. _M_erase_node(__it._M_cur_node, __it._M_cur_bucket);
  891. return __result;
  892. }
  893. template<typename _Key, typename _Value,
  894. typename _Allocator, typename _ExtractKey, typename _Equal,
  895. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  896. bool __chc, bool __cit, bool __uk>
  897. typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  898. _H1, _H2, _Hash, _RehashPolicy,
  899. __chc, __cit, __uk>::size_type
  900. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  901. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  902. erase(const key_type& __k)
  903. {
  904. typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
  905. std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
  906. size_type __result = 0;
  907. _Node** __slot = _M_buckets + __n;
  908. while (*__slot && !this->_M_compare(__k, __code, *__slot))
  909. __slot = &((*__slot)->_M_next);
  910. _Node** __saved_slot = 0;
  911. while (*__slot && this->_M_compare(__k, __code, *__slot))
  912. {
  913. // _GLIBCXX_RESOLVE_LIB_DEFECTS
  914. // 526. Is it undefined if a function in the standard changes
  915. // in parameters?
  916. if (&this->_M_extract((*__slot)->_M_v) != &__k)
  917. {
  918. _Node* __p = *__slot;
  919. *__slot = __p->_M_next;
  920. _M_deallocate_node(__p);
  921. --_M_element_count;
  922. ++__result;
  923. }
  924. else
  925. {
  926. __saved_slot = __slot;
  927. __slot = &((*__slot)->_M_next);
  928. }
  929. }
  930. if (__saved_slot)
  931. {
  932. _Node* __p = *__saved_slot;
  933. *__saved_slot = __p->_M_next;
  934. _M_deallocate_node(__p);
  935. --_M_element_count;
  936. ++__result;
  937. }
  938. return __result;
  939. }
  940. // ??? This could be optimized by taking advantage of the bucket
  941. // structure, but it's not clear that it's worth doing. It probably
  942. // wouldn't even be an optimization unless the load factor is large.
  943. template<typename _Key, typename _Value,
  944. typename _Allocator, typename _ExtractKey, typename _Equal,
  945. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  946. bool __chc, bool __cit, bool __uk>
  947. typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  948. _H1, _H2, _Hash, _RehashPolicy,
  949. __chc, __cit, __uk>::iterator
  950. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  951. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  952. erase(iterator __first, iterator __last)
  953. {
  954. while (__first != __last)
  955. __first = this->erase(__first);
  956. return __last;
  957. }
  958. template<typename _Key, typename _Value,
  959. typename _Allocator, typename _ExtractKey, typename _Equal,
  960. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  961. bool __chc, bool __cit, bool __uk>
  962. typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  963. _H1, _H2, _Hash, _RehashPolicy,
  964. __chc, __cit, __uk>::const_iterator
  965. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  966. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  967. erase(const_iterator __first, const_iterator __last)
  968. {
  969. while (__first != __last)
  970. __first = this->erase(__first);
  971. return __last;
  972. }
  973. template<typename _Key, typename _Value,
  974. typename _Allocator, typename _ExtractKey, typename _Equal,
  975. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  976. bool __chc, bool __cit, bool __uk>
  977. void
  978. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  979. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  980. clear()
  981. {
  982. _M_deallocate_nodes(_M_buckets, _M_bucket_count);
  983. _M_element_count = 0;
  984. }
  985. template<typename _Key, typename _Value,
  986. typename _Allocator, typename _ExtractKey, typename _Equal,
  987. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  988. bool __chc, bool __cit, bool __uk>
  989. void
  990. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  991. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  992. rehash(size_type __n)
  993. {
  994. _M_rehash(std::max(_M_rehash_policy._M_next_bkt(__n),
  995. _M_rehash_policy._M_bkt_for_elements(_M_element_count
  996. + 1)));
  997. }
  998. template<typename _Key, typename _Value,
  999. typename _Allocator, typename _ExtractKey, typename _Equal,
  1000. typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
  1001. bool __chc, bool __cit, bool __uk>
  1002. void
  1003. _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
  1004. _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
  1005. _M_rehash(size_type __n)
  1006. {
  1007. _Node** __new_array = _M_allocate_buckets(__n);
  1008. __try
  1009. {
  1010. for (size_type __i = 0; __i < _M_bucket_count; ++__i)
  1011. while (_Node* __p = _M_buckets[__i])
  1012. {
  1013. std::size_t __new_index = this->_M_bucket_index(__p, __n);
  1014. _M_buckets[__i] = __p->_M_next;
  1015. __p->_M_next = __new_array[__new_index];
  1016. __new_array[__new_index] = __p;
  1017. }
  1018. _M_deallocate_buckets(_M_buckets, _M_bucket_count);
  1019. _M_bucket_count = __n;
  1020. _M_buckets = __new_array;
  1021. }
  1022. __catch(...)
  1023. {
  1024. // A failure here means that a hash function threw an exception.
  1025. // We can't restore the previous state without calling the hash
  1026. // function again, so the only sensible recovery is to delete
  1027. // everything.
  1028. _M_deallocate_nodes(__new_array, __n);
  1029. _M_deallocate_buckets(__new_array, __n);
  1030. _M_deallocate_nodes(_M_buckets, _M_bucket_count);
  1031. _M_element_count = 0;
  1032. __throw_exception_again;
  1033. }
  1034. }
  1035. _GLIBCXX_END_NAMESPACE_VERSION
  1036. } // namespace tr1
  1037. } // namespace std
  1038. #endif // _GLIBCXX_TR1_HASHTABLE_H