1 // hashtable.h header -*- C++ -*-
3 // Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
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)
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.
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.
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/>.
25 /** @file bits/hashtable.h
26 * This is an internal header file, included by other library headers.
27 * You should not attempt to use it directly.
28 * @headername{unordered_map, unordered_set}
32 #define _HASHTABLE_H 1
34 #pragma GCC system_header
36 #include <bits/hashtable_policy.h>
40 // Class template _Hashtable, class definition.
42 // Meaning of class template _Hashtable's template parameters
44 // _Key and _Value: arbitrary CopyConstructible types.
46 // _Allocator: an allocator type ([lib.allocator.requirements]) whose
47 // value type is Value. As a conforming extension, we allow for
48 // value type != Value.
50 // _ExtractKey: function object that takes a object of type Value
51 // and returns a value of type _Key.
53 // _Equal: function object that takes two objects of type k and returns
54 // a bool-like value that is true if the two objects are considered equal.
56 // _H1: the hash function. A unary function object with argument type
57 // Key and result type size_t. Return values should be distributed
58 // over the entire range [0, numeric_limits<size_t>:::max()].
60 // _H2: the range-hashing function (in the terminology of Tavori and
61 // Dreizin). A binary function object whose argument types and result
62 // type are all size_t. Given arguments r and N, the return value is
63 // in the range [0, N).
65 // _Hash: the ranged hash function (Tavori and Dreizin). A binary function
66 // whose argument types are _Key and size_t and whose result type is
67 // size_t. Given arguments k and N, the return value is in the range
68 // [0, N). Default: hash(k, N) = h2(h1(k), N). If _Hash is anything other
69 // than the default, _H1 and _H2 are ignored.
71 // _RehashPolicy: Policy class with three members, all of which govern
72 // the bucket count. _M_next_bkt(n) returns a bucket count no smaller
73 // than n. _M_bkt_for_elements(n) returns a bucket count appropriate
74 // for an element count of n. _M_need_rehash(n_bkt, n_elt, n_ins)
75 // determines whether, if the current bucket count is n_bkt and the
76 // current element count is n_elt, we need to increase the bucket
77 // count. If so, returns make_pair(true, n), where n is the new
78 // bucket count. If not, returns make_pair(false, <anything>).
80 // ??? Right now it is hard-wired that the number of buckets never
81 // shrinks. Should we allow _RehashPolicy to change that?
83 // __cache_hash_code: bool. true if we store the value of the hash
84 // function along with the value. This is a time-space tradeoff.
85 // Storing it may improve lookup speed by reducing the number of times
86 // we need to call the Equal function.
88 // __constant_iterators: bool. true if iterator and const_iterator are
89 // both constant iterator types. This is true for unordered_set and
90 // unordered_multiset, false for unordered_map and unordered_multimap.
92 // __unique_keys: bool. true if the return value of _Hashtable::count(k)
93 // is always at most one, false if it may be an arbitrary number. This
94 // true for unordered_set and unordered_map, false for unordered_multiset
95 // and unordered_multimap.
97 template<typename _Key
, typename _Value
, typename _Allocator
,
98 typename _ExtractKey
, typename _Equal
,
99 typename _H1
, typename _H2
, typename _Hash
,
100 typename _RehashPolicy
,
101 bool __cache_hash_code
,
102 bool __constant_iterators
,
105 : public __detail::_Rehash_base
<_RehashPolicy
,
106 _Hashtable
<_Key
, _Value
, _Allocator
,
108 _Equal
, _H1
, _H2
, _Hash
,
111 __constant_iterators
,
113 public __detail::_Hash_code_base
<_Key
, _Value
, _ExtractKey
, _Equal
,
114 _H1
, _H2
, _Hash
, __cache_hash_code
>,
115 public __detail::_Map_base
<_Key
, _Value
, _ExtractKey
, __unique_keys
,
116 _Hashtable
<_Key
, _Value
, _Allocator
,
118 _Equal
, _H1
, _H2
, _Hash
,
121 __constant_iterators
,
123 public __detail::_Equality_base
<_ExtractKey
, __unique_keys
,
124 _Hashtable
<_Key
, _Value
, _Allocator
,
126 _Equal
, _H1
, _H2
, _Hash
,
129 __constant_iterators
,
133 typedef _Allocator allocator_type
;
134 typedef _Value value_type
;
135 typedef _Key key_type
;
136 typedef _Equal key_equal
;
137 // mapped_type, if present, comes from _Map_base.
138 // hasher, if present, comes from _Hash_code_base.
139 typedef typename
_Allocator::pointer pointer
;
140 typedef typename
_Allocator::const_pointer const_pointer
;
141 typedef typename
_Allocator::reference reference
;
142 typedef typename
_Allocator::const_reference const_reference
;
144 typedef std::size_t size_type
;
145 typedef std::ptrdiff_t difference_type
;
146 typedef __detail::_Node_iterator
<value_type
, __constant_iterators
,
149 typedef __detail::_Node_const_iterator
<value_type
,
150 __constant_iterators
,
152 const_local_iterator
;
154 typedef __detail::_Hashtable_iterator
<value_type
, __constant_iterators
,
157 typedef __detail::_Hashtable_const_iterator
<value_type
,
158 __constant_iterators
,
162 template<typename _Key2
, typename _Value2
, typename _Ex2
, bool __unique2
,
163 typename _Hashtable2
>
164 friend struct __detail::_Map_base
;
167 typedef __detail::_Hash_node
<_Value
, __cache_hash_code
> _Node
;
168 typedef typename
_Allocator::template rebind
<_Node
>::other
169 _Node_allocator_type
;
170 typedef typename
_Allocator::template rebind
<_Node
*>::other
171 _Bucket_allocator_type
;
173 typedef typename
_Allocator::template rebind
<_Value
>::other
174 _Value_allocator_type
;
176 _Node_allocator_type _M_node_allocator
;
178 size_type _M_bucket_count
;
179 size_type _M_begin_bucket_index
; // First non-empty bucket.
180 size_type _M_element_count
;
181 _RehashPolicy _M_rehash_policy
;
183 template<typename
... _Args
>
185 _M_allocate_node(_Args
&&... __args
);
188 _M_deallocate_node(_Node
* __n
);
191 _M_deallocate_nodes(_Node
**, size_type
);
194 _M_allocate_buckets(size_type __n
);
197 _M_deallocate_buckets(_Node
**, size_type __n
);
200 // Constructor, destructor, assignment, swap
201 _Hashtable(size_type __bucket_hint
,
202 const _H1
&, const _H2
&, const _Hash
&,
203 const _Equal
&, const _ExtractKey
&,
204 const allocator_type
&);
206 template<typename _InputIterator
>
207 _Hashtable(_InputIterator __first
, _InputIterator __last
,
208 size_type __bucket_hint
,
209 const _H1
&, const _H2
&, const _Hash
&,
210 const _Equal
&, const _ExtractKey
&,
211 const allocator_type
&);
213 _Hashtable(const _Hashtable
&);
215 _Hashtable(_Hashtable
&&);
218 operator=(const _Hashtable
& __ht
)
220 _Hashtable
__tmp(__ht
);
226 operator=(_Hashtable
&& __ht
)
237 void swap(_Hashtable
&);
239 // Basic container operations
242 { return iterator(_M_buckets
+ _M_begin_bucket_index
); }
246 { return const_iterator(_M_buckets
+ _M_begin_bucket_index
); }
250 { return iterator(_M_buckets
+ _M_bucket_count
); }
254 { return const_iterator(_M_buckets
+ _M_bucket_count
); }
258 { return const_iterator(_M_buckets
+ _M_begin_bucket_index
); }
262 { return const_iterator(_M_buckets
+ _M_bucket_count
); }
266 { return _M_element_count
; }
270 { return size() == 0; }
273 get_allocator() const
274 { return allocator_type(_M_node_allocator
); }
278 { return _M_node_allocator
.max_size(); }
283 { return this->_M_eq
; }
285 // hash_function, if present, comes from _Hash_code_base.
290 { return _M_bucket_count
; }
293 max_bucket_count() const
294 { return max_size(); }
297 bucket_size(size_type __n
) const
298 { return std::distance(begin(__n
), end(__n
)); }
301 bucket(const key_type
& __k
) const
303 return this->_M_bucket_index(__k
, this->_M_hash_code(__k
),
309 { return local_iterator(_M_buckets
[__n
]); }
313 { return local_iterator(0); }
316 begin(size_type __n
) const
317 { return const_local_iterator(_M_buckets
[__n
]); }
321 { return const_local_iterator(0); }
325 cbegin(size_type __n
) const
326 { return const_local_iterator(_M_buckets
[__n
]); }
329 cend(size_type
) const
330 { return const_local_iterator(0); }
335 return static_cast<float>(size()) / static_cast<float>(bucket_count());
338 // max_load_factor, if present, comes from _Rehash_base.
340 // Generalization of max_load_factor. Extension, not found in TR1. Only
341 // useful if _RehashPolicy is something other than the default.
343 __rehash_policy() const
344 { return _M_rehash_policy
; }
347 __rehash_policy(const _RehashPolicy
&);
351 find(const key_type
& __k
);
354 find(const key_type
& __k
) const;
357 count(const key_type
& __k
) const;
359 std::pair
<iterator
, iterator
>
360 equal_range(const key_type
& __k
);
362 std::pair
<const_iterator
, const_iterator
>
363 equal_range(const key_type
& __k
) const;
366 // Find and insert helper functions and types
368 _M_find_node(_Node
*, const key_type
&,
369 typename
_Hashtable::_Hash_code_type
) const;
371 template<typename _Arg
>
373 _M_insert_bucket(_Arg
&&, size_type
,
374 typename
_Hashtable::_Hash_code_type
);
376 template<typename _Arg
>
377 std::pair
<iterator
, bool>
378 _M_insert(_Arg
&&, std::true_type
);
380 template<typename _Arg
>
382 _M_insert(_Arg
&&, std::false_type
);
384 typedef typename
std::conditional
<__unique_keys
,
385 std::pair
<iterator
, bool>,
389 typedef typename
std::conditional
<__unique_keys
,
390 std::_Select1st
<_Insert_Return_Type
>,
391 std::_Identity
<_Insert_Return_Type
>
398 insert(const value_type
& __v
)
399 { return _M_insert(__v
, std::integral_constant
<bool, __unique_keys
>()); }
402 insert(const_iterator
, const value_type
& __v
)
403 { return _Insert_Conv_Type()(insert(__v
)); }
406 insert(value_type
&& __v
)
407 { return _M_insert(std::move(__v
),
408 std::integral_constant
<bool, __unique_keys
>()); }
411 insert(const_iterator
, value_type
&& __v
)
412 { return _Insert_Conv_Type()(insert(std::move(__v
))); }
414 template<typename _Pair
, typename
= typename
415 std::enable_if
<!__constant_iterators
416 && std::is_convertible
<_Pair
,
417 value_type
>::value
>::type
>
420 { return _M_insert(std::forward
<_Pair
>(__v
),
421 std::integral_constant
<bool, __unique_keys
>()); }
423 template<typename _Pair
, typename
= typename
424 std::enable_if
<!__constant_iterators
425 && std::is_convertible
<_Pair
,
426 value_type
>::value
>::type
>
428 insert(const_iterator
, _Pair
&& __v
)
429 { return _Insert_Conv_Type()(insert(std::forward
<_Pair
>(__v
))); }
431 template<typename _InputIterator
>
433 insert(_InputIterator __first
, _InputIterator __last
);
436 insert(initializer_list
<value_type
> __l
)
437 { this->insert(__l
.begin(), __l
.end()); }
440 erase(const_iterator
);
443 erase(const key_type
&);
446 erase(const_iterator
, const_iterator
);
451 // Set number of buckets to be appropriate for container of n element.
452 void rehash(size_type __n
);
455 // reserve, if present, comes from _Rehash_base.
458 // Unconditionally change size of bucket array to n.
459 void _M_rehash(size_type __n
);
463 // Definitions of class template _Hashtable's out-of-line member functions.
464 template<typename _Key
, typename _Value
,
465 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
466 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
467 bool __chc
, bool __cit
, bool __uk
>
468 template<typename
... _Args
>
469 typename _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
470 _H1
, _H2
, _Hash
, _RehashPolicy
,
471 __chc
, __cit
, __uk
>::_Node
*
472 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
473 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
474 _M_allocate_node(_Args
&&... __args
)
476 _Node
* __n
= _M_node_allocator
.allocate(1);
479 _M_node_allocator
.construct(__n
, std::forward
<_Args
>(__args
)...);
485 _M_node_allocator
.deallocate(__n
, 1);
486 __throw_exception_again
;
490 template<typename _Key
, typename _Value
,
491 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
492 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
493 bool __chc
, bool __cit
, bool __uk
>
495 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
496 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
497 _M_deallocate_node(_Node
* __n
)
499 _M_node_allocator
.destroy(__n
);
500 _M_node_allocator
.deallocate(__n
, 1);
503 template<typename _Key
, typename _Value
,
504 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
505 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
506 bool __chc
, bool __cit
, bool __uk
>
508 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
509 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
510 _M_deallocate_nodes(_Node
** __array
, size_type __n
)
512 for (size_type __i
= 0; __i
< __n
; ++__i
)
514 _Node
* __p
= __array
[__i
];
519 _M_deallocate_node(__tmp
);
525 template<typename _Key
, typename _Value
,
526 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
527 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
528 bool __chc
, bool __cit
, bool __uk
>
529 typename _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
530 _H1
, _H2
, _Hash
, _RehashPolicy
,
531 __chc
, __cit
, __uk
>::_Node
**
532 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
533 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
534 _M_allocate_buckets(size_type __n
)
536 _Bucket_allocator_type
__alloc(_M_node_allocator
);
538 // We allocate one extra bucket to hold a sentinel, an arbitrary
539 // non-null pointer. Iterator increment relies on this.
540 _Node
** __p
= __alloc
.allocate(__n
+ 1);
541 std::fill(__p
, __p
+ __n
, (_Node
*) 0);
542 __p
[__n
] = reinterpret_cast<_Node
*>(0x1000);
546 template<typename _Key
, typename _Value
,
547 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
548 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
549 bool __chc
, bool __cit
, bool __uk
>
551 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
552 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
553 _M_deallocate_buckets(_Node
** __p
, size_type __n
)
555 _Bucket_allocator_type
__alloc(_M_node_allocator
);
556 __alloc
.deallocate(__p
, __n
+ 1);
559 template<typename _Key
, typename _Value
,
560 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
561 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
562 bool __chc
, bool __cit
, bool __uk
>
563 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
564 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
565 _Hashtable(size_type __bucket_hint
,
566 const _H1
& __h1
, const _H2
& __h2
, const _Hash
& __h
,
567 const _Equal
& __eq
, const _ExtractKey
& __exk
,
568 const allocator_type
& __a
)
569 : __detail::_Rehash_base
<_RehashPolicy
, _Hashtable
>(),
570 __detail::_Hash_code_base
<_Key
, _Value
, _ExtractKey
, _Equal
,
571 _H1
, _H2
, _Hash
, __chc
>(__exk
, __eq
,
573 __detail::_Map_base
<_Key
, _Value
, _ExtractKey
, __uk
, _Hashtable
>(),
574 _M_node_allocator(__a
),
579 _M_bucket_count
= _M_rehash_policy
._M_next_bkt(__bucket_hint
);
580 _M_buckets
= _M_allocate_buckets(_M_bucket_count
);
581 _M_begin_bucket_index
= _M_bucket_count
;
584 template<typename _Key
, typename _Value
,
585 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
586 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
587 bool __chc
, bool __cit
, bool __uk
>
588 template<typename _InputIterator
>
589 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
590 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
591 _Hashtable(_InputIterator __f
, _InputIterator __l
,
592 size_type __bucket_hint
,
593 const _H1
& __h1
, const _H2
& __h2
, const _Hash
& __h
,
594 const _Equal
& __eq
, const _ExtractKey
& __exk
,
595 const allocator_type
& __a
)
596 : __detail::_Rehash_base
<_RehashPolicy
, _Hashtable
>(),
597 __detail::_Hash_code_base
<_Key
, _Value
, _ExtractKey
, _Equal
,
598 _H1
, _H2
, _Hash
, __chc
>(__exk
, __eq
,
600 __detail::_Map_base
<_Key
, _Value
, _ExtractKey
, __uk
, _Hashtable
>(),
601 _M_node_allocator(__a
),
606 _M_bucket_count
= std::max(_M_rehash_policy
._M_next_bkt(__bucket_hint
),
608 _M_bkt_for_elements(__detail::
611 _M_buckets
= _M_allocate_buckets(_M_bucket_count
);
612 _M_begin_bucket_index
= _M_bucket_count
;
615 for (; __f
!= __l
; ++__f
)
621 _M_deallocate_buckets(_M_buckets
, _M_bucket_count
);
622 __throw_exception_again
;
626 template<typename _Key
, typename _Value
,
627 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
628 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
629 bool __chc
, bool __cit
, bool __uk
>
630 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
631 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
632 _Hashtable(const _Hashtable
& __ht
)
633 : __detail::_Rehash_base
<_RehashPolicy
, _Hashtable
>(__ht
),
634 __detail::_Hash_code_base
<_Key
, _Value
, _ExtractKey
, _Equal
,
635 _H1
, _H2
, _Hash
, __chc
>(__ht
),
636 __detail::_Map_base
<_Key
, _Value
, _ExtractKey
, __uk
, _Hashtable
>(__ht
),
637 _M_node_allocator(__ht
._M_node_allocator
),
638 _M_bucket_count(__ht
._M_bucket_count
),
639 _M_begin_bucket_index(__ht
._M_begin_bucket_index
),
640 _M_element_count(__ht
._M_element_count
),
641 _M_rehash_policy(__ht
._M_rehash_policy
)
643 _M_buckets
= _M_allocate_buckets(_M_bucket_count
);
646 for (size_type __i
= 0; __i
< __ht
._M_bucket_count
; ++__i
)
648 _Node
* __n
= __ht
._M_buckets
[__i
];
649 _Node
** __tail
= _M_buckets
+ __i
;
652 *__tail
= _M_allocate_node(__n
->_M_v
);
653 this->_M_copy_code(*__tail
, __n
);
654 __tail
= &((*__tail
)->_M_next
);
662 _M_deallocate_buckets(_M_buckets
, _M_bucket_count
);
663 __throw_exception_again
;
667 template<typename _Key
, typename _Value
,
668 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
669 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
670 bool __chc
, bool __cit
, bool __uk
>
671 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
672 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
673 _Hashtable(_Hashtable
&& __ht
)
674 : __detail::_Rehash_base
<_RehashPolicy
, _Hashtable
>(__ht
),
675 __detail::_Hash_code_base
<_Key
, _Value
, _ExtractKey
, _Equal
,
676 _H1
, _H2
, _Hash
, __chc
>(__ht
),
677 __detail::_Map_base
<_Key
, _Value
, _ExtractKey
, __uk
, _Hashtable
>(__ht
),
678 _M_node_allocator(__ht
._M_node_allocator
),
679 _M_buckets(__ht
._M_buckets
),
680 _M_bucket_count(__ht
._M_bucket_count
),
681 _M_begin_bucket_index(__ht
._M_begin_bucket_index
),
682 _M_element_count(__ht
._M_element_count
),
683 _M_rehash_policy(__ht
._M_rehash_policy
)
685 size_type __n_bkt
= __ht
._M_rehash_policy
._M_next_bkt(0);
686 __ht
._M_buckets
= __ht
._M_allocate_buckets(__n_bkt
);
687 __ht
._M_bucket_count
= __n_bkt
;
688 __ht
._M_begin_bucket_index
= __ht
._M_bucket_count
;
689 __ht
._M_element_count
= 0;
690 __ht
._M_rehash_policy
= _RehashPolicy();
693 template<typename _Key
, typename _Value
,
694 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
695 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
696 bool __chc
, bool __cit
, bool __uk
>
697 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
698 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
702 _M_deallocate_buckets(_M_buckets
, _M_bucket_count
);
705 template<typename _Key
, typename _Value
,
706 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
707 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
708 bool __chc
, bool __cit
, bool __uk
>
710 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
711 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
712 swap(_Hashtable
& __x
)
714 // The only base class with member variables is hash_code_base. We
715 // define _Hash_code_base::_M_swap because different specializations
716 // have different members.
717 __detail::_Hash_code_base
<_Key
, _Value
, _ExtractKey
, _Equal
,
718 _H1
, _H2
, _Hash
, __chc
>::_M_swap(__x
);
720 // _GLIBCXX_RESOLVE_LIB_DEFECTS
721 // 431. Swapping containers with unequal allocators.
722 std::__alloc_swap
<_Node_allocator_type
>::_S_do_it(_M_node_allocator
,
723 __x
._M_node_allocator
);
725 std::swap(_M_rehash_policy
, __x
._M_rehash_policy
);
726 std::swap(_M_buckets
, __x
._M_buckets
);
727 std::swap(_M_bucket_count
, __x
._M_bucket_count
);
728 std::swap(_M_begin_bucket_index
, __x
._M_begin_bucket_index
);
729 std::swap(_M_element_count
, __x
._M_element_count
);
732 template<typename _Key
, typename _Value
,
733 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
734 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
735 bool __chc
, bool __cit
, bool __uk
>
737 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
738 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
739 __rehash_policy(const _RehashPolicy
& __pol
)
741 _M_rehash_policy
= __pol
;
742 size_type __n_bkt
= __pol
._M_bkt_for_elements(_M_element_count
);
743 if (__n_bkt
> _M_bucket_count
)
747 template<typename _Key
, typename _Value
,
748 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
749 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
750 bool __chc
, bool __cit
, bool __uk
>
751 typename _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
752 _H1
, _H2
, _Hash
, _RehashPolicy
,
753 __chc
, __cit
, __uk
>::iterator
754 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
755 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
756 find(const key_type
& __k
)
758 typename
_Hashtable::_Hash_code_type __code
= this->_M_hash_code(__k
);
759 std::size_t __n
= this->_M_bucket_index(__k
, __code
, _M_bucket_count
);
760 _Node
* __p
= _M_find_node(_M_buckets
[__n
], __k
, __code
);
761 return __p
? iterator(__p
, _M_buckets
+ __n
) : this->end();
764 template<typename _Key
, typename _Value
,
765 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
766 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
767 bool __chc
, bool __cit
, bool __uk
>
768 typename _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
769 _H1
, _H2
, _Hash
, _RehashPolicy
,
770 __chc
, __cit
, __uk
>::const_iterator
771 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
772 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
773 find(const key_type
& __k
) const
775 typename
_Hashtable::_Hash_code_type __code
= this->_M_hash_code(__k
);
776 std::size_t __n
= this->_M_bucket_index(__k
, __code
, _M_bucket_count
);
777 _Node
* __p
= _M_find_node(_M_buckets
[__n
], __k
, __code
);
778 return __p
? const_iterator(__p
, _M_buckets
+ __n
) : this->end();
781 template<typename _Key
, typename _Value
,
782 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
783 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
784 bool __chc
, bool __cit
, bool __uk
>
785 typename _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
786 _H1
, _H2
, _Hash
, _RehashPolicy
,
787 __chc
, __cit
, __uk
>::size_type
788 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
789 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
790 count(const key_type
& __k
) const
792 typename
_Hashtable::_Hash_code_type __code
= this->_M_hash_code(__k
);
793 std::size_t __n
= this->_M_bucket_index(__k
, __code
, _M_bucket_count
);
794 std::size_t __result
= 0;
795 for (_Node
* __p
= _M_buckets
[__n
]; __p
; __p
= __p
->_M_next
)
796 if (this->_M_compare(__k
, __code
, __p
))
801 template<typename _Key
, typename _Value
,
802 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
803 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
804 bool __chc
, bool __cit
, bool __uk
>
805 std::pair
<typename _Hashtable
<_Key
, _Value
, _Allocator
,
806 _ExtractKey
, _Equal
, _H1
,
807 _H2
, _Hash
, _RehashPolicy
,
808 __chc
, __cit
, __uk
>::iterator
,
809 typename _Hashtable
<_Key
, _Value
, _Allocator
,
810 _ExtractKey
, _Equal
, _H1
,
811 _H2
, _Hash
, _RehashPolicy
,
812 __chc
, __cit
, __uk
>::iterator
>
813 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
814 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
815 equal_range(const key_type
& __k
)
817 typename
_Hashtable::_Hash_code_type __code
= this->_M_hash_code(__k
);
818 std::size_t __n
= this->_M_bucket_index(__k
, __code
, _M_bucket_count
);
819 _Node
** __head
= _M_buckets
+ __n
;
820 _Node
* __p
= _M_find_node(*__head
, __k
, __code
);
824 _Node
* __p1
= __p
->_M_next
;
825 for (; __p1
; __p1
= __p1
->_M_next
)
826 if (!this->_M_compare(__k
, __code
, __p1
))
829 iterator
__first(__p
, __head
);
830 iterator
__last(__p1
, __head
);
832 __last
._M_incr_bucket();
833 return std::make_pair(__first
, __last
);
836 return std::make_pair(this->end(), this->end());
839 template<typename _Key
, typename _Value
,
840 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
841 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
842 bool __chc
, bool __cit
, bool __uk
>
843 std::pair
<typename _Hashtable
<_Key
, _Value
, _Allocator
,
844 _ExtractKey
, _Equal
, _H1
,
845 _H2
, _Hash
, _RehashPolicy
,
846 __chc
, __cit
, __uk
>::const_iterator
,
847 typename _Hashtable
<_Key
, _Value
, _Allocator
,
848 _ExtractKey
, _Equal
, _H1
,
849 _H2
, _Hash
, _RehashPolicy
,
850 __chc
, __cit
, __uk
>::const_iterator
>
851 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
852 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
853 equal_range(const key_type
& __k
) const
855 typename
_Hashtable::_Hash_code_type __code
= this->_M_hash_code(__k
);
856 std::size_t __n
= this->_M_bucket_index(__k
, __code
, _M_bucket_count
);
857 _Node
** __head
= _M_buckets
+ __n
;
858 _Node
* __p
= _M_find_node(*__head
, __k
, __code
);
862 _Node
* __p1
= __p
->_M_next
;
863 for (; __p1
; __p1
= __p1
->_M_next
)
864 if (!this->_M_compare(__k
, __code
, __p1
))
867 const_iterator
__first(__p
, __head
);
868 const_iterator
__last(__p1
, __head
);
870 __last
._M_incr_bucket();
871 return std::make_pair(__first
, __last
);
874 return std::make_pair(this->end(), this->end());
877 // Find the node whose key compares equal to k, beginning the search
878 // at p (usually the head of a bucket). Return nil if no node is found.
879 template<typename _Key
, typename _Value
,
880 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
881 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
882 bool __chc
, bool __cit
, bool __uk
>
883 typename _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
,
884 _Equal
, _H1
, _H2
, _Hash
, _RehashPolicy
,
885 __chc
, __cit
, __uk
>::_Node
*
886 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
887 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
888 _M_find_node(_Node
* __p
, const key_type
& __k
,
889 typename
_Hashtable::_Hash_code_type __code
) const
891 for (; __p
; __p
= __p
->_M_next
)
892 if (this->_M_compare(__k
, __code
, __p
))
897 // Insert v in bucket n (assumes no element with its key already present).
898 template<typename _Key
, typename _Value
,
899 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
900 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
901 bool __chc
, bool __cit
, bool __uk
>
902 template<typename _Arg
>
903 typename _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
904 _H1
, _H2
, _Hash
, _RehashPolicy
,
905 __chc
, __cit
, __uk
>::iterator
906 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
907 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
908 _M_insert_bucket(_Arg
&& __v
, size_type __n
,
909 typename
_Hashtable::_Hash_code_type __code
)
911 std::pair
<bool, std::size_t> __do_rehash
912 = _M_rehash_policy
._M_need_rehash(_M_bucket_count
,
913 _M_element_count
, 1);
915 if (__do_rehash
.first
)
917 const key_type
& __k
= this->_M_extract(__v
);
918 __n
= this->_M_bucket_index(__k
, __code
, __do_rehash
.second
);
921 // Allocate the new node before doing the rehash so that we don't
922 // do a rehash if the allocation throws.
923 _Node
* __new_node
= _M_allocate_node(std::forward
<_Arg
>(__v
));
927 if (__do_rehash
.first
)
928 _M_rehash(__do_rehash
.second
);
930 __new_node
->_M_next
= _M_buckets
[__n
];
931 this->_M_store_code(__new_node
, __code
);
932 _M_buckets
[__n
] = __new_node
;
934 if (__n
< _M_begin_bucket_index
)
935 _M_begin_bucket_index
= __n
;
936 return iterator(__new_node
, _M_buckets
+ __n
);
940 _M_deallocate_node(__new_node
);
941 __throw_exception_again
;
945 // Insert v if no element with its key is already present.
946 template<typename _Key
, typename _Value
,
947 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
948 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
949 bool __chc
, bool __cit
, bool __uk
>
950 template<typename _Arg
>
951 std::pair
<typename _Hashtable
<_Key
, _Value
, _Allocator
,
952 _ExtractKey
, _Equal
, _H1
,
953 _H2
, _Hash
, _RehashPolicy
,
954 __chc
, __cit
, __uk
>::iterator
, bool>
955 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
956 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
957 _M_insert(_Arg
&& __v
, std::true_type
)
959 const key_type
& __k
= this->_M_extract(__v
);
960 typename
_Hashtable::_Hash_code_type __code
= this->_M_hash_code(__k
);
961 size_type __n
= this->_M_bucket_index(__k
, __code
, _M_bucket_count
);
963 if (_Node
* __p
= _M_find_node(_M_buckets
[__n
], __k
, __code
))
964 return std::make_pair(iterator(__p
, _M_buckets
+ __n
), false);
965 return std::make_pair(_M_insert_bucket(std::forward
<_Arg
>(__v
),
969 // Insert v unconditionally.
970 template<typename _Key
, typename _Value
,
971 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
972 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
973 bool __chc
, bool __cit
, bool __uk
>
974 template<typename _Arg
>
975 typename _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
976 _H1
, _H2
, _Hash
, _RehashPolicy
,
977 __chc
, __cit
, __uk
>::iterator
978 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
979 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
980 _M_insert(_Arg
&& __v
, std::false_type
)
982 std::pair
<bool, std::size_t> __do_rehash
983 = _M_rehash_policy
._M_need_rehash(_M_bucket_count
,
984 _M_element_count
, 1);
985 if (__do_rehash
.first
)
986 _M_rehash(__do_rehash
.second
);
988 const key_type
& __k
= this->_M_extract(__v
);
989 typename
_Hashtable::_Hash_code_type __code
= this->_M_hash_code(__k
);
990 size_type __n
= this->_M_bucket_index(__k
, __code
, _M_bucket_count
);
992 // First find the node, avoid leaking new_node if compare throws.
993 _Node
* __prev
= _M_find_node(_M_buckets
[__n
], __k
, __code
);
994 _Node
* __new_node
= _M_allocate_node(std::forward
<_Arg
>(__v
));
998 __new_node
->_M_next
= __prev
->_M_next
;
999 __prev
->_M_next
= __new_node
;
1003 __new_node
->_M_next
= _M_buckets
[__n
];
1004 _M_buckets
[__n
] = __new_node
;
1005 if (__n
< _M_begin_bucket_index
)
1006 _M_begin_bucket_index
= __n
;
1008 this->_M_store_code(__new_node
, __code
);
1011 return iterator(__new_node
, _M_buckets
+ __n
);
1014 template<typename _Key
, typename _Value
,
1015 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
1016 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
1017 bool __chc
, bool __cit
, bool __uk
>
1018 template<typename _InputIterator
>
1020 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
1021 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
1022 insert(_InputIterator __first
, _InputIterator __last
)
1024 size_type __n_elt
= __detail::__distance_fw(__first
, __last
);
1025 std::pair
<bool, std::size_t> __do_rehash
1026 = _M_rehash_policy
._M_need_rehash(_M_bucket_count
,
1027 _M_element_count
, __n_elt
);
1028 if (__do_rehash
.first
)
1029 _M_rehash(__do_rehash
.second
);
1031 for (; __first
!= __last
; ++__first
)
1032 this->insert(*__first
);
1035 template<typename _Key
, typename _Value
,
1036 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
1037 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
1038 bool __chc
, bool __cit
, bool __uk
>
1039 typename _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
1040 _H1
, _H2
, _Hash
, _RehashPolicy
,
1041 __chc
, __cit
, __uk
>::iterator
1042 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
1043 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
1044 erase(const_iterator __it
)
1046 iterator
__result(__it
._M_cur_node
, __it
._M_cur_bucket
);
1049 _Node
* __cur
= *__it
._M_cur_bucket
;
1050 if (__cur
== __it
._M_cur_node
)
1052 *__it
._M_cur_bucket
= __cur
->_M_next
;
1054 // If _M_begin_bucket_index no longer indexes the first non-empty
1055 // bucket - its single node is being erased - update it.
1056 if (!_M_buckets
[_M_begin_bucket_index
])
1057 _M_begin_bucket_index
= __result
._M_cur_bucket
- _M_buckets
;
1061 _Node
* __next
= __cur
->_M_next
;
1062 while (__next
!= __it
._M_cur_node
)
1065 __next
= __cur
->_M_next
;
1067 __cur
->_M_next
= __next
->_M_next
;
1070 _M_deallocate_node(__it
._M_cur_node
);
1076 template<typename _Key
, typename _Value
,
1077 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
1078 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
1079 bool __chc
, bool __cit
, bool __uk
>
1080 typename _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
1081 _H1
, _H2
, _Hash
, _RehashPolicy
,
1082 __chc
, __cit
, __uk
>::size_type
1083 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
1084 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
1085 erase(const key_type
& __k
)
1087 typename
_Hashtable::_Hash_code_type __code
= this->_M_hash_code(__k
);
1088 std::size_t __n
= this->_M_bucket_index(__k
, __code
, _M_bucket_count
);
1089 size_type __result
= 0;
1091 _Node
** __slot
= _M_buckets
+ __n
;
1092 while (*__slot
&& !this->_M_compare(__k
, __code
, *__slot
))
1093 __slot
= &((*__slot
)->_M_next
);
1095 _Node
** __saved_slot
= 0;
1096 while (*__slot
&& this->_M_compare(__k
, __code
, *__slot
))
1098 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1099 // 526. Is it undefined if a function in the standard changes
1101 if (std::__addressof(this->_M_extract((*__slot
)->_M_v
))
1102 != std::__addressof(__k
))
1104 _Node
* __p
= *__slot
;
1105 *__slot
= __p
->_M_next
;
1106 _M_deallocate_node(__p
);
1112 __saved_slot
= __slot
;
1113 __slot
= &((*__slot
)->_M_next
);
1119 _Node
* __p
= *__saved_slot
;
1120 *__saved_slot
= __p
->_M_next
;
1121 _M_deallocate_node(__p
);
1126 // If the entire bucket indexed by _M_begin_bucket_index has been
1127 // erased look forward for the first non-empty bucket.
1128 if (!_M_buckets
[_M_begin_bucket_index
])
1130 if (!_M_element_count
)
1131 _M_begin_bucket_index
= _M_bucket_count
;
1134 ++_M_begin_bucket_index
;
1135 while (!_M_buckets
[_M_begin_bucket_index
])
1136 ++_M_begin_bucket_index
;
1143 // ??? This could be optimized by taking advantage of the bucket
1144 // structure, but it's not clear that it's worth doing. It probably
1145 // wouldn't even be an optimization unless the load factor is large.
1146 template<typename _Key
, typename _Value
,
1147 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
1148 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
1149 bool __chc
, bool __cit
, bool __uk
>
1150 typename _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
1151 _H1
, _H2
, _Hash
, _RehashPolicy
,
1152 __chc
, __cit
, __uk
>::iterator
1153 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
1154 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
1155 erase(const_iterator __first
, const_iterator __last
)
1157 while (__first
!= __last
)
1158 __first
= this->erase(__first
);
1159 return iterator(__last
._M_cur_node
, __last
._M_cur_bucket
);
1162 template<typename _Key
, typename _Value
,
1163 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
1164 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
1165 bool __chc
, bool __cit
, bool __uk
>
1167 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
1168 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
1171 _M_deallocate_nodes(_M_buckets
, _M_bucket_count
);
1172 _M_element_count
= 0;
1173 _M_begin_bucket_index
= _M_bucket_count
;
1176 template<typename _Key
, typename _Value
,
1177 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
1178 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
1179 bool __chc
, bool __cit
, bool __uk
>
1181 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
1182 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
1183 rehash(size_type __n
)
1185 _M_rehash(std::max(_M_rehash_policy
._M_next_bkt(__n
),
1186 _M_rehash_policy
._M_bkt_for_elements(_M_element_count
1190 template<typename _Key
, typename _Value
,
1191 typename _Allocator
, typename _ExtractKey
, typename _Equal
,
1192 typename _H1
, typename _H2
, typename _Hash
, typename _RehashPolicy
,
1193 bool __chc
, bool __cit
, bool __uk
>
1195 _Hashtable
<_Key
, _Value
, _Allocator
, _ExtractKey
, _Equal
,
1196 _H1
, _H2
, _Hash
, _RehashPolicy
, __chc
, __cit
, __uk
>::
1197 _M_rehash(size_type __n
)
1199 _Node
** __new_array
= _M_allocate_buckets(__n
);
1202 _M_begin_bucket_index
= __n
;
1203 for (size_type __i
= 0; __i
< _M_bucket_count
; ++__i
)
1204 while (_Node
* __p
= _M_buckets
[__i
])
1206 std::size_t __new_index
= this->_M_bucket_index(__p
, __n
);
1207 _M_buckets
[__i
] = __p
->_M_next
;
1208 __p
->_M_next
= __new_array
[__new_index
];
1209 __new_array
[__new_index
] = __p
;
1210 if (__new_index
< _M_begin_bucket_index
)
1211 _M_begin_bucket_index
= __new_index
;
1213 _M_deallocate_buckets(_M_buckets
, _M_bucket_count
);
1214 _M_bucket_count
= __n
;
1215 _M_buckets
= __new_array
;
1219 // A failure here means that a hash function threw an exception.
1220 // We can't restore the previous state without calling the hash
1221 // function again, so the only sensible recovery is to delete
1223 _M_deallocate_nodes(__new_array
, __n
);
1224 _M_deallocate_buckets(__new_array
, __n
);
1225 _M_deallocate_nodes(_M_buckets
, _M_bucket_count
);
1226 _M_element_count
= 0;
1227 _M_begin_bucket_index
= _M_bucket_count
;
1228 __throw_exception_again
;
1233 #endif // _HASHTABLE_H