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