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

1192 lines
41KB

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