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