]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/include/tr1_impl/hashtable_policy.h
Licensing changes to GPLv3 resp. GPLv3 with GCC Runtime Exception.
[thirdparty/gcc.git] / libstdc++-v3 / include / tr1_impl / hashtable_policy.h
1 // Internal policy header for TR1 unordered_set and unordered_map -*- C++ -*-
2
3 // Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24
25 /** @file tr1_impl/hashtable_policy.h
26 * This is an internal header file, included by other library headers.
27 * You should not attempt to use it directly.
28 */
29
30 namespace std
31 {
32 _GLIBCXX_BEGIN_NAMESPACE_TR1
33
34 namespace __detail
35 {
36 // Helper function: return distance(first, last) for forward
37 // iterators, or 0 for input iterators.
38 template<class _Iterator>
39 inline typename std::iterator_traits<_Iterator>::difference_type
40 __distance_fw(_Iterator __first, _Iterator __last,
41 std::input_iterator_tag)
42 { return 0; }
43
44 template<class _Iterator>
45 inline typename std::iterator_traits<_Iterator>::difference_type
46 __distance_fw(_Iterator __first, _Iterator __last,
47 std::forward_iterator_tag)
48 { return std::distance(__first, __last); }
49
50 template<class _Iterator>
51 inline typename std::iterator_traits<_Iterator>::difference_type
52 __distance_fw(_Iterator __first, _Iterator __last)
53 {
54 typedef typename std::iterator_traits<_Iterator>::iterator_category _Tag;
55 return __distance_fw(__first, __last, _Tag());
56 }
57
58 template<typename _RAIter, typename _Tp>
59 _RAIter
60 __lower_bound(_RAIter __first, _RAIter __last, const _Tp& __val)
61 {
62 typedef typename std::iterator_traits<_RAIter>::difference_type _DType;
63
64 _DType __len = __last - __first;
65 while (__len > 0)
66 {
67 _DType __half = __len >> 1;
68 _RAIter __middle = __first + __half;
69 if (*__middle < __val)
70 {
71 __first = __middle;
72 ++__first;
73 __len = __len - __half - 1;
74 }
75 else
76 __len = __half;
77 }
78 return __first;
79 }
80
81 // Auxiliary types used for all instantiations of _Hashtable: nodes
82 // and iterators.
83
84 // Nodes, used to wrap elements stored in the hash table. A policy
85 // template parameter of class template _Hashtable controls whether
86 // nodes also store a hash code. In some cases (e.g. strings) this
87 // may be a performance win.
88 template<typename _Value, bool __cache_hash_code>
89 struct _Hash_node;
90
91 template<typename _Value>
92 struct _Hash_node<_Value, true>
93 {
94 _Value _M_v;
95 std::size_t _M_hash_code;
96 _Hash_node* _M_next;
97
98 #ifdef _GLIBCXX_INCLUDE_AS_CXX0X
99 template<typename... _Args>
100 _Hash_node(_Args&&... __args)
101 : _M_v(std::forward<_Args>(__args)...),
102 _M_hash_code(), _M_next() { }
103 #endif
104 };
105
106 template<typename _Value>
107 struct _Hash_node<_Value, false>
108 {
109 _Value _M_v;
110 _Hash_node* _M_next;
111
112 #ifdef _GLIBCXX_INCLUDE_AS_CXX0X
113 template<typename... _Args>
114 _Hash_node(_Args&&... __args)
115 : _M_v(std::forward<_Args>(__args)...),
116 _M_next() { }
117 #endif
118 };
119
120 // Local iterators, used to iterate within a bucket but not between
121 // buckets.
122 template<typename _Value, bool __cache>
123 struct _Node_iterator_base
124 {
125 _Node_iterator_base(_Hash_node<_Value, __cache>* __p)
126 : _M_cur(__p) { }
127
128 void
129 _M_incr()
130 { _M_cur = _M_cur->_M_next; }
131
132 _Hash_node<_Value, __cache>* _M_cur;
133 };
134
135 template<typename _Value, bool __cache>
136 inline bool
137 operator==(const _Node_iterator_base<_Value, __cache>& __x,
138 const _Node_iterator_base<_Value, __cache>& __y)
139 { return __x._M_cur == __y._M_cur; }
140
141 template<typename _Value, bool __cache>
142 inline bool
143 operator!=(const _Node_iterator_base<_Value, __cache>& __x,
144 const _Node_iterator_base<_Value, __cache>& __y)
145 { return __x._M_cur != __y._M_cur; }
146
147 template<typename _Value, bool __constant_iterators, bool __cache>
148 struct _Node_iterator
149 : public _Node_iterator_base<_Value, __cache>
150 {
151 typedef _Value value_type;
152 typedef typename
153 __gnu_cxx::__conditional_type<__constant_iterators,
154 const _Value*, _Value*>::__type
155 pointer;
156 typedef typename
157 __gnu_cxx::__conditional_type<__constant_iterators,
158 const _Value&, _Value&>::__type
159 reference;
160 typedef std::ptrdiff_t difference_type;
161 typedef std::forward_iterator_tag iterator_category;
162
163 _Node_iterator()
164 : _Node_iterator_base<_Value, __cache>(0) { }
165
166 explicit
167 _Node_iterator(_Hash_node<_Value, __cache>* __p)
168 : _Node_iterator_base<_Value, __cache>(__p) { }
169
170 reference
171 operator*() const
172 { return this->_M_cur->_M_v; }
173
174 pointer
175 operator->() const
176 { return &this->_M_cur->_M_v; }
177
178 _Node_iterator&
179 operator++()
180 {
181 this->_M_incr();
182 return *this;
183 }
184
185 _Node_iterator
186 operator++(int)
187 {
188 _Node_iterator __tmp(*this);
189 this->_M_incr();
190 return __tmp;
191 }
192 };
193
194 template<typename _Value, bool __constant_iterators, bool __cache>
195 struct _Node_const_iterator
196 : public _Node_iterator_base<_Value, __cache>
197 {
198 typedef _Value value_type;
199 typedef const _Value* pointer;
200 typedef const _Value& reference;
201 typedef std::ptrdiff_t difference_type;
202 typedef std::forward_iterator_tag iterator_category;
203
204 _Node_const_iterator()
205 : _Node_iterator_base<_Value, __cache>(0) { }
206
207 explicit
208 _Node_const_iterator(_Hash_node<_Value, __cache>* __p)
209 : _Node_iterator_base<_Value, __cache>(__p) { }
210
211 _Node_const_iterator(const _Node_iterator<_Value, __constant_iterators,
212 __cache>& __x)
213 : _Node_iterator_base<_Value, __cache>(__x._M_cur) { }
214
215 reference
216 operator*() const
217 { return this->_M_cur->_M_v; }
218
219 pointer
220 operator->() const
221 { return &this->_M_cur->_M_v; }
222
223 _Node_const_iterator&
224 operator++()
225 {
226 this->_M_incr();
227 return *this;
228 }
229
230 _Node_const_iterator
231 operator++(int)
232 {
233 _Node_const_iterator __tmp(*this);
234 this->_M_incr();
235 return __tmp;
236 }
237 };
238
239 template<typename _Value, bool __cache>
240 struct _Hashtable_iterator_base
241 {
242 _Hashtable_iterator_base(_Hash_node<_Value, __cache>* __node,
243 _Hash_node<_Value, __cache>** __bucket)
244 : _M_cur_node(__node), _M_cur_bucket(__bucket) { }
245
246 void
247 _M_incr()
248 {
249 _M_cur_node = _M_cur_node->_M_next;
250 if (!_M_cur_node)
251 _M_incr_bucket();
252 }
253
254 void
255 _M_incr_bucket();
256
257 _Hash_node<_Value, __cache>* _M_cur_node;
258 _Hash_node<_Value, __cache>** _M_cur_bucket;
259 };
260
261 // Global iterators, used for arbitrary iteration within a hash
262 // table. Larger and more expensive than local iterators.
263 template<typename _Value, bool __cache>
264 void
265 _Hashtable_iterator_base<_Value, __cache>::
266 _M_incr_bucket()
267 {
268 ++_M_cur_bucket;
269
270 // This loop requires the bucket array to have a non-null sentinel.
271 while (!*_M_cur_bucket)
272 ++_M_cur_bucket;
273 _M_cur_node = *_M_cur_bucket;
274 }
275
276 template<typename _Value, bool __cache>
277 inline bool
278 operator==(const _Hashtable_iterator_base<_Value, __cache>& __x,
279 const _Hashtable_iterator_base<_Value, __cache>& __y)
280 { return __x._M_cur_node == __y._M_cur_node; }
281
282 template<typename _Value, bool __cache>
283 inline bool
284 operator!=(const _Hashtable_iterator_base<_Value, __cache>& __x,
285 const _Hashtable_iterator_base<_Value, __cache>& __y)
286 { return __x._M_cur_node != __y._M_cur_node; }
287
288 template<typename _Value, bool __constant_iterators, bool __cache>
289 struct _Hashtable_iterator
290 : public _Hashtable_iterator_base<_Value, __cache>
291 {
292 typedef _Value value_type;
293 typedef typename
294 __gnu_cxx::__conditional_type<__constant_iterators,
295 const _Value*, _Value*>::__type
296 pointer;
297 typedef typename
298 __gnu_cxx::__conditional_type<__constant_iterators,
299 const _Value&, _Value&>::__type
300 reference;
301 typedef std::ptrdiff_t difference_type;
302 typedef std::forward_iterator_tag iterator_category;
303
304 _Hashtable_iterator()
305 : _Hashtable_iterator_base<_Value, __cache>(0, 0) { }
306
307 _Hashtable_iterator(_Hash_node<_Value, __cache>* __p,
308 _Hash_node<_Value, __cache>** __b)
309 : _Hashtable_iterator_base<_Value, __cache>(__p, __b) { }
310
311 explicit
312 _Hashtable_iterator(_Hash_node<_Value, __cache>** __b)
313 : _Hashtable_iterator_base<_Value, __cache>(*__b, __b) { }
314
315 reference
316 operator*() const
317 { return this->_M_cur_node->_M_v; }
318
319 pointer
320 operator->() const
321 { return &this->_M_cur_node->_M_v; }
322
323 _Hashtable_iterator&
324 operator++()
325 {
326 this->_M_incr();
327 return *this;
328 }
329
330 _Hashtable_iterator
331 operator++(int)
332 {
333 _Hashtable_iterator __tmp(*this);
334 this->_M_incr();
335 return __tmp;
336 }
337 };
338
339 template<typename _Value, bool __constant_iterators, bool __cache>
340 struct _Hashtable_const_iterator
341 : public _Hashtable_iterator_base<_Value, __cache>
342 {
343 typedef _Value value_type;
344 typedef const _Value* pointer;
345 typedef const _Value& reference;
346 typedef std::ptrdiff_t difference_type;
347 typedef std::forward_iterator_tag iterator_category;
348
349 _Hashtable_const_iterator()
350 : _Hashtable_iterator_base<_Value, __cache>(0, 0) { }
351
352 _Hashtable_const_iterator(_Hash_node<_Value, __cache>* __p,
353 _Hash_node<_Value, __cache>** __b)
354 : _Hashtable_iterator_base<_Value, __cache>(__p, __b) { }
355
356 explicit
357 _Hashtable_const_iterator(_Hash_node<_Value, __cache>** __b)
358 : _Hashtable_iterator_base<_Value, __cache>(*__b, __b) { }
359
360 _Hashtable_const_iterator(const _Hashtable_iterator<_Value,
361 __constant_iterators, __cache>& __x)
362 : _Hashtable_iterator_base<_Value, __cache>(__x._M_cur_node,
363 __x._M_cur_bucket) { }
364
365 reference
366 operator*() const
367 { return this->_M_cur_node->_M_v; }
368
369 pointer
370 operator->() const
371 { return &this->_M_cur_node->_M_v; }
372
373 _Hashtable_const_iterator&
374 operator++()
375 {
376 this->_M_incr();
377 return *this;
378 }
379
380 _Hashtable_const_iterator
381 operator++(int)
382 {
383 _Hashtable_const_iterator __tmp(*this);
384 this->_M_incr();
385 return __tmp;
386 }
387 };
388
389
390 // Many of class template _Hashtable's template parameters are policy
391 // classes. These are defaults for the policies.
392
393 // Default range hashing function: use division to fold a large number
394 // into the range [0, N).
395 struct _Mod_range_hashing
396 {
397 typedef std::size_t first_argument_type;
398 typedef std::size_t second_argument_type;
399 typedef std::size_t result_type;
400
401 result_type
402 operator()(first_argument_type __num, second_argument_type __den) const
403 { return __num % __den; }
404 };
405
406 // Default ranged hash function H. In principle it should be a
407 // function object composed from objects of type H1 and H2 such that
408 // h(k, N) = h2(h1(k), N), but that would mean making extra copies of
409 // h1 and h2. So instead we'll just use a tag to tell class template
410 // hashtable to do that composition.
411 struct _Default_ranged_hash { };
412
413 // Default value for rehash policy. Bucket size is (usually) the
414 // smallest prime that keeps the load factor small enough.
415 struct _Prime_rehash_policy
416 {
417 _Prime_rehash_policy(float __z = 1.0)
418 : _M_max_load_factor(__z), _M_growth_factor(2.f), _M_next_resize(0) { }
419
420 float
421 max_load_factor() const
422 { return _M_max_load_factor; }
423
424 // Return a bucket size no smaller than n.
425 std::size_t
426 _M_next_bkt(std::size_t __n) const;
427
428 // Return a bucket count appropriate for n elements
429 std::size_t
430 _M_bkt_for_elements(std::size_t __n) const;
431
432 // __n_bkt is current bucket count, __n_elt is current element count,
433 // and __n_ins is number of elements to be inserted. Do we need to
434 // increase bucket count? If so, return make_pair(true, n), where n
435 // is the new bucket count. If not, return make_pair(false, 0).
436 std::pair<bool, std::size_t>
437 _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt,
438 std::size_t __n_ins) const;
439
440 enum { _S_n_primes = sizeof(unsigned long) != 8 ? 256 : 256 + 48 };
441
442 float _M_max_load_factor;
443 float _M_growth_factor;
444 mutable std::size_t _M_next_resize;
445 };
446
447 extern const unsigned long __prime_list[];
448
449 // XXX This is a hack. There's no good reason for any of
450 // _Prime_rehash_policy's member functions to be inline.
451
452 // Return a prime no smaller than n.
453 inline std::size_t
454 _Prime_rehash_policy::
455 _M_next_bkt(std::size_t __n) const
456 {
457 const unsigned long* __p = __lower_bound(__prime_list, __prime_list
458 + _S_n_primes, __n);
459 _M_next_resize =
460 static_cast<std::size_t>(__builtin_ceil(*__p * _M_max_load_factor));
461 return *__p;
462 }
463
464 // Return the smallest prime p such that alpha p >= n, where alpha
465 // is the load factor.
466 inline std::size_t
467 _Prime_rehash_policy::
468 _M_bkt_for_elements(std::size_t __n) const
469 {
470 const float __min_bkts = __n / _M_max_load_factor;
471 const unsigned long* __p = __lower_bound(__prime_list, __prime_list
472 + _S_n_primes, __min_bkts);
473 _M_next_resize =
474 static_cast<std::size_t>(__builtin_ceil(*__p * _M_max_load_factor));
475 return *__p;
476 }
477
478 // Finds the smallest prime p such that alpha p > __n_elt + __n_ins.
479 // If p > __n_bkt, return make_pair(true, p); otherwise return
480 // make_pair(false, 0). In principle this isn't very different from
481 // _M_bkt_for_elements.
482
483 // The only tricky part is that we're caching the element count at
484 // which we need to rehash, so we don't have to do a floating-point
485 // multiply for every insertion.
486
487 inline std::pair<bool, std::size_t>
488 _Prime_rehash_policy::
489 _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt,
490 std::size_t __n_ins) const
491 {
492 if (__n_elt + __n_ins > _M_next_resize)
493 {
494 float __min_bkts = ((float(__n_ins) + float(__n_elt))
495 / _M_max_load_factor);
496 if (__min_bkts > __n_bkt)
497 {
498 __min_bkts = std::max(__min_bkts, _M_growth_factor * __n_bkt);
499 const unsigned long* __p =
500 __lower_bound(__prime_list, __prime_list + _S_n_primes,
501 __min_bkts);
502 _M_next_resize = static_cast<std::size_t>
503 (__builtin_ceil(*__p * _M_max_load_factor));
504 return std::make_pair(true, *__p);
505 }
506 else
507 {
508 _M_next_resize = static_cast<std::size_t>
509 (__builtin_ceil(__n_bkt * _M_max_load_factor));
510 return std::make_pair(false, 0);
511 }
512 }
513 else
514 return std::make_pair(false, 0);
515 }
516
517 // Base classes for std::tr1::_Hashtable. We define these base
518 // classes because in some cases we want to do different things
519 // depending on the value of a policy class. In some cases the
520 // policy class affects which member functions and nested typedefs
521 // are defined; we handle that by specializing base class templates.
522 // Several of the base class templates need to access other members
523 // of class template _Hashtable, so we use the "curiously recurring
524 // template pattern" for them.
525
526 // class template _Map_base. If the hashtable has a value type of the
527 // form pair<T1, T2> and a key extraction policy that returns the
528 // first part of the pair, the hashtable gets a mapped_type typedef.
529 // If it satisfies those criteria and also has unique keys, then it
530 // also gets an operator[].
531 template<typename _Key, typename _Value, typename _Ex, bool __unique,
532 typename _Hashtable>
533 struct _Map_base { };
534
535 template<typename _Key, typename _Pair, typename _Hashtable>
536 struct _Map_base<_Key, _Pair, std::_Select1st<_Pair>, false, _Hashtable>
537 {
538 typedef typename _Pair::second_type mapped_type;
539 };
540
541 template<typename _Key, typename _Pair, typename _Hashtable>
542 struct _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>
543 {
544 typedef typename _Pair::second_type mapped_type;
545
546 mapped_type&
547 operator[](const _Key& __k);
548
549 #ifdef _GLIBCXX_INCLUDE_AS_CXX0X
550 // _GLIBCXX_RESOLVE_LIB_DEFECTS
551 // DR 761. unordered_map needs an at() member function.
552 mapped_type&
553 at(const _Key& __k);
554
555 const mapped_type&
556 at(const _Key& __k) const;
557 #endif
558 };
559
560 template<typename _Key, typename _Pair, typename _Hashtable>
561 typename _Map_base<_Key, _Pair, std::_Select1st<_Pair>,
562 true, _Hashtable>::mapped_type&
563 _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::
564 operator[](const _Key& __k)
565 {
566 _Hashtable* __h = static_cast<_Hashtable*>(this);
567 typename _Hashtable::_Hash_code_type __code = __h->_M_hash_code(__k);
568 std::size_t __n = __h->_M_bucket_index(__k, __code,
569 __h->_M_bucket_count);
570
571 typename _Hashtable::_Node* __p =
572 __h->_M_find_node(__h->_M_buckets[__n], __k, __code);
573 if (!__p)
574 return __h->_M_insert_bucket(std::make_pair(__k, mapped_type()),
575 __n, __code)->second;
576 return (__p->_M_v).second;
577 }
578
579 #ifdef _GLIBCXX_INCLUDE_AS_CXX0X
580 template<typename _Key, typename _Pair, typename _Hashtable>
581 typename _Map_base<_Key, _Pair, std::_Select1st<_Pair>,
582 true, _Hashtable>::mapped_type&
583 _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::
584 at(const _Key& __k)
585 {
586 _Hashtable* __h = static_cast<_Hashtable*>(this);
587 typename _Hashtable::_Hash_code_type __code = __h->_M_hash_code(__k);
588 std::size_t __n = __h->_M_bucket_index(__k, __code,
589 __h->_M_bucket_count);
590
591 typename _Hashtable::_Node* __p =
592 __h->_M_find_node(__h->_M_buckets[__n], __k, __code);
593 if (!__p)
594 __throw_out_of_range(__N("_Map_base::at"));
595 return (__p->_M_v).second;
596 }
597
598 template<typename _Key, typename _Pair, typename _Hashtable>
599 const typename _Map_base<_Key, _Pair, std::_Select1st<_Pair>,
600 true, _Hashtable>::mapped_type&
601 _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::
602 at(const _Key& __k) const
603 {
604 const _Hashtable* __h = static_cast<const _Hashtable*>(this);
605 typename _Hashtable::_Hash_code_type __code = __h->_M_hash_code(__k);
606 std::size_t __n = __h->_M_bucket_index(__k, __code,
607 __h->_M_bucket_count);
608
609 typename _Hashtable::_Node* __p =
610 __h->_M_find_node(__h->_M_buckets[__n], __k, __code);
611 if (!__p)
612 __throw_out_of_range(__N("_Map_base::at"));
613 return (__p->_M_v).second;
614 }
615 #endif
616
617 // class template _Rehash_base. Give hashtable the max_load_factor
618 // functions iff the rehash policy is _Prime_rehash_policy.
619 template<typename _RehashPolicy, typename _Hashtable>
620 struct _Rehash_base { };
621
622 template<typename _Hashtable>
623 struct _Rehash_base<_Prime_rehash_policy, _Hashtable>
624 {
625 float
626 max_load_factor() const
627 {
628 const _Hashtable* __this = static_cast<const _Hashtable*>(this);
629 return __this->__rehash_policy().max_load_factor();
630 }
631
632 void
633 max_load_factor(float __z)
634 {
635 _Hashtable* __this = static_cast<_Hashtable*>(this);
636 __this->__rehash_policy(_Prime_rehash_policy(__z));
637 }
638 };
639
640 // Class template _Hash_code_base. Encapsulates two policy issues that
641 // aren't quite orthogonal.
642 // (1) the difference between using a ranged hash function and using
643 // the combination of a hash function and a range-hashing function.
644 // In the former case we don't have such things as hash codes, so
645 // we have a dummy type as placeholder.
646 // (2) Whether or not we cache hash codes. Caching hash codes is
647 // meaningless if we have a ranged hash function.
648 // We also put the key extraction and equality comparison function
649 // objects here, for convenience.
650
651 // Primary template: unused except as a hook for specializations.
652 template<typename _Key, typename _Value,
653 typename _ExtractKey, typename _Equal,
654 typename _H1, typename _H2, typename _Hash,
655 bool __cache_hash_code>
656 struct _Hash_code_base;
657
658 // Specialization: ranged hash function, no caching hash codes. H1
659 // and H2 are provided but ignored. We define a dummy hash code type.
660 template<typename _Key, typename _Value,
661 typename _ExtractKey, typename _Equal,
662 typename _H1, typename _H2, typename _Hash>
663 struct _Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2,
664 _Hash, false>
665 {
666 protected:
667 _Hash_code_base(const _ExtractKey& __ex, const _Equal& __eq,
668 const _H1&, const _H2&, const _Hash& __h)
669 : _M_extract(__ex), _M_eq(__eq), _M_ranged_hash(__h) { }
670
671 typedef void* _Hash_code_type;
672
673 _Hash_code_type
674 _M_hash_code(const _Key& __key) const
675 { return 0; }
676
677 std::size_t
678 _M_bucket_index(const _Key& __k, _Hash_code_type,
679 std::size_t __n) const
680 { return _M_ranged_hash(__k, __n); }
681
682 std::size_t
683 _M_bucket_index(const _Hash_node<_Value, false>* __p,
684 std::size_t __n) const
685 { return _M_ranged_hash(_M_extract(__p->_M_v), __n); }
686
687 bool
688 _M_compare(const _Key& __k, _Hash_code_type,
689 _Hash_node<_Value, false>* __n) const
690 { return _M_eq(__k, _M_extract(__n->_M_v)); }
691
692 void
693 _M_store_code(_Hash_node<_Value, false>*, _Hash_code_type) const
694 { }
695
696 void
697 _M_copy_code(_Hash_node<_Value, false>*,
698 const _Hash_node<_Value, false>*) const
699 { }
700
701 void
702 _M_swap(_Hash_code_base& __x)
703 {
704 std::swap(_M_extract, __x._M_extract);
705 std::swap(_M_eq, __x._M_eq);
706 std::swap(_M_ranged_hash, __x._M_ranged_hash);
707 }
708
709 protected:
710 _ExtractKey _M_extract;
711 _Equal _M_eq;
712 _Hash _M_ranged_hash;
713 };
714
715
716 // No specialization for ranged hash function while caching hash codes.
717 // That combination is meaningless, and trying to do it is an error.
718
719
720 // Specialization: ranged hash function, cache hash codes. This
721 // combination is meaningless, so we provide only a declaration
722 // and no definition.
723 template<typename _Key, typename _Value,
724 typename _ExtractKey, typename _Equal,
725 typename _H1, typename _H2, typename _Hash>
726 struct _Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2,
727 _Hash, true>;
728
729 // Specialization: hash function and range-hashing function, no
730 // caching of hash codes. H is provided but ignored. Provides
731 // typedef and accessor required by TR1.
732 template<typename _Key, typename _Value,
733 typename _ExtractKey, typename _Equal,
734 typename _H1, typename _H2>
735 struct _Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2,
736 _Default_ranged_hash, false>
737 {
738 typedef _H1 hasher;
739
740 hasher
741 hash_function() const
742 { return _M_h1; }
743
744 protected:
745 _Hash_code_base(const _ExtractKey& __ex, const _Equal& __eq,
746 const _H1& __h1, const _H2& __h2,
747 const _Default_ranged_hash&)
748 : _M_extract(__ex), _M_eq(__eq), _M_h1(__h1), _M_h2(__h2) { }
749
750 typedef std::size_t _Hash_code_type;
751
752 _Hash_code_type
753 _M_hash_code(const _Key& __k) const
754 { return _M_h1(__k); }
755
756 std::size_t
757 _M_bucket_index(const _Key&, _Hash_code_type __c,
758 std::size_t __n) const
759 { return _M_h2(__c, __n); }
760
761 std::size_t
762 _M_bucket_index(const _Hash_node<_Value, false>* __p,
763 std::size_t __n) const
764 { return _M_h2(_M_h1(_M_extract(__p->_M_v)), __n); }
765
766 bool
767 _M_compare(const _Key& __k, _Hash_code_type,
768 _Hash_node<_Value, false>* __n) const
769 { return _M_eq(__k, _M_extract(__n->_M_v)); }
770
771 void
772 _M_store_code(_Hash_node<_Value, false>*, _Hash_code_type) const
773 { }
774
775 void
776 _M_copy_code(_Hash_node<_Value, false>*,
777 const _Hash_node<_Value, false>*) const
778 { }
779
780 void
781 _M_swap(_Hash_code_base& __x)
782 {
783 std::swap(_M_extract, __x._M_extract);
784 std::swap(_M_eq, __x._M_eq);
785 std::swap(_M_h1, __x._M_h1);
786 std::swap(_M_h2, __x._M_h2);
787 }
788
789 protected:
790 _ExtractKey _M_extract;
791 _Equal _M_eq;
792 _H1 _M_h1;
793 _H2 _M_h2;
794 };
795
796 // Specialization: hash function and range-hashing function,
797 // caching hash codes. H is provided but ignored. Provides
798 // typedef and accessor required by TR1.
799 template<typename _Key, typename _Value,
800 typename _ExtractKey, typename _Equal,
801 typename _H1, typename _H2>
802 struct _Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2,
803 _Default_ranged_hash, true>
804 {
805 typedef _H1 hasher;
806
807 hasher
808 hash_function() const
809 { return _M_h1; }
810
811 protected:
812 _Hash_code_base(const _ExtractKey& __ex, const _Equal& __eq,
813 const _H1& __h1, const _H2& __h2,
814 const _Default_ranged_hash&)
815 : _M_extract(__ex), _M_eq(__eq), _M_h1(__h1), _M_h2(__h2) { }
816
817 typedef std::size_t _Hash_code_type;
818
819 _Hash_code_type
820 _M_hash_code(const _Key& __k) const
821 { return _M_h1(__k); }
822
823 std::size_t
824 _M_bucket_index(const _Key&, _Hash_code_type __c,
825 std::size_t __n) const
826 { return _M_h2(__c, __n); }
827
828 std::size_t
829 _M_bucket_index(const _Hash_node<_Value, true>* __p,
830 std::size_t __n) const
831 { return _M_h2(__p->_M_hash_code, __n); }
832
833 bool
834 _M_compare(const _Key& __k, _Hash_code_type __c,
835 _Hash_node<_Value, true>* __n) const
836 { return __c == __n->_M_hash_code && _M_eq(__k, _M_extract(__n->_M_v)); }
837
838 void
839 _M_store_code(_Hash_node<_Value, true>* __n, _Hash_code_type __c) const
840 { __n->_M_hash_code = __c; }
841
842 void
843 _M_copy_code(_Hash_node<_Value, true>* __to,
844 const _Hash_node<_Value, true>* __from) const
845 { __to->_M_hash_code = __from->_M_hash_code; }
846
847 void
848 _M_swap(_Hash_code_base& __x)
849 {
850 std::swap(_M_extract, __x._M_extract);
851 std::swap(_M_eq, __x._M_eq);
852 std::swap(_M_h1, __x._M_h1);
853 std::swap(_M_h2, __x._M_h2);
854 }
855
856 protected:
857 _ExtractKey _M_extract;
858 _Equal _M_eq;
859 _H1 _M_h1;
860 _H2 _M_h2;
861 };
862 } // namespace __detail
863
864 _GLIBCXX_END_NAMESPACE_TR1
865 }