Home | History | Annotate | Download | only in backward
      1 // Hashtable implementation used by containers -*- C++ -*-
      2 
      3 // Copyright (C) 2001-2013 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 /*
     26  * Copyright (c) 1996,1997
     27  * Silicon Graphics Computer Systems, Inc.
     28  *
     29  * Permission to use, copy, modify, distribute and sell this software
     30  * and its documentation for any purpose is hereby granted without fee,
     31  * provided that the above copyright notice appear in all copies and
     32  * that both that copyright notice and this permission notice appear
     33  * in supporting documentation.  Silicon Graphics makes no
     34  * representations about the suitability of this software for any
     35  * purpose.  It is provided "as is" without express or implied warranty.
     36  *
     37  *
     38  * Copyright (c) 1994
     39  * Hewlett-Packard Company
     40  *
     41  * Permission to use, copy, modify, distribute and sell this software
     42  * and its documentation for any purpose is hereby granted without fee,
     43  * provided that the above copyright notice appear in all copies and
     44  * that both that copyright notice and this permission notice appear
     45  * in supporting documentation.  Hewlett-Packard Company makes no
     46  * representations about the suitability of this software for any
     47  * purpose.  It is provided "as is" without express or implied warranty.
     48  *
     49  */
     50 
     51 /** @file backward/hashtable.h
     52  *  This file is a GNU extension to the Standard C++ Library (possibly
     53  *  containing extensions from the HP/SGI STL subset).
     54  */
     55 
     56 #ifndef _BACKWARD_HASHTABLE_H
     57 #define _BACKWARD_HASHTABLE_H 1
     58 
     59 // Hashtable class, used to implement the hashed associative containers
     60 // hash_set, hash_map, hash_multiset, and hash_multimap.
     61 
     62 #include <vector>
     63 #include <iterator>
     64 #include <algorithm>
     65 #include <bits/stl_function.h>
     66 #include <backward/hash_fun.h>
     67 
     68 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
     69 {
     70 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     71 
     72   using std::size_t;
     73   using std::ptrdiff_t;
     74   using std::forward_iterator_tag;
     75   using std::input_iterator_tag;
     76   using std::_Construct;
     77   using std::_Destroy;
     78   using std::distance;
     79   using std::vector;
     80   using std::pair;
     81   using std::__iterator_category;
     82 
     83   template<class _Val>
     84     struct _Hashtable_node
     85     {
     86       _Hashtable_node* _M_next;
     87       _Val _M_val;
     88     };
     89 
     90   template<class _Val, class _Key, class _HashFcn, class _ExtractKey,
     91 	   class _EqualKey, class _Alloc = std::allocator<_Val> >
     92     class hashtable;
     93 
     94   template<class _Val, class _Key, class _HashFcn,
     95 	   class _ExtractKey, class _EqualKey, class _Alloc>
     96     struct _Hashtable_iterator;
     97 
     98   template<class _Val, class _Key, class _HashFcn,
     99 	   class _ExtractKey, class _EqualKey, class _Alloc>
    100     struct _Hashtable_const_iterator;
    101 
    102   template<class _Val, class _Key, class _HashFcn,
    103 	   class _ExtractKey, class _EqualKey, class _Alloc>
    104     struct _Hashtable_iterator
    105     {
    106       typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>
    107         _Hashtable;
    108       typedef _Hashtable_iterator<_Val, _Key, _HashFcn,
    109 				  _ExtractKey, _EqualKey, _Alloc>
    110         iterator;
    111       typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
    112 					_ExtractKey, _EqualKey, _Alloc>
    113         const_iterator;
    114       typedef _Hashtable_node<_Val> _Node;
    115       typedef forward_iterator_tag iterator_category;
    116       typedef _Val value_type;
    117       typedef ptrdiff_t difference_type;
    118       typedef size_t size_type;
    119       typedef _Val& reference;
    120       typedef _Val* pointer;
    121 
    122       _Node* _M_cur;
    123       _Hashtable* _M_ht;
    124 
    125       _Hashtable_iterator(_Node* __n, _Hashtable* __tab)
    126       : _M_cur(__n), _M_ht(__tab) { }
    127 
    128       _Hashtable_iterator() { }
    129 
    130       reference
    131       operator*() const
    132       { return _M_cur->_M_val; }
    133 
    134       pointer
    135       operator->() const
    136       { return &(operator*()); }
    137 
    138       iterator&
    139       operator++();
    140 
    141       iterator
    142       operator++(int);
    143 
    144       bool
    145       operator==(const iterator& __it) const
    146       { return _M_cur == __it._M_cur; }
    147 
    148       bool
    149       operator!=(const iterator& __it) const
    150       { return _M_cur != __it._M_cur; }
    151     };
    152 
    153   template<class _Val, class _Key, class _HashFcn,
    154 	   class _ExtractKey, class _EqualKey, class _Alloc>
    155     struct _Hashtable_const_iterator
    156     {
    157       typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>
    158         _Hashtable;
    159       typedef _Hashtable_iterator<_Val,_Key,_HashFcn,
    160 				  _ExtractKey,_EqualKey,_Alloc>
    161         iterator;
    162       typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
    163 					_ExtractKey, _EqualKey, _Alloc>
    164         const_iterator;
    165       typedef _Hashtable_node<_Val> _Node;
    166 
    167       typedef forward_iterator_tag iterator_category;
    168       typedef _Val value_type;
    169       typedef ptrdiff_t difference_type;
    170       typedef size_t size_type;
    171       typedef const _Val& reference;
    172       typedef const _Val* pointer;
    173 
    174       const _Node* _M_cur;
    175       const _Hashtable* _M_ht;
    176 
    177       _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab)
    178       : _M_cur(__n), _M_ht(__tab) { }
    179 
    180       _Hashtable_const_iterator() { }
    181 
    182       _Hashtable_const_iterator(const iterator& __it)
    183       : _M_cur(__it._M_cur), _M_ht(__it._M_ht) { }
    184 
    185       reference
    186       operator*() const
    187       { return _M_cur->_M_val; }
    188 
    189       pointer
    190       operator->() const
    191       { return &(operator*()); }
    192 
    193       const_iterator&
    194       operator++();
    195 
    196       const_iterator
    197       operator++(int);
    198 
    199       bool
    200       operator==(const const_iterator& __it) const
    201       { return _M_cur == __it._M_cur; }
    202 
    203       bool
    204       operator!=(const const_iterator& __it) const
    205       { return _M_cur != __it._M_cur; }
    206     };
    207 
    208   // Note: assumes long is at least 32 bits.
    209   enum { _S_num_primes = 29 };
    210 
    211   template<typename _PrimeType>
    212     struct _Hashtable_prime_list
    213     {
    214       static const _PrimeType  __stl_prime_list[_S_num_primes];
    215 
    216       static const _PrimeType*
    217       _S_get_prime_list();
    218     };
    219 
    220   template<typename _PrimeType> const _PrimeType
    221   _Hashtable_prime_list<_PrimeType>::__stl_prime_list[_S_num_primes] =
    222     {
    223       5ul,          53ul,         97ul,         193ul,       389ul,
    224       769ul,        1543ul,       3079ul,       6151ul,      12289ul,
    225       24593ul,      49157ul,      98317ul,      196613ul,    393241ul,
    226       786433ul,     1572869ul,    3145739ul,    6291469ul,   12582917ul,
    227       25165843ul,   50331653ul,   100663319ul,  201326611ul, 402653189ul,
    228       805306457ul,  1610612741ul, 3221225473ul, 4294967291ul
    229     };
    230 
    231  template<class _PrimeType> inline const _PrimeType*
    232  _Hashtable_prime_list<_PrimeType>::_S_get_prime_list()
    233  {
    234    return __stl_prime_list;
    235  }
    236 
    237   inline unsigned long
    238   __stl_next_prime(unsigned long __n)
    239   {
    240     const unsigned long* __first = _Hashtable_prime_list<unsigned long>::_S_get_prime_list();
    241     const unsigned long* __last = __first + (int)_S_num_primes;
    242     const unsigned long* pos = std::lower_bound(__first, __last, __n);
    243     return pos == __last ? *(__last - 1) : *pos;
    244   }
    245 
    246   // Forward declaration of operator==.
    247   template<class _Val, class _Key, class _HF, class _Ex,
    248 	   class _Eq, class _All>
    249     class hashtable;
    250 
    251   template<class _Val, class _Key, class _HF, class _Ex,
    252 	   class _Eq, class _All>
    253     bool
    254     operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
    255 	       const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2);
    256 
    257   // Hashtables handle allocators a bit differently than other
    258   // containers do.  If we're using standard-conforming allocators, then
    259   // a hashtable unconditionally has a member variable to hold its
    260   // allocator, even if it so happens that all instances of the
    261   // allocator type are identical.  This is because, for hashtables,
    262   // this extra storage is negligible.  Additionally, a base class
    263   // wouldn't serve any other purposes; it wouldn't, for example,
    264   // simplify the exception-handling code.
    265   template<class _Val, class _Key, class _HashFcn,
    266 	   class _ExtractKey, class _EqualKey, class _Alloc>
    267     class hashtable
    268     {
    269     public:
    270       typedef _Key key_type;
    271       typedef _Val value_type;
    272       typedef _HashFcn hasher;
    273       typedef _EqualKey key_equal;
    274 
    275       typedef size_t            size_type;
    276       typedef ptrdiff_t         difference_type;
    277       typedef value_type*       pointer;
    278       typedef const value_type* const_pointer;
    279       typedef value_type&       reference;
    280       typedef const value_type& const_reference;
    281 
    282       hasher
    283       hash_funct() const
    284       { return _M_hash; }
    285 
    286       key_equal
    287       key_eq() const
    288       { return _M_equals; }
    289 
    290     private:
    291       typedef _Hashtable_node<_Val> _Node;
    292 
    293     public:
    294       typedef typename _Alloc::template rebind<value_type>::other allocator_type;
    295       allocator_type
    296       get_allocator() const
    297       { return _M_node_allocator; }
    298 
    299     private:
    300       typedef typename _Alloc::template rebind<_Node>::other _Node_Alloc;
    301       typedef typename _Alloc::template rebind<_Node*>::other _Nodeptr_Alloc;
    302       typedef vector<_Node*, _Nodeptr_Alloc> _Vector_type;
    303 
    304       _Node_Alloc _M_node_allocator;
    305 
    306       _Node*
    307       _M_get_node()
    308       { return _M_node_allocator.allocate(1); }
    309 
    310       void
    311       _M_put_node(_Node* __p)
    312       { _M_node_allocator.deallocate(__p, 1); }
    313 
    314     private:
    315       hasher                _M_hash;
    316       key_equal             _M_equals;
    317       _ExtractKey           _M_get_key;
    318       _Vector_type          _M_buckets;
    319       size_type             _M_num_elements;
    320 
    321     public:
    322       typedef _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey,
    323 				  _EqualKey, _Alloc>
    324         iterator;
    325       typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey,
    326 					_EqualKey, _Alloc>
    327         const_iterator;
    328 
    329       friend struct
    330       _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>;
    331 
    332       friend struct
    333       _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey,
    334 				_EqualKey, _Alloc>;
    335 
    336     public:
    337       hashtable(size_type __n, const _HashFcn& __hf,
    338 		const _EqualKey& __eql, const _ExtractKey& __ext,
    339 		const allocator_type& __a = allocator_type())
    340       : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql),
    341 	_M_get_key(__ext), _M_buckets(__a), _M_num_elements(0)
    342       { _M_initialize_buckets(__n); }
    343 
    344       hashtable(size_type __n, const _HashFcn& __hf,
    345 		const _EqualKey& __eql,
    346 		const allocator_type& __a = allocator_type())
    347       : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql),
    348 	_M_get_key(_ExtractKey()), _M_buckets(__a), _M_num_elements(0)
    349       { _M_initialize_buckets(__n); }
    350 
    351       hashtable(const hashtable& __ht)
    352       : _M_node_allocator(__ht.get_allocator()), _M_hash(__ht._M_hash),
    353       _M_equals(__ht._M_equals), _M_get_key(__ht._M_get_key),
    354       _M_buckets(__ht.get_allocator()), _M_num_elements(0)
    355       { _M_copy_from(__ht); }
    356 
    357       hashtable&
    358       operator= (const hashtable& __ht)
    359       {
    360 	if (&__ht != this)
    361 	  {
    362 	    clear();
    363 	    _M_hash = __ht._M_hash;
    364 	    _M_equals = __ht._M_equals;
    365 	    _M_get_key = __ht._M_get_key;
    366 	    _M_copy_from(__ht);
    367 	  }
    368 	return *this;
    369       }
    370 
    371       ~hashtable()
    372       { clear(); }
    373 
    374       size_type
    375       size() const
    376       { return _M_num_elements; }
    377 
    378       size_type
    379       max_size() const
    380       { return size_type(-1); }
    381 
    382       bool
    383       empty() const
    384       { return size() == 0; }
    385 
    386       void
    387       swap(hashtable& __ht)
    388       {
    389 	std::swap(_M_hash, __ht._M_hash);
    390 	std::swap(_M_equals, __ht._M_equals);
    391 	std::swap(_M_get_key, __ht._M_get_key);
    392 	_M_buckets.swap(__ht._M_buckets);
    393 	std::swap(_M_num_elements, __ht._M_num_elements);
    394       }
    395 
    396       iterator
    397       begin()
    398       {
    399 	for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
    400 	  if (_M_buckets[__n])
    401 	    return iterator(_M_buckets[__n], this);
    402 	return end();
    403       }
    404 
    405       iterator
    406       end()
    407       { return iterator(0, this); }
    408 
    409       const_iterator
    410       begin() const
    411       {
    412 	for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
    413 	  if (_M_buckets[__n])
    414 	    return const_iterator(_M_buckets[__n], this);
    415 	return end();
    416       }
    417 
    418       const_iterator
    419       end() const
    420       { return const_iterator(0, this); }
    421 
    422       template<class _Vl, class _Ky, class _HF, class _Ex, class _Eq,
    423 		class _Al>
    424         friend bool
    425         operator==(const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&,
    426 		   const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&);
    427 
    428     public:
    429       size_type
    430       bucket_count() const
    431       { return _M_buckets.size(); }
    432 
    433       size_type
    434       max_bucket_count() const
    435       { return _Hashtable_prime_list<unsigned long>::
    436                _S_get_prime_list()[(int)_S_num_primes - 1];
    437       }
    438 
    439       size_type
    440       elems_in_bucket(size_type __bucket) const
    441       {
    442 	size_type __result = 0;
    443 	for (_Node* __n = _M_buckets[__bucket]; __n; __n = __n->_M_next)
    444 	  __result += 1;
    445 	return __result;
    446       }
    447 
    448       pair<iterator, bool>
    449       insert_unique(const value_type& __obj)
    450       {
    451 	resize(_M_num_elements + 1);
    452 	return insert_unique_noresize(__obj);
    453       }
    454 
    455       iterator
    456       insert_equal(const value_type& __obj)
    457       {
    458 	resize(_M_num_elements + 1);
    459 	return insert_equal_noresize(__obj);
    460       }
    461 
    462       pair<iterator, bool>
    463       insert_unique_noresize(const value_type& __obj);
    464 
    465       iterator
    466       insert_equal_noresize(const value_type& __obj);
    467 
    468       template<class _InputIterator>
    469         void
    470         insert_unique(_InputIterator __f, _InputIterator __l)
    471         { insert_unique(__f, __l, __iterator_category(__f)); }
    472 
    473       template<class _InputIterator>
    474         void
    475         insert_equal(_InputIterator __f, _InputIterator __l)
    476         { insert_equal(__f, __l, __iterator_category(__f)); }
    477 
    478       template<class _InputIterator>
    479         void
    480         insert_unique(_InputIterator __f, _InputIterator __l,
    481 		      input_iterator_tag)
    482         {
    483 	  for ( ; __f != __l; ++__f)
    484 	    insert_unique(*__f);
    485 	}
    486 
    487       template<class _InputIterator>
    488         void
    489         insert_equal(_InputIterator __f, _InputIterator __l,
    490 		     input_iterator_tag)
    491         {
    492 	  for ( ; __f != __l; ++__f)
    493 	    insert_equal(*__f);
    494 	}
    495 
    496       template<class _ForwardIterator>
    497         void
    498         insert_unique(_ForwardIterator __f, _ForwardIterator __l,
    499 		      forward_iterator_tag)
    500         {
    501 	  size_type __n = distance(__f, __l);
    502 	  resize(_M_num_elements + __n);
    503 	  for ( ; __n > 0; --__n, ++__f)
    504 	    insert_unique_noresize(*__f);
    505 	}
    506 
    507       template<class _ForwardIterator>
    508         void
    509         insert_equal(_ForwardIterator __f, _ForwardIterator __l,
    510 		     forward_iterator_tag)
    511         {
    512 	  size_type __n = distance(__f, __l);
    513 	  resize(_M_num_elements + __n);
    514 	  for ( ; __n > 0; --__n, ++__f)
    515 	    insert_equal_noresize(*__f);
    516 	}
    517 
    518       reference
    519       find_or_insert(const value_type& __obj);
    520 
    521       iterator
    522       find(const key_type& __key)
    523       {
    524 	size_type __n = _M_bkt_num_key(__key);
    525 	_Node* __first;
    526 	for (__first = _M_buckets[__n];
    527 	     __first && !_M_equals(_M_get_key(__first->_M_val), __key);
    528 	     __first = __first->_M_next)
    529 	  { }
    530 	return iterator(__first, this);
    531       }
    532 
    533       const_iterator
    534       find(const key_type& __key) const
    535       {
    536 	size_type __n = _M_bkt_num_key(__key);
    537 	const _Node* __first;
    538 	for (__first = _M_buckets[__n];
    539 	     __first && !_M_equals(_M_get_key(__first->_M_val), __key);
    540 	     __first = __first->_M_next)
    541 	  { }
    542 	return const_iterator(__first, this);
    543       }
    544 
    545       size_type
    546       count(const key_type& __key) const
    547       {
    548 	const size_type __n = _M_bkt_num_key(__key);
    549 	size_type __result = 0;
    550 
    551 	for (const _Node* __cur = _M_buckets[__n]; __cur;
    552 	     __cur = __cur->_M_next)
    553 	  if (_M_equals(_M_get_key(__cur->_M_val), __key))
    554 	    ++__result;
    555 	return __result;
    556       }
    557 
    558       pair<iterator, iterator>
    559       equal_range(const key_type& __key);
    560 
    561       pair<const_iterator, const_iterator>
    562       equal_range(const key_type& __key) const;
    563 
    564       size_type
    565       erase(const key_type& __key);
    566 
    567       void
    568       erase(const iterator& __it);
    569 
    570       void
    571       erase(iterator __first, iterator __last);
    572 
    573       void
    574       erase(const const_iterator& __it);
    575 
    576       void
    577       erase(const_iterator __first, const_iterator __last);
    578 
    579       void
    580       resize(size_type __num_elements_hint);
    581 
    582       void
    583       clear();
    584 
    585     private:
    586       size_type
    587       _M_next_size(size_type __n) const
    588       { return __stl_next_prime(__n); }
    589 
    590       void
    591       _M_initialize_buckets(size_type __n)
    592       {
    593 	const size_type __n_buckets = _M_next_size(__n);
    594 	_M_buckets.reserve(__n_buckets);
    595 	_M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0);
    596 	_M_num_elements = 0;
    597       }
    598 
    599       size_type
    600       _M_bkt_num_key(const key_type& __key) const
    601       { return _M_bkt_num_key(__key, _M_buckets.size()); }
    602 
    603       size_type
    604       _M_bkt_num(const value_type& __obj) const
    605       { return _M_bkt_num_key(_M_get_key(__obj)); }
    606 
    607       size_type
    608       _M_bkt_num_key(const key_type& __key, size_t __n) const
    609       { return _M_hash(__key) % __n; }
    610 
    611       size_type
    612       _M_bkt_num(const value_type& __obj, size_t __n) const
    613       { return _M_bkt_num_key(_M_get_key(__obj), __n); }
    614 
    615       _Node*
    616       _M_new_node(const value_type& __obj)
    617       {
    618 	_Node* __n = _M_get_node();
    619 	__n->_M_next = 0;
    620 	__try
    621 	  {
    622 	    this->get_allocator().construct(&__n->_M_val, __obj);
    623 	    return __n;
    624 	  }
    625 	__catch(...)
    626 	  {
    627 	    _M_put_node(__n);
    628 	    __throw_exception_again;
    629 	  }
    630       }
    631 
    632       void
    633       _M_delete_node(_Node* __n)
    634       {
    635 	this->get_allocator().destroy(&__n->_M_val);
    636 	_M_put_node(__n);
    637       }
    638 
    639       void
    640       _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last);
    641 
    642       void
    643       _M_erase_bucket(const size_type __n, _Node* __last);
    644 
    645       void
    646       _M_copy_from(const hashtable& __ht);
    647     };
    648 
    649   template<class _Val, class _Key, class _HF, class _ExK, class _EqK,
    650 	    class _All>
    651     _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>&
    652     _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
    653     operator++()
    654     {
    655       const _Node* __old = _M_cur;
    656       _M_cur = _M_cur->_M_next;
    657       if (!_M_cur)
    658 	{
    659 	  size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
    660 	  while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
    661 	    _M_cur = _M_ht->_M_buckets[__bucket];
    662 	}
    663       return *this;
    664     }
    665 
    666   template<class _Val, class _Key, class _HF, class _ExK, class _EqK,
    667 	    class _All>
    668     inline _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>
    669     _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
    670     operator++(int)
    671     {
    672       iterator __tmp = *this;
    673       ++*this;
    674       return __tmp;
    675     }
    676 
    677   template<class _Val, class _Key, class _HF, class _ExK, class _EqK,
    678 	    class _All>
    679     _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>&
    680     _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
    681     operator++()
    682     {
    683       const _Node* __old = _M_cur;
    684       _M_cur = _M_cur->_M_next;
    685       if (!_M_cur)
    686 	{
    687 	  size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
    688 	  while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
    689 	    _M_cur = _M_ht->_M_buckets[__bucket];
    690 	}
    691       return *this;
    692     }
    693 
    694   template<class _Val, class _Key, class _HF, class _ExK, class _EqK,
    695 	    class _All>
    696     inline _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>
    697     _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
    698     operator++(int)
    699     {
    700       const_iterator __tmp = *this;
    701       ++*this;
    702       return __tmp;
    703     }
    704 
    705   template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
    706     bool
    707     operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
    708 	       const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2)
    709     {
    710       typedef typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::_Node _Node;
    711 
    712       if (__ht1._M_buckets.size() != __ht2._M_buckets.size())
    713 	return false;
    714 
    715       for (size_t __n = 0; __n < __ht1._M_buckets.size(); ++__n)
    716 	{
    717 	  _Node* __cur1 = __ht1._M_buckets[__n];
    718 	  _Node* __cur2 = __ht2._M_buckets[__n];
    719 	  // Check same length of lists
    720 	  for (; __cur1 && __cur2;
    721 	       __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next)
    722 	    { }
    723 	  if (__cur1 || __cur2)
    724 	    return false;
    725 	  // Now check one's elements are in the other
    726 	  for (__cur1 = __ht1._M_buckets[__n] ; __cur1;
    727 	       __cur1 = __cur1->_M_next)
    728 	    {
    729 	      bool _found__cur1 = false;
    730 	      for (__cur2 = __ht2._M_buckets[__n];
    731 		   __cur2; __cur2 = __cur2->_M_next)
    732 		{
    733 		  if (__cur1->_M_val == __cur2->_M_val)
    734 		    {
    735 		      _found__cur1 = true;
    736 		      break;
    737 		    }
    738 		}
    739 	      if (!_found__cur1)
    740 		return false;
    741 	    }
    742 	}
    743       return true;
    744     }
    745 
    746   template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
    747     inline bool
    748     operator!=(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
    749 	       const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2)
    750     { return !(__ht1 == __ht2); }
    751 
    752   template<class _Val, class _Key, class _HF, class _Extract, class _EqKey,
    753 	    class _All>
    754     inline void
    755     swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1,
    756 	 hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2)
    757     { __ht1.swap(__ht2); }
    758 
    759   template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
    760     pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator, bool>
    761     hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
    762     insert_unique_noresize(const value_type& __obj)
    763     {
    764       const size_type __n = _M_bkt_num(__obj);
    765       _Node* __first = _M_buckets[__n];
    766 
    767       for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
    768 	if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
    769 	  return pair<iterator, bool>(iterator(__cur, this), false);
    770 
    771       _Node* __tmp = _M_new_node(__obj);
    772       __tmp->_M_next = __first;
    773       _M_buckets[__n] = __tmp;
    774       ++_M_num_elements;
    775       return pair<iterator, bool>(iterator(__tmp, this), true);
    776     }
    777 
    778   template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
    779     typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator
    780     hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
    781     insert_equal_noresize(const value_type& __obj)
    782     {
    783       const size_type __n = _M_bkt_num(__obj);
    784       _Node* __first = _M_buckets[__n];
    785 
    786       for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
    787 	if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
    788 	  {
    789 	    _Node* __tmp = _M_new_node(__obj);
    790 	    __tmp->_M_next = __cur->_M_next;
    791 	    __cur->_M_next = __tmp;
    792 	    ++_M_num_elements;
    793 	    return iterator(__tmp, this);
    794 	  }
    795 
    796       _Node* __tmp = _M_new_node(__obj);
    797       __tmp->_M_next = __first;
    798       _M_buckets[__n] = __tmp;
    799       ++_M_num_elements;
    800       return iterator(__tmp, this);
    801     }
    802 
    803   template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
    804     typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::reference
    805     hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
    806     find_or_insert(const value_type& __obj)
    807     {
    808       resize(_M_num_elements + 1);
    809 
    810       size_type __n = _M_bkt_num(__obj);
    811       _Node* __first = _M_buckets[__n];
    812 
    813       for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
    814 	if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
    815 	  return __cur->_M_val;
    816 
    817       _Node* __tmp = _M_new_node(__obj);
    818       __tmp->_M_next = __first;
    819       _M_buckets[__n] = __tmp;
    820       ++_M_num_elements;
    821       return __tmp->_M_val;
    822     }
    823 
    824   template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
    825     pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator,
    826 	 typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator>
    827     hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
    828     equal_range(const key_type& __key)
    829     {
    830       typedef pair<iterator, iterator> _Pii;
    831       const size_type __n = _M_bkt_num_key(__key);
    832 
    833       for (_Node* __first = _M_buckets[__n]; __first;
    834 	   __first = __first->_M_next)
    835 	if (_M_equals(_M_get_key(__first->_M_val), __key))
    836 	  {
    837 	    for (_Node* __cur = __first->_M_next; __cur;
    838 		 __cur = __cur->_M_next)
    839 	      if (!_M_equals(_M_get_key(__cur->_M_val), __key))
    840 		return _Pii(iterator(__first, this), iterator(__cur, this));
    841 	    for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
    842 	      if (_M_buckets[__m])
    843 		return _Pii(iterator(__first, this),
    844 			    iterator(_M_buckets[__m], this));
    845 	    return _Pii(iterator(__first, this), end());
    846 	  }
    847       return _Pii(end(), end());
    848     }
    849 
    850   template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
    851     pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator,
    852 	 typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator>
    853     hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
    854     equal_range(const key_type& __key) const
    855     {
    856       typedef pair<const_iterator, const_iterator> _Pii;
    857       const size_type __n = _M_bkt_num_key(__key);
    858 
    859       for (const _Node* __first = _M_buckets[__n]; __first;
    860 	   __first = __first->_M_next)
    861 	{
    862 	  if (_M_equals(_M_get_key(__first->_M_val), __key))
    863 	    {
    864 	      for (const _Node* __cur = __first->_M_next; __cur;
    865 		   __cur = __cur->_M_next)
    866 		if (!_M_equals(_M_get_key(__cur->_M_val), __key))
    867 		  return _Pii(const_iterator(__first, this),
    868 			      const_iterator(__cur, this));
    869 	      for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
    870 		if (_M_buckets[__m])
    871 		  return _Pii(const_iterator(__first, this),
    872 			      const_iterator(_M_buckets[__m], this));
    873 	      return _Pii(const_iterator(__first, this), end());
    874 	    }
    875 	}
    876       return _Pii(end(), end());
    877     }
    878 
    879   template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
    880     typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::size_type
    881     hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
    882     erase(const key_type& __key)
    883     {
    884       const size_type __n = _M_bkt_num_key(__key);
    885       _Node* __first = _M_buckets[__n];
    886       _Node* __saved_slot = 0;
    887       size_type __erased = 0;
    888 
    889       if (__first)
    890 	{
    891 	  _Node* __cur = __first;
    892 	  _Node* __next = __cur->_M_next;
    893 	  while (__next)
    894 	    {
    895 	      if (_M_equals(_M_get_key(__next->_M_val), __key))
    896 		{
    897 		  if (&_M_get_key(__next->_M_val) != &__key)
    898 		    {
    899 		      __cur->_M_next = __next->_M_next;
    900 		      _M_delete_node(__next);
    901 		      __next = __cur->_M_next;
    902 		      ++__erased;
    903 		      --_M_num_elements;
    904 		    }
    905 		  else
    906 		    {
    907 		      __saved_slot = __cur;
    908 		      __cur = __next;
    909 		      __next = __cur->_M_next;
    910 		    }
    911 		}
    912 	      else
    913 		{
    914 		  __cur = __next;
    915 		  __next = __cur->_M_next;
    916 		}
    917 	    }
    918 	  bool __delete_first = _M_equals(_M_get_key(__first->_M_val), __key);
    919 	  if (__saved_slot)
    920 	    {
    921 	      __next = __saved_slot->_M_next;
    922 	      __saved_slot->_M_next = __next->_M_next;
    923 	      _M_delete_node(__next);
    924 	      ++__erased;
    925 	      --_M_num_elements;
    926 	    }
    927 	  if (__delete_first)
    928 	    {
    929 	      _M_buckets[__n] = __first->_M_next;
    930 	      _M_delete_node(__first);
    931 	      ++__erased;
    932 	      --_M_num_elements;
    933 	    }
    934 	}
    935       return __erased;
    936     }
    937 
    938   template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
    939     void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
    940     erase(const iterator& __it)
    941     {
    942       _Node* __p = __it._M_cur;
    943       if (__p)
    944 	{
    945 	  const size_type __n = _M_bkt_num(__p->_M_val);
    946 	  _Node* __cur = _M_buckets[__n];
    947 
    948 	  if (__cur == __p)
    949 	    {
    950 	      _M_buckets[__n] = __cur->_M_next;
    951 	      _M_delete_node(__cur);
    952 	      --_M_num_elements;
    953 	    }
    954 	  else
    955 	    {
    956 	      _Node* __next = __cur->_M_next;
    957 	      while (__next)
    958 		{
    959 		  if (__next == __p)
    960 		    {
    961 		      __cur->_M_next = __next->_M_next;
    962 		      _M_delete_node(__next);
    963 		      --_M_num_elements;
    964 		      break;
    965 		    }
    966 		  else
    967 		    {
    968 		      __cur = __next;
    969 		      __next = __cur->_M_next;
    970 		    }
    971 		}
    972 	    }
    973 	}
    974     }
    975 
    976   template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
    977     void
    978     hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
    979     erase(iterator __first, iterator __last)
    980     {
    981       size_type __f_bucket = __first._M_cur ? _M_bkt_num(__first._M_cur->_M_val)
    982 	                                    : _M_buckets.size();
    983 
    984       size_type __l_bucket = __last._M_cur ? _M_bkt_num(__last._M_cur->_M_val)
    985 	                                   : _M_buckets.size();
    986 
    987       if (__first._M_cur == __last._M_cur)
    988 	return;
    989       else if (__f_bucket == __l_bucket)
    990 	_M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur);
    991       else
    992 	{
    993 	  _M_erase_bucket(__f_bucket, __first._M_cur, 0);
    994 	  for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n)
    995 	    _M_erase_bucket(__n, 0);
    996 	  if (__l_bucket != _M_buckets.size())
    997 	    _M_erase_bucket(__l_bucket, __last._M_cur);
    998 	}
    999     }
   1000 
   1001   template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
   1002     inline void
   1003     hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
   1004     erase(const_iterator __first, const_iterator __last)
   1005     {
   1006       erase(iterator(const_cast<_Node*>(__first._M_cur),
   1007 		     const_cast<hashtable*>(__first._M_ht)),
   1008 	    iterator(const_cast<_Node*>(__last._M_cur),
   1009 		     const_cast<hashtable*>(__last._M_ht)));
   1010     }
   1011 
   1012   template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
   1013     inline void
   1014     hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
   1015     erase(const const_iterator& __it)
   1016     { erase(iterator(const_cast<_Node*>(__it._M_cur),
   1017 		     const_cast<hashtable*>(__it._M_ht))); }
   1018 
   1019   template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
   1020     void
   1021     hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
   1022     resize(size_type __num_elements_hint)
   1023     {
   1024       const size_type __old_n = _M_buckets.size();
   1025       if (__num_elements_hint > __old_n)
   1026 	{
   1027 	  const size_type __n = _M_next_size(__num_elements_hint);
   1028 	  if (__n > __old_n)
   1029 	    {
   1030 	      _Vector_type __tmp(__n, (_Node*)(0), _M_buckets.get_allocator());
   1031 	      __try
   1032 		{
   1033 		  for (size_type __bucket = 0; __bucket < __old_n; ++__bucket)
   1034 		    {
   1035 		      _Node* __first = _M_buckets[__bucket];
   1036 		      while (__first)
   1037 			{
   1038 			  size_type __new_bucket = _M_bkt_num(__first->_M_val,
   1039 							      __n);
   1040 			  _M_buckets[__bucket] = __first->_M_next;
   1041 			  __first->_M_next = __tmp[__new_bucket];
   1042 			  __tmp[__new_bucket] = __first;
   1043 			  __first = _M_buckets[__bucket];
   1044 			}
   1045 		    }
   1046 		  _M_buckets.swap(__tmp);
   1047 		}
   1048 	      __catch(...)
   1049 		{
   1050 		  for (size_type __bucket = 0; __bucket < __tmp.size();
   1051 		       ++__bucket)
   1052 		    {
   1053 		      while (__tmp[__bucket])
   1054 			{
   1055 			  _Node* __next = __tmp[__bucket]->_M_next;
   1056 			  _M_delete_node(__tmp[__bucket]);
   1057 			  __tmp[__bucket] = __next;
   1058 			}
   1059 		    }
   1060 		  __throw_exception_again;
   1061 		}
   1062 	    }
   1063 	}
   1064     }
   1065 
   1066   template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
   1067     void
   1068     hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
   1069     _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last)
   1070     {
   1071       _Node* __cur = _M_buckets[__n];
   1072       if (__cur == __first)
   1073 	_M_erase_bucket(__n, __last);
   1074       else
   1075 	{
   1076 	  _Node* __next;
   1077 	  for (__next = __cur->_M_next;
   1078 	       __next != __first;
   1079 	       __cur = __next, __next = __cur->_M_next)
   1080 	    ;
   1081 	  while (__next != __last)
   1082 	    {
   1083 	      __cur->_M_next = __next->_M_next;
   1084 	      _M_delete_node(__next);
   1085 	      __next = __cur->_M_next;
   1086 	      --_M_num_elements;
   1087 	    }
   1088 	}
   1089     }
   1090 
   1091   template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
   1092     void
   1093     hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
   1094     _M_erase_bucket(const size_type __n, _Node* __last)
   1095     {
   1096       _Node* __cur = _M_buckets[__n];
   1097       while (__cur != __last)
   1098 	{
   1099 	  _Node* __next = __cur->_M_next;
   1100 	  _M_delete_node(__cur);
   1101 	  __cur = __next;
   1102 	  _M_buckets[__n] = __cur;
   1103 	  --_M_num_elements;
   1104 	}
   1105     }
   1106 
   1107   template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
   1108     void
   1109     hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
   1110     clear()
   1111     {
   1112       if (_M_num_elements == 0)
   1113 	return;
   1114 
   1115       for (size_type __i = 0; __i < _M_buckets.size(); ++__i)
   1116 	{
   1117 	  _Node* __cur = _M_buckets[__i];
   1118 	  while (__cur != 0)
   1119 	    {
   1120 	      _Node* __next = __cur->_M_next;
   1121 	      _M_delete_node(__cur);
   1122 	      __cur = __next;
   1123 	    }
   1124 	  _M_buckets[__i] = 0;
   1125 	}
   1126       _M_num_elements = 0;
   1127     }
   1128 
   1129   template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
   1130     void
   1131     hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
   1132     _M_copy_from(const hashtable& __ht)
   1133     {
   1134       _M_buckets.clear();
   1135       _M_buckets.reserve(__ht._M_buckets.size());
   1136       _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0);
   1137       __try
   1138 	{
   1139 	  for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) {
   1140 	    const _Node* __cur = __ht._M_buckets[__i];
   1141 	    if (__cur)
   1142 	      {
   1143 		_Node* __local_copy = _M_new_node(__cur->_M_val);
   1144 		_M_buckets[__i] = __local_copy;
   1145 
   1146 		for (_Node* __next = __cur->_M_next;
   1147 		     __next;
   1148 		     __cur = __next, __next = __cur->_M_next)
   1149 		  {
   1150 		    __local_copy->_M_next = _M_new_node(__next->_M_val);
   1151 		    __local_copy = __local_copy->_M_next;
   1152 		  }
   1153 	      }
   1154 	  }
   1155 	  _M_num_elements = __ht._M_num_elements;
   1156 	}
   1157       __catch(...)
   1158 	{
   1159 	  clear();
   1160 	  __throw_exception_again;
   1161 	}
   1162     }
   1163 
   1164 _GLIBCXX_END_NAMESPACE_VERSION
   1165 } // namespace
   1166 
   1167 #endif
   1168