|
libstdc++
|
00001 // Internal policy header for unordered_set and unordered_map -*- C++ -*- 00002 00003 // Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /** @file bits/hashtable_policy.h 00026 * This is an internal header file, included by other library headers. 00027 * Do not attempt to use it directly. 00028 * @headername{unordered_map,unordered_set} 00029 */ 00030 00031 #ifndef _HASHTABLE_POLICY_H 00032 #define _HASHTABLE_POLICY_H 1 00033 00034 namespace std _GLIBCXX_VISIBILITY(default) 00035 { 00036 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00037 00038 template<typename _Key, typename _Value, typename _Alloc, 00039 typename _ExtractKey, typename _Equal, 00040 typename _H1, typename _H2, typename _Hash, 00041 typename _RehashPolicy, typename _Traits> 00042 class _Hashtable; 00043 00044 _GLIBCXX_END_NAMESPACE_VERSION 00045 00046 namespace __detail 00047 { 00048 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00049 00050 /** 00051 * @defgroup hashtable-detail Base and Implementation Classes 00052 * @ingroup unordered_associative_containers 00053 * @{ 00054 */ 00055 template<typename _Key, typename _Value, 00056 typename _ExtractKey, typename _Equal, 00057 typename _H1, typename _H2, typename _Hash, typename _Traits> 00058 struct _Hashtable_base; 00059 00060 // Helper function: return distance(first, last) for forward 00061 // iterators, or 0 for input iterators. 00062 template<class _Iterator> 00063 inline typename std::iterator_traits<_Iterator>::difference_type 00064 __distance_fw(_Iterator __first, _Iterator __last, 00065 std::input_iterator_tag) 00066 { return 0; } 00067 00068 template<class _Iterator> 00069 inline typename std::iterator_traits<_Iterator>::difference_type 00070 __distance_fw(_Iterator __first, _Iterator __last, 00071 std::forward_iterator_tag) 00072 { return std::distance(__first, __last); } 00073 00074 template<class _Iterator> 00075 inline typename std::iterator_traits<_Iterator>::difference_type 00076 __distance_fw(_Iterator __first, _Iterator __last) 00077 { 00078 typedef typename std::iterator_traits<_Iterator>::iterator_category _Tag; 00079 return __distance_fw(__first, __last, _Tag()); 00080 } 00081 00082 // Helper type used to detect when the hash functor is noexcept qualified or 00083 // not 00084 template <typename _Key, typename _Hash> 00085 struct __is_noexcept_hash : std::integral_constant<bool, 00086 noexcept(declval<const _Hash&>()(declval<const _Key&>()))> 00087 { }; 00088 00089 // Auxiliary types used for all instantiations of _Hashtable nodes 00090 // and iterators. 00091 00092 /** 00093 * struct _Hashtable_traits 00094 * 00095 * Important traits for hash tables. 00096 * 00097 * @tparam __cache_hash_code Boolean value. True if the value of 00098 * the hash function is stored along with the value. This is a 00099 * time-space tradeoff. Storing it may improve lookup speed by 00100 * reducing the number of times we need to call the _Equal 00101 * function. 00102 * 00103 * @tparam __constant_iterators Boolean value. True if iterator and 00104 * const_iterator are both constant iterator types. This is true 00105 * for unordered_set and unordered_multiset, false for 00106 * unordered_map and unordered_multimap. 00107 * 00108 * @tparam __unique_keys Boolean value. True if the return value 00109 * of _Hashtable::count(k) is always at most one, false if it may 00110 * be an arbitrary number. This true for unordered_set and 00111 * unordered_map, false for unordered_multiset and 00112 * unordered_multimap. 00113 */ 00114 template<bool _Cache_hash_code, bool _Constant_iterators, bool _Unique_keys> 00115 struct _Hashtable_traits 00116 { 00117 template<bool _Cond> 00118 using __bool_constant = integral_constant<bool, _Cond>; 00119 00120 using __hash_cached = __bool_constant<_Cache_hash_code>; 00121 using __constant_iterators = __bool_constant<_Constant_iterators>; 00122 using __unique_keys = __bool_constant<_Unique_keys>; 00123 }; 00124 00125 /** 00126 * struct _Hash_node_base 00127 * 00128 * Nodes, used to wrap elements stored in the hash table. A policy 00129 * template parameter of class template _Hashtable controls whether 00130 * nodes also store a hash code. In some cases (e.g. strings) this 00131 * may be a performance win. 00132 */ 00133 struct _Hash_node_base 00134 { 00135 _Hash_node_base* _M_nxt; 00136 00137 _Hash_node_base() : _M_nxt() { } 00138 00139 _Hash_node_base(_Hash_node_base* __next) : _M_nxt(__next) { } 00140 }; 00141 00142 /** 00143 * Primary template struct _Hash_node. 00144 */ 00145 template<typename _Value, bool _Cache_hash_code> 00146 struct _Hash_node; 00147 00148 /** 00149 * Specialization for nodes with caches, struct _Hash_node. 00150 * 00151 * Base class is __detail::_Hash_node_base. 00152 */ 00153 template<typename _Value> 00154 struct _Hash_node<_Value, true> : _Hash_node_base 00155 { 00156 _Value _M_v; 00157 std::size_t _M_hash_code; 00158 00159 template<typename... _Args> 00160 _Hash_node(_Args&&... __args) 00161 : _M_v(std::forward<_Args>(__args)...), _M_hash_code() { } 00162 00163 _Hash_node* 00164 _M_next() const { return static_cast<_Hash_node*>(_M_nxt); } 00165 }; 00166 00167 /** 00168 * Specialization for nodes without caches, struct _Hash_node. 00169 * 00170 * Base class is __detail::_Hash_node_base. 00171 */ 00172 template<typename _Value> 00173 struct _Hash_node<_Value, false> : _Hash_node_base 00174 { 00175 _Value _M_v; 00176 00177 template<typename... _Args> 00178 _Hash_node(_Args&&... __args) 00179 : _M_v(std::forward<_Args>(__args)...) { } 00180 00181 _Hash_node* 00182 _M_next() const { return static_cast<_Hash_node*>(_M_nxt); } 00183 }; 00184 00185 /// Base class for node iterators. 00186 template<typename _Value, bool _Cache_hash_code> 00187 struct _Node_iterator_base 00188 { 00189 typedef _Hash_node<_Value, _Cache_hash_code> __node_type; 00190 00191 __node_type* _M_cur; 00192 00193 _Node_iterator_base(__node_type* __p) 00194 : _M_cur(__p) { } 00195 00196 void 00197 _M_incr() 00198 { _M_cur = _M_cur->_M_next(); } 00199 }; 00200 00201 template<typename _Value, bool _Cache_hash_code> 00202 inline bool 00203 operator==(const _Node_iterator_base<_Value, _Cache_hash_code>& __x, 00204 const _Node_iterator_base<_Value, _Cache_hash_code >& __y) 00205 { return __x._M_cur == __y._M_cur; } 00206 00207 template<typename _Value, bool _Cache_hash_code> 00208 inline bool 00209 operator!=(const _Node_iterator_base<_Value, _Cache_hash_code>& __x, 00210 const _Node_iterator_base<_Value, _Cache_hash_code>& __y) 00211 { return __x._M_cur != __y._M_cur; } 00212 00213 /// Node iterators, used to iterate through all the hashtable. 00214 template<typename _Value, bool __constant_iterators, bool __cache> 00215 struct _Node_iterator 00216 : public _Node_iterator_base<_Value, __cache> 00217 { 00218 private: 00219 using __base_type = _Node_iterator_base<_Value, __cache>; 00220 using __node_type = typename __base_type::__node_type; 00221 00222 public: 00223 typedef _Value value_type; 00224 typedef std::ptrdiff_t difference_type; 00225 typedef std::forward_iterator_tag iterator_category; 00226 00227 using pointer = typename std::conditional<__constant_iterators, 00228 const _Value*, _Value*>::type; 00229 00230 using reference = typename std::conditional<__constant_iterators, 00231 const _Value&, _Value&>::type; 00232 00233 _Node_iterator() 00234 : __base_type(0) { } 00235 00236 explicit 00237 _Node_iterator(__node_type* __p) 00238 : __base_type(__p) { } 00239 00240 reference 00241 operator*() const 00242 { return this->_M_cur->_M_v; } 00243 00244 pointer 00245 operator->() const 00246 { return std::__addressof(this->_M_cur->_M_v); } 00247 00248 _Node_iterator& 00249 operator++() 00250 { 00251 this->_M_incr(); 00252 return *this; 00253 } 00254 00255 _Node_iterator 00256 operator++(int) 00257 { 00258 _Node_iterator __tmp(*this); 00259 this->_M_incr(); 00260 return __tmp; 00261 } 00262 }; 00263 00264 /// Node const_iterators, used to iterate through all the hashtable. 00265 template<typename _Value, bool __constant_iterators, bool __cache> 00266 struct _Node_const_iterator 00267 : public _Node_iterator_base<_Value, __cache> 00268 { 00269 private: 00270 using __base_type = _Node_iterator_base<_Value, __cache>; 00271 using __node_type = typename __base_type::__node_type; 00272 00273 public: 00274 typedef _Value value_type; 00275 typedef std::ptrdiff_t difference_type; 00276 typedef std::forward_iterator_tag iterator_category; 00277 00278 typedef const _Value* pointer; 00279 typedef const _Value& reference; 00280 00281 _Node_const_iterator() 00282 : __base_type(0) { } 00283 00284 explicit 00285 _Node_const_iterator(__node_type* __p) 00286 : __base_type(__p) { } 00287 00288 _Node_const_iterator(const _Node_iterator<_Value, __constant_iterators, 00289 __cache>& __x) 00290 : __base_type(__x._M_cur) { } 00291 00292 reference 00293 operator*() const 00294 { return this->_M_cur->_M_v; } 00295 00296 pointer 00297 operator->() const 00298 { return std::__addressof(this->_M_cur->_M_v); } 00299 00300 _Node_const_iterator& 00301 operator++() 00302 { 00303 this->_M_incr(); 00304 return *this; 00305 } 00306 00307 _Node_const_iterator 00308 operator++(int) 00309 { 00310 _Node_const_iterator __tmp(*this); 00311 this->_M_incr(); 00312 return __tmp; 00313 } 00314 }; 00315 00316 // Many of class template _Hashtable's template parameters are policy 00317 // classes. These are defaults for the policies. 00318 00319 /// Default range hashing function: use division to fold a large number 00320 /// into the range [0, N). 00321 struct _Mod_range_hashing 00322 { 00323 typedef std::size_t first_argument_type; 00324 typedef std::size_t second_argument_type; 00325 typedef std::size_t result_type; 00326 00327 result_type 00328 operator()(first_argument_type __num, second_argument_type __den) const 00329 { return __num % __den; } 00330 }; 00331 00332 /// Default ranged hash function H. In principle it should be a 00333 /// function object composed from objects of type H1 and H2 such that 00334 /// h(k, N) = h2(h1(k), N), but that would mean making extra copies of 00335 /// h1 and h2. So instead we'll just use a tag to tell class template 00336 /// hashtable to do that composition. 00337 struct _Default_ranged_hash { }; 00338 00339 /// Default value for rehash policy. Bucket size is (usually) the 00340 /// smallest prime that keeps the load factor small enough. 00341 struct _Prime_rehash_policy 00342 { 00343 _Prime_rehash_policy(float __z = 1.0) 00344 : _M_max_load_factor(__z), _M_prev_resize(0), _M_next_resize(0) { } 00345 00346 float 00347 max_load_factor() const noexcept 00348 { return _M_max_load_factor; } 00349 00350 // Return a bucket size no smaller than n. 00351 std::size_t 00352 _M_next_bkt(std::size_t __n) const; 00353 00354 // Return a bucket count appropriate for n elements 00355 std::size_t 00356 _M_bkt_for_elements(std::size_t __n) const; 00357 00358 // __n_bkt is current bucket count, __n_elt is current element count, 00359 // and __n_ins is number of elements to be inserted. Do we need to 00360 // increase bucket count? If so, return make_pair(true, n), where n 00361 // is the new bucket count. If not, return make_pair(false, 0). 00362 std::pair<bool, std::size_t> 00363 _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt, 00364 std::size_t __n_ins) const; 00365 00366 typedef std::pair<std::size_t, std::size_t> _State; 00367 00368 _State 00369 _M_state() const 00370 { return std::make_pair(_M_prev_resize, _M_next_resize); } 00371 00372 void 00373 _M_reset(const _State& __state) 00374 { 00375 _M_prev_resize = __state.first; 00376 _M_next_resize = __state.second; 00377 } 00378 00379 enum { _S_n_primes = sizeof(unsigned long) != 8 ? 256 : 256 + 48 }; 00380 00381 float _M_max_load_factor; 00382 mutable std::size_t _M_prev_resize; 00383 mutable std::size_t _M_next_resize; 00384 }; 00385 00386 extern const unsigned long __prime_list[]; 00387 00388 // XXX This is a hack. There's no good reason for any of 00389 // _Prime_rehash_policy's member functions to be inline. 00390 00391 // Return a prime no smaller than n. 00392 inline std::size_t 00393 _Prime_rehash_policy:: 00394 _M_next_bkt(std::size_t __n) const 00395 { 00396 // Optimize lookups involving the first elements of __prime_list. 00397 // (useful to speed-up, eg, constructors) 00398 static const unsigned char __fast_bkt[12] 00399 = { 2, 2, 2, 3, 5, 5, 7, 7, 11, 11, 11, 11 }; 00400 00401 if (__n <= 11) 00402 { 00403 _M_prev_resize = 0; 00404 _M_next_resize 00405 = __builtin_ceil(__fast_bkt[__n] * (long double)_M_max_load_factor); 00406 return __fast_bkt[__n]; 00407 } 00408 00409 const unsigned long* __p 00410 = std::lower_bound(__prime_list + 5, __prime_list + _S_n_primes, __n); 00411 00412 // Shrink will take place only if the number of elements is small enough 00413 // so that the prime number 2 steps before __p is large enough to still 00414 // conform to the max load factor: 00415 _M_prev_resize 00416 = __builtin_floor(*(__p - 2) * (long double)_M_max_load_factor); 00417 00418 // Let's guaranty that a minimal grow step of 11 is used 00419 if (*__p - __n < 11) 00420 __p = std::lower_bound(__p, __prime_list + _S_n_primes, __n + 11); 00421 _M_next_resize = __builtin_ceil(*__p * (long double)_M_max_load_factor); 00422 return *__p; 00423 } 00424 00425 // Return the smallest prime p such that alpha p >= n, where alpha 00426 // is the load factor. 00427 inline std::size_t 00428 _Prime_rehash_policy:: 00429 _M_bkt_for_elements(std::size_t __n) const 00430 { return _M_next_bkt(__builtin_ceil(__n / (long double)_M_max_load_factor)); } 00431 00432 // Finds the smallest prime p such that alpha p > __n_elt + __n_ins. 00433 // If p > __n_bkt, return make_pair(true, p); otherwise return 00434 // make_pair(false, 0). In principle this isn't very different from 00435 // _M_bkt_for_elements. 00436 00437 // The only tricky part is that we're caching the element count at 00438 // which we need to rehash, so we don't have to do a floating-point 00439 // multiply for every insertion. 00440 00441 inline std::pair<bool, std::size_t> 00442 _Prime_rehash_policy:: 00443 _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt, 00444 std::size_t __n_ins) const 00445 { 00446 if (__n_elt + __n_ins >= _M_next_resize) 00447 { 00448 long double __min_bkts = (__n_elt + __n_ins) 00449 / (long double)_M_max_load_factor; 00450 if (__min_bkts >= __n_bkt) 00451 return std::make_pair(true, 00452 _M_next_bkt(__builtin_floor(__min_bkts) + 1)); 00453 else 00454 { 00455 _M_next_resize 00456 = __builtin_floor(__n_bkt * (long double)_M_max_load_factor); 00457 return std::make_pair(false, 0); 00458 } 00459 } 00460 else if (__n_elt + __n_ins < _M_prev_resize) 00461 { 00462 long double __min_bkts = (__n_elt + __n_ins) 00463 / (long double)_M_max_load_factor; 00464 return std::make_pair(true, 00465 _M_next_bkt(__builtin_floor(__min_bkts) + 1)); 00466 } 00467 else 00468 return std::make_pair(false, 0); 00469 } 00470 00471 // Base classes for std::_Hashtable. We define these base classes 00472 // because in some cases we want to do different things depending on 00473 // the value of a policy class. In some cases the policy class 00474 // affects which member functions and nested typedefs are defined; 00475 // we handle that by specializing base class templates. Several of 00476 // the base class templates need to access other members of class 00477 // template _Hashtable, so we use a variant of the "Curiously 00478 // Recurring Template Pattern" (CRTP) technique. 00479 00480 /** 00481 * Primary class template _Map_base. 00482 * 00483 * If the hashtable has a value type of the form pair<T1, T2> and a 00484 * key extraction policy (_ExtractKey) that returns the first part 00485 * of the pair, the hashtable gets a mapped_type typedef. If it 00486 * satisfies those criteria and also has unique keys, then it also 00487 * gets an operator[]. 00488 */ 00489 template<typename _Key, typename _Value, typename _Alloc, 00490 typename _ExtractKey, typename _Equal, 00491 typename _H1, typename _H2, typename _Hash, 00492 typename _RehashPolicy, typename _Traits, 00493 bool _Unique_keys = _Traits::__unique_keys::value> 00494 struct _Map_base { }; 00495 00496 /// Partial specialization, __unique_keys set to false. 00497 template<typename _Key, typename _Pair, typename _Alloc, typename _Equal, 00498 typename _H1, typename _H2, typename _Hash, 00499 typename _RehashPolicy, typename _Traits> 00500 struct _Map_base<_Key, _Pair, _Alloc, std::_Select1st<_Pair>, _Equal, 00501 _H1, _H2, _Hash, _RehashPolicy, _Traits, false> 00502 { 00503 using mapped_type = typename _Pair::second_type; 00504 }; 00505 00506 /// Partial specialization, __unique_keys set to true. 00507 template<typename _Key, typename _Pair, typename _Alloc, typename _Equal, 00508 typename _H1, typename _H2, typename _Hash, 00509 typename _RehashPolicy, typename _Traits> 00510 struct _Map_base<_Key, _Pair, _Alloc, std::_Select1st<_Pair>, _Equal, 00511 _H1, _H2, _Hash, _RehashPolicy, _Traits, true> 00512 { 00513 private: 00514 using __hashtable_base = __detail::_Hashtable_base<_Key, _Pair, 00515 std::_Select1st<_Pair>, 00516 _Equal, _H1, _H2, _Hash, 00517 _Traits>; 00518 00519 using __hashtable = _Hashtable<_Key, _Pair, _Alloc, 00520 std::_Select1st<_Pair>, _Equal, 00521 _H1, _H2, _Hash, _RehashPolicy, _Traits>; 00522 00523 using __hash_code = typename __hashtable_base::__hash_code; 00524 using __node_type = typename __hashtable_base::__node_type; 00525 00526 public: 00527 using key_type = typename __hashtable_base::key_type; 00528 using iterator = typename __hashtable_base::iterator; 00529 using mapped_type = typename _Pair::second_type; 00530 00531 mapped_type& 00532 operator[](const key_type& __k); 00533 00534 mapped_type& 00535 operator[](key_type&& __k); 00536 00537 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00538 // DR 761. unordered_map needs an at() member function. 00539 mapped_type& 00540 at(const key_type& __k); 00541 00542 const mapped_type& 00543 at(const key_type& __k) const; 00544 }; 00545 00546 template<typename _Key, typename _Pair, typename _Alloc, typename _Equal, 00547 typename _H1, typename _H2, typename _Hash, 00548 typename _RehashPolicy, typename _Traits> 00549 typename _Map_base<_Key, _Pair, _Alloc, std::_Select1st<_Pair>, _Equal, 00550 _H1, _H2, _Hash, _RehashPolicy, _Traits, true> 00551 ::mapped_type& 00552 _Map_base<_Key, _Pair, _Alloc, std::_Select1st<_Pair>, _Equal, 00553 _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: 00554 operator[](const key_type& __k) 00555 { 00556 __hashtable* __h = static_cast<__hashtable*>(this); 00557 __hash_code __code = __h->_M_hash_code(__k); 00558 std::size_t __n = __h->_M_bucket_index(__k, __code); 00559 __node_type* __p = __h->_M_find_node(__n, __k, __code); 00560 00561 if (!__p) 00562 return __h->_M_insert_bucket(std::make_pair(__k, mapped_type()), 00563 __n, __code)->second; 00564 return (__p->_M_v).second; 00565 } 00566 00567 template<typename _Key, typename _Pair, typename _Alloc, typename _Equal, 00568 typename _H1, typename _H2, typename _Hash, 00569 typename _RehashPolicy, typename _Traits> 00570 typename _Map_base<_Key, _Pair, _Alloc, std::_Select1st<_Pair>, _Equal, 00571 _H1, _H2, _Hash, _RehashPolicy, _Traits, true> 00572 ::mapped_type& 00573 _Map_base<_Key, _Pair, _Alloc, std::_Select1st<_Pair>, _Equal, 00574 _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: 00575 operator[](key_type&& __k) 00576 { 00577 __hashtable* __h = static_cast<__hashtable*>(this); 00578 __hash_code __code = __h->_M_hash_code(__k); 00579 std::size_t __n = __h->_M_bucket_index(__k, __code); 00580 __node_type* __p = __h->_M_find_node(__n, __k, __code); 00581 00582 if (!__p) 00583 return __h->_M_insert_bucket(std::make_pair(std::move(__k), 00584 mapped_type()), 00585 __n, __code)->second; 00586 return (__p->_M_v).second; 00587 } 00588 00589 template<typename _Key, typename _Pair, typename _Alloc, typename _Equal, 00590 typename _H1, typename _H2, typename _Hash, 00591 typename _RehashPolicy, typename _Traits> 00592 typename _Map_base<_Key, _Pair, _Alloc, std::_Select1st<_Pair>, _Equal, 00593 _H1, _H2, _Hash, _RehashPolicy, _Traits, true> 00594 ::mapped_type& 00595 _Map_base<_Key, _Pair, _Alloc, std::_Select1st<_Pair>, _Equal, 00596 _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: 00597 at(const key_type& __k) 00598 { 00599 __hashtable* __h = static_cast<__hashtable*>(this); 00600 __hash_code __code = __h->_M_hash_code(__k); 00601 std::size_t __n = __h->_M_bucket_index(__k, __code); 00602 __node_type* __p = __h->_M_find_node(__n, __k, __code); 00603 00604 if (!__p) 00605 __throw_out_of_range(__N("_Map_base::at")); 00606 return (__p->_M_v).second; 00607 } 00608 00609 template<typename _Key, typename _Pair, typename _Alloc, typename _Equal, 00610 typename _H1, typename _H2, typename _Hash, 00611 typename _RehashPolicy, typename _Traits> 00612 const typename _Map_base<_Key, _Pair, _Alloc, std::_Select1st<_Pair>, 00613 _Equal, 00614 _H1, _H2, _Hash, _RehashPolicy, _Traits, true> 00615 ::mapped_type& 00616 _Map_base<_Key, _Pair, _Alloc, std::_Select1st<_Pair>, _Equal, 00617 _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: 00618 at(const key_type& __k) const 00619 { 00620 const __hashtable* __h = static_cast<const __hashtable*>(this); 00621 __hash_code __code = __h->_M_hash_code(__k); 00622 std::size_t __n = __h->_M_bucket_index(__k, __code); 00623 __node_type* __p = __h->_M_find_node(__n, __k, __code); 00624 00625 if (!__p) 00626 __throw_out_of_range(__N("_Map_base::at")); 00627 return (__p->_M_v).second; 00628 } 00629 00630 /** 00631 * Primary class template _Insert_base. 00632 * 00633 * insert member functions appropriate to all _Hashtables. 00634 */ 00635 template<typename _Key, typename _Value, typename _Alloc, 00636 typename _ExtractKey, typename _Equal, 00637 typename _H1, typename _H2, typename _Hash, 00638 typename _RehashPolicy, typename _Traits> 00639 struct _Insert_base 00640 { 00641 using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, 00642 _Equal, _H1, _H2, _Hash, 00643 _RehashPolicy, _Traits>; 00644 00645 using __hashtable_base = _Hashtable_base<_Key, _Value, _ExtractKey, 00646 _Equal, _H1, _H2, _Hash, 00647 _Traits>; 00648 00649 using value_type = typename __hashtable_base::value_type; 00650 using iterator = typename __hashtable_base::iterator; 00651 using const_iterator = typename __hashtable_base::const_iterator; 00652 using size_type = typename __hashtable_base::size_type; 00653 00654 using __unique_keys = typename __hashtable_base::__unique_keys; 00655 using __ireturn_type = typename __hashtable_base::__ireturn_type; 00656 using __iconv_type = typename __hashtable_base::__iconv_type; 00657 00658 __hashtable& 00659 _M_conjure_hashtable() 00660 { return *(static_cast<__hashtable*>(this)); } 00661 00662 __ireturn_type 00663 insert(const value_type& __v) 00664 { 00665 __hashtable& __h = _M_conjure_hashtable(); 00666 return __h._M_insert(__v, __unique_keys()); 00667 } 00668 00669 iterator 00670 insert(const_iterator, const value_type& __v) 00671 { return __iconv_type()(insert(__v)); } 00672 00673 void 00674 insert(initializer_list<value_type> __l) 00675 { this->insert(__l.begin(), __l.end()); } 00676 00677 template<typename _InputIterator> 00678 void 00679 insert(_InputIterator __first, _InputIterator __last); 00680 }; 00681 00682 template<typename _Key, typename _Value, typename _Alloc, 00683 typename _ExtractKey, typename _Equal, 00684 typename _H1, typename _H2, typename _Hash, 00685 typename _RehashPolicy, typename _Traits> 00686 template<typename _InputIterator> 00687 void 00688 _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, 00689 _RehashPolicy, _Traits>:: 00690 insert(_InputIterator __first, _InputIterator __last) 00691 { 00692 using __rehash_type = typename __hashtable::__rehash_type; 00693 using __rehash_state = typename __hashtable::__rehash_state; 00694 using pair_type = std::pair<bool, std::size_t>; 00695 00696 size_type __n_elt = __detail::__distance_fw(__first, __last); 00697 00698 __hashtable& __h = _M_conjure_hashtable(); 00699 __rehash_type& __rehash = __h._M_rehash_policy; 00700 const __rehash_state& __saved_state = __rehash._M_state(); 00701 pair_type __do_rehash = __rehash._M_need_rehash(__h._M_bucket_count, 00702 __h._M_element_count, 00703 __n_elt); 00704 00705 if (__do_rehash.first) 00706 __h._M_rehash(__do_rehash.second, __saved_state); 00707 00708 for (; __first != __last; ++__first) 00709 this->insert(*__first); 00710 } 00711 00712 /** 00713 * Primary class template _Insert. 00714 * 00715 * Select insert member functions appropriate to _Hashtable policy choices. 00716 */ 00717 template<typename _Key, typename _Value, typename _Alloc, 00718 typename _ExtractKey, typename _Equal, 00719 typename _H1, typename _H2, typename _Hash, 00720 typename _RehashPolicy, typename _Traits, 00721 bool _Constant_iterators = _Traits::__constant_iterators::value, 00722 bool _Unique_keys = _Traits::__unique_keys::value> 00723 struct _Insert; 00724 00725 /// Specialization. 00726 template<typename _Key, typename _Value, typename _Alloc, 00727 typename _ExtractKey, typename _Equal, 00728 typename _H1, typename _H2, typename _Hash, 00729 typename _RehashPolicy, typename _Traits> 00730 struct _Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, 00731 _RehashPolicy, _Traits, true, true> 00732 : public _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, 00733 _H1, _H2, _Hash, _RehashPolicy, _Traits> 00734 { 00735 using __base_type = _Insert_base<_Key, _Value, _Alloc, _ExtractKey, 00736 _Equal, _H1, _H2, _Hash, 00737 _RehashPolicy, _Traits>; 00738 using value_type = typename __base_type::value_type; 00739 using iterator = typename __base_type::iterator; 00740 using const_iterator = typename __base_type::const_iterator; 00741 00742 using __unique_keys = typename __base_type::__unique_keys; 00743 using __hashtable = typename __base_type::__hashtable; 00744 00745 using __base_type::insert; 00746 00747 std::pair<iterator, bool> 00748 insert(value_type&& __v) 00749 { 00750 __hashtable& __h = this->_M_conjure_hashtable(); 00751 return __h._M_insert(std::move(__v), __unique_keys()); 00752 } 00753 00754 iterator 00755 insert(const_iterator, value_type&& __v) 00756 { return insert(std::move(__v)).first; } 00757 }; 00758 00759 /// Specialization. 00760 template<typename _Key, typename _Value, typename _Alloc, 00761 typename _ExtractKey, typename _Equal, 00762 typename _H1, typename _H2, typename _Hash, 00763 typename _RehashPolicy, typename _Traits> 00764 struct _Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, 00765 _RehashPolicy, _Traits, true, false> 00766 : public _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, 00767 _H1, _H2, _Hash, _RehashPolicy, _Traits> 00768 { 00769 using __base_type = _Insert_base<_Key, _Value, _Alloc, _ExtractKey, 00770 _Equal, _H1, _H2, _Hash, 00771 _RehashPolicy, _Traits>; 00772 using value_type = typename __base_type::value_type; 00773 using iterator = typename __base_type::iterator; 00774 using const_iterator = typename __base_type::const_iterator; 00775 00776 using __unique_keys = typename __base_type::__unique_keys; 00777 using __hashtable = typename __base_type::__hashtable; 00778 00779 using __base_type::insert; 00780 00781 iterator 00782 insert(value_type&& __v) 00783 { 00784 __hashtable& __h = this->_M_conjure_hashtable(); 00785 return __h._M_insert(std::move(__v), __unique_keys()); 00786 } 00787 00788 iterator 00789 insert(const_iterator, value_type&& __v) 00790 { return insert(std::move(__v)); } 00791 }; 00792 00793 /// Specialization. 00794 template<typename _Key, typename _Value, typename _Alloc, 00795 typename _ExtractKey, typename _Equal, 00796 typename _H1, typename _H2, typename _Hash, 00797 typename _RehashPolicy, typename _Traits, bool _Unique_keys> 00798 struct _Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, 00799 _RehashPolicy, _Traits, false, _Unique_keys> 00800 : public _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, 00801 _H1, _H2, _Hash, _RehashPolicy, _Traits> 00802 { 00803 using __base_type = _Insert_base<_Key, _Value, _Alloc, _ExtractKey, 00804 _Equal, _H1, _H2, _Hash, 00805 _RehashPolicy, _Traits>; 00806 using value_type = typename __base_type::value_type; 00807 using iterator = typename __base_type::iterator; 00808 using const_iterator = typename __base_type::const_iterator; 00809 00810 using __unique_keys = typename __base_type::__unique_keys; 00811 using __hashtable = typename __base_type::__hashtable; 00812 using __ireturn_type = typename __base_type::__ireturn_type; 00813 using __iconv_type = typename __base_type::__iconv_type; 00814 00815 using __base_type::insert; 00816 00817 template<typename _Pair> 00818 using __is_convertible = std::is_convertible<_Pair, value_type>; 00819 00820 template<typename _Pair> 00821 using _IFconv = std::enable_if<__is_convertible<_Pair>::value>; 00822 00823 template<typename _Pair> 00824 using _IFconvp = typename _IFconv<_Pair>::type; 00825 00826 template<typename _Pair, typename = _IFconvp<_Pair>> 00827 __ireturn_type 00828 insert(_Pair&& __v) 00829 { 00830 __hashtable& __h = this->_M_conjure_hashtable(); 00831 return __h._M_insert(std::forward<_Pair>(__v), __unique_keys()); 00832 } 00833 00834 template<typename _Pair, typename = _IFconvp<_Pair>> 00835 iterator 00836 insert(const_iterator, _Pair&& __v) 00837 { return __iconv_type()(insert(std::forward<_Pair>(__v))); } 00838 }; 00839 00840 /** 00841 * Primary class template _Rehash_base. 00842 * 00843 * Give hashtable the max_load_factor functions and reserve iff the 00844 * rehash policy is _Prime_rehash_policy. 00845 */ 00846 template<typename _Key, typename _Value, typename _Alloc, 00847 typename _ExtractKey, typename _Equal, 00848 typename _H1, typename _H2, typename _Hash, 00849 typename _RehashPolicy, typename _Traits> 00850 struct _Rehash_base; 00851 00852 /// Specialization. 00853 template<typename _Key, typename _Value, typename _Alloc, 00854 typename _ExtractKey, typename _Equal, 00855 typename _H1, typename _H2, typename _Hash, typename _Traits> 00856 struct _Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, 00857 _H1, _H2, _Hash, _Prime_rehash_policy, _Traits> 00858 { 00859 using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, 00860 _Equal, _H1, _H2, _Hash, 00861 _Prime_rehash_policy, _Traits>; 00862 00863 float 00864 max_load_factor() const noexcept 00865 { 00866 const __hashtable* __this = static_cast<const __hashtable*>(this); 00867 return __this->__rehash_policy().max_load_factor(); 00868 } 00869 00870 void 00871 max_load_factor(float __z) 00872 { 00873 __hashtable* __this = static_cast<__hashtable*>(this); 00874 __this->__rehash_policy(_Prime_rehash_policy(__z)); 00875 } 00876 00877 void 00878 reserve(std::size_t __n) 00879 { 00880 __hashtable* __this = static_cast<__hashtable*>(this); 00881 __this->rehash(__builtin_ceil(__n / max_load_factor())); 00882 } 00883 }; 00884 00885 /** 00886 * Primary class template _Hashtable_ebo_helper. 00887 * 00888 * Helper class using EBO when it is not forbidden, type is not 00889 * final, and when it worth it, type is empty. 00890 */ 00891 template<int _Nm, typename _Tp, 00892 bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)> 00893 struct _Hashtable_ebo_helper; 00894 00895 /// Specialization using EBO. 00896 template<int _Nm, typename _Tp> 00897 struct _Hashtable_ebo_helper<_Nm, _Tp, true> 00898 // See PR53067. 00899 : public _Tp 00900 { 00901 _Hashtable_ebo_helper() = default; 00902 00903 _Hashtable_ebo_helper(const _Tp& __tp) : _Tp(__tp) 00904 { } 00905 00906 static const _Tp& 00907 _S_cget(const _Hashtable_ebo_helper& __eboh) 00908 { return static_cast<const _Tp&>(__eboh); } 00909 00910 static _Tp& 00911 _S_get(_Hashtable_ebo_helper& __eboh) 00912 { return static_cast<_Tp&>(__eboh); } 00913 }; 00914 00915 /// Specialization not using EBO. 00916 template<int _Nm, typename _Tp> 00917 struct _Hashtable_ebo_helper<_Nm, _Tp, false> 00918 { 00919 _Hashtable_ebo_helper() = default; 00920 00921 _Hashtable_ebo_helper(const _Tp& __tp) : _M_tp(__tp) 00922 { } 00923 00924 static const _Tp& 00925 _S_cget(const _Hashtable_ebo_helper& __eboh) 00926 { return __eboh._M_tp; } 00927 00928 static _Tp& 00929 _S_get(_Hashtable_ebo_helper& __eboh) 00930 { return __eboh._M_tp; } 00931 00932 private: 00933 _Tp _M_tp; 00934 }; 00935 00936 /** 00937 * Primary class template _Hash_code_base. 00938 * 00939 * Encapsulates two policy issues that aren't quite orthogonal. 00940 * (1) the difference between using a ranged hash function and using 00941 * the combination of a hash function and a range-hashing function. 00942 * In the former case we don't have such things as hash codes, so 00943 * we have a dummy type as placeholder. 00944 * (2) Whether or not we cache hash codes. Caching hash codes is 00945 * meaningless if we have a ranged hash function. 00946 * 00947 * We also put the key extraction objects here, for convenience. 00948 * Each specialization derives from one or more of the template 00949 * parameters to benefit from Ebo. This is important as this type 00950 * is inherited in some cases by the _Local_iterator_base type used 00951 * to implement local_iterator and const_local_iterator. As with 00952 * any iterator type we prefer to make it as small as possible. 00953 * 00954 * Primary template is unused except as a hook for specializations. 00955 */ 00956 template<typename _Key, typename _Value, typename _ExtractKey, 00957 typename _H1, typename _H2, typename _Hash, 00958 bool __cache_hash_code> 00959 struct _Hash_code_base; 00960 00961 /// Specialization: ranged hash function, no caching hash codes. H1 00962 /// and H2 are provided but ignored. We define a dummy hash code type. 00963 template<typename _Key, typename _Value, typename _ExtractKey, 00964 typename _H1, typename _H2, typename _Hash> 00965 struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, false> 00966 // See PR53067. 00967 : public _Hashtable_ebo_helper<0, _ExtractKey>, 00968 public _Hashtable_ebo_helper<1, _Hash> 00969 { 00970 private: 00971 typedef _Hashtable_ebo_helper<0, _ExtractKey> _EboExtractKey; 00972 typedef _Hashtable_ebo_helper<1, _Hash> _EboHash; 00973 00974 protected: 00975 typedef void* __hash_code; 00976 typedef _Hash_node<_Value, false> __node_type; 00977 00978 // We need the default constructor for the local iterators. 00979 _Hash_code_base() = default; 00980 00981 _Hash_code_base(const _ExtractKey& __ex, const _H1&, const _H2&, 00982 const _Hash& __h) 00983 : _EboExtractKey(__ex), _EboHash(__h) { } 00984 00985 __hash_code 00986 _M_hash_code(const _Key& __key) const 00987 { return 0; } 00988 00989 std::size_t 00990 _M_bucket_index(const _Key& __k, __hash_code, std::size_t __n) const 00991 { return _M_ranged_hash()(__k, __n); } 00992 00993 std::size_t 00994 _M_bucket_index(const __node_type* __p, std::size_t __n) const 00995 { return _M_ranged_hash()(_M_extract()(__p->_M_v), __n); } 00996 00997 void 00998 _M_store_code(__node_type*, __hash_code) const 00999 { } 01000 01001 void 01002 _M_copy_code(__node_type*, const __node_type*) const 01003 { } 01004 01005 void 01006 _M_swap(_Hash_code_base& __x) 01007 { 01008 std::swap(_M_extract(), __x._M_extract()); 01009 std::swap(_M_ranged_hash(), __x._M_ranged_hash()); 01010 } 01011 01012 protected: 01013 const _ExtractKey& 01014 _M_extract() const { return _EboExtractKey::_S_cget(*this); } 01015 01016 _ExtractKey& 01017 _M_extract() { return _EboExtractKey::_S_get(*this); } 01018 01019 const _Hash& 01020 _M_ranged_hash() const { return _EboHash::_S_cget(*this); } 01021 01022 _Hash& 01023 _M_ranged_hash() { return _EboHash::_S_get(*this); } 01024 }; 01025 01026 // No specialization for ranged hash function while caching hash codes. 01027 // That combination is meaningless, and trying to do it is an error. 01028 01029 /// Specialization: ranged hash function, cache hash codes. This 01030 /// combination is meaningless, so we provide only a declaration 01031 /// and no definition. 01032 template<typename _Key, typename _Value, typename _ExtractKey, 01033 typename _H1, typename _H2, typename _Hash> 01034 struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, true>; 01035 01036 /// Specialization: hash function and range-hashing function, no 01037 /// caching of hash codes. 01038 /// Provides typedef and accessor required by TR1. 01039 template<typename _Key, typename _Value, typename _ExtractKey, 01040 typename _H1, typename _H2> 01041 struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, 01042 _Default_ranged_hash, false> 01043 // See PR53067. 01044 : public _Hashtable_ebo_helper<0, _ExtractKey>, 01045 public _Hashtable_ebo_helper<1, _H1>, 01046 public _Hashtable_ebo_helper<2, _H2> 01047 { 01048 private: 01049 typedef _Hashtable_ebo_helper<0, _ExtractKey> _EboExtractKey; 01050 typedef _Hashtable_ebo_helper<1, _H1> _EboH1; 01051 typedef _Hashtable_ebo_helper<2, _H2> _EboH2; 01052 01053 public: 01054 typedef _H1 hasher; 01055 01056 hasher 01057 hash_function() const 01058 { return _M_h1(); } 01059 01060 typedef std::size_t __hash_code; 01061 typedef _Hash_node<_Value, false> __node_type; 01062 01063 protected: 01064 // We need the default constructor for the local iterators. 01065 _Hash_code_base() = default; 01066 01067 _Hash_code_base(const _ExtractKey& __ex, 01068 const _H1& __h1, const _H2& __h2, 01069 const _Default_ranged_hash&) 01070 : _EboExtractKey(__ex), _EboH1(__h1), _EboH2(__h2) { } 01071 01072 __hash_code 01073 _M_hash_code(const _Key& __k) const 01074 { return _M_h1()(__k); } 01075 01076 std::size_t 01077 _M_bucket_index(const _Key&, __hash_code __c, std::size_t __n) const 01078 { return _M_h2()(__c, __n); } 01079 01080 std::size_t 01081 _M_bucket_index(const __node_type* __p, 01082 std::size_t __n) const 01083 { return _M_h2()(_M_h1()(_M_extract()(__p->_M_v)), __n); } 01084 01085 void 01086 _M_store_code(__node_type*, __hash_code) const 01087 { } 01088 01089 void 01090 _M_copy_code(__node_type*, const __node_type*) const 01091 { } 01092 01093 void 01094 _M_swap(_Hash_code_base& __x) 01095 { 01096 std::swap(_M_extract(), __x._M_extract()); 01097 std::swap(_M_h1(), __x._M_h1()); 01098 std::swap(_M_h2(), __x._M_h2()); 01099 } 01100 01101 const _ExtractKey& 01102 _M_extract() const { return _EboExtractKey::_S_cget(*this); } 01103 01104 _ExtractKey& 01105 _M_extract() { return _EboExtractKey::_S_get(*this); } 01106 01107 const _H1& 01108 _M_h1() const { return _EboH1::_S_cget(*this); } 01109 01110 _H1& 01111 _M_h1() { return _EboH1::_S_get(*this); } 01112 01113 const _H2& 01114 _M_h2() const { return _EboH2::_S_cget(*this); } 01115 01116 _H2& 01117 _M_h2() { return _EboH2::_S_get(*this); } 01118 }; 01119 01120 /// Specialization: hash function and range-hashing function, 01121 /// caching hash codes. H is provided but ignored. Provides 01122 /// typedef and accessor required by TR1. 01123 template<typename _Key, typename _Value, typename _ExtractKey, 01124 typename _H1, typename _H2> 01125 struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, 01126 _Default_ranged_hash, true> 01127 // See PR53067. 01128 : public _Hashtable_ebo_helper<0, _ExtractKey>, 01129 public _Hashtable_ebo_helper<1, _H1>, 01130 public _Hashtable_ebo_helper<2, _H2> 01131 { 01132 private: 01133 typedef _Hashtable_ebo_helper<0, _ExtractKey> _EboExtractKey; 01134 typedef _Hashtable_ebo_helper<1, _H1> _EboH1; 01135 typedef _Hashtable_ebo_helper<2, _H2> _EboH2; 01136 01137 public: 01138 typedef _H1 hasher; 01139 01140 hasher 01141 hash_function() const 01142 { return _M_h1(); } 01143 01144 typedef std::size_t __hash_code; 01145 typedef _Hash_node<_Value, true> __node_type; 01146 01147 protected: 01148 _Hash_code_base(const _ExtractKey& __ex, 01149 const _H1& __h1, const _H2& __h2, 01150 const _Default_ranged_hash&) 01151 : _EboExtractKey(__ex), _EboH1(__h1), _EboH2(__h2) { } 01152 01153 __hash_code 01154 _M_hash_code(const _Key& __k) const 01155 { return _M_h1()(__k); } 01156 01157 std::size_t 01158 _M_bucket_index(const _Key&, __hash_code __c, 01159 std::size_t __n) const 01160 { return _M_h2()(__c, __n); } 01161 01162 std::size_t 01163 _M_bucket_index(const __node_type* __p, std::size_t __n) const 01164 { return _M_h2()(__p->_M_hash_code, __n); } 01165 01166 void 01167 _M_store_code(__node_type* __n, __hash_code __c) const 01168 { __n->_M_hash_code = __c; } 01169 01170 void 01171 _M_copy_code(__node_type* __to, const __node_type* __from) const 01172 { __to->_M_hash_code = __from->_M_hash_code; } 01173 01174 void 01175 _M_swap(_Hash_code_base& __x) 01176 { 01177 std::swap(_M_extract(), __x._M_extract()); 01178 std::swap(_M_h1(), __x._M_h1()); 01179 std::swap(_M_h2(), __x._M_h2()); 01180 } 01181 01182 const _ExtractKey& 01183 _M_extract() const { return _EboExtractKey::_S_cget(*this); } 01184 01185 _ExtractKey& 01186 _M_extract() { return _EboExtractKey::_S_get(*this); } 01187 01188 const _H1& 01189 _M_h1() const { return _EboH1::_S_cget(*this); } 01190 01191 _H1& 01192 _M_h1() { return _EboH1::_S_get(*this); } 01193 01194 const _H2& 01195 _M_h2() const { return _EboH2::_S_cget(*this); } 01196 01197 _H2& 01198 _M_h2() { return _EboH2::_S_get(*this); } 01199 }; 01200 01201 /** 01202 * Primary class template _Equal_helper. 01203 * 01204 */ 01205 template <typename _Key, typename _Value, typename _ExtractKey, 01206 typename _Equal, typename _HashCodeType, 01207 bool __cache_hash_code> 01208 struct _Equal_helper; 01209 01210 /// Specialization. 01211 template<typename _Key, typename _Value, typename _ExtractKey, 01212 typename _Equal, typename _HashCodeType> 01213 struct _Equal_helper<_Key, _Value, _ExtractKey, _Equal, _HashCodeType, true> 01214 { 01215 static bool 01216 _S_equals(const _Equal& __eq, const _ExtractKey& __extract, 01217 const _Key& __k, _HashCodeType __c, _Hash_node<_Value, true>* __n) 01218 { return __c == __n->_M_hash_code && __eq(__k, __extract(__n->_M_v)); } 01219 }; 01220 01221 /// Specialization. 01222 template<typename _Key, typename _Value, typename _ExtractKey, 01223 typename _Equal, typename _HashCodeType> 01224 struct _Equal_helper<_Key, _Value, _ExtractKey, _Equal, _HashCodeType, false> 01225 { 01226 static bool 01227 _S_equals(const _Equal& __eq, const _ExtractKey& __extract, 01228 const _Key& __k, _HashCodeType, _Hash_node<_Value, false>* __n) 01229 { return __eq(__k, __extract(__n->_M_v)); } 01230 }; 01231 01232 01233 /** 01234 * Primary class template _Local_iterator_base. 01235 * 01236 * Base class for local iterators, used to iterate within a bucket 01237 * but not between buckets. 01238 */ 01239 template<typename _Key, typename _Value, typename _ExtractKey, 01240 typename _H1, typename _H2, typename _Hash, 01241 bool __cache_hash_code> 01242 struct _Local_iterator_base; 01243 01244 /// Specialization. 01245 template<typename _Key, typename _Value, typename _ExtractKey, 01246 typename _H1, typename _H2, typename _Hash> 01247 struct _Local_iterator_base<_Key, _Value, _ExtractKey, 01248 _H1, _H2, _Hash, true> 01249 // See PR53067. 01250 : public _H2 01251 { 01252 _Local_iterator_base() = default; 01253 _Local_iterator_base(_Hash_node<_Value, true>* __p, 01254 std::size_t __bkt, std::size_t __bkt_count) 01255 : _M_cur(__p), _M_bucket(__bkt), _M_bucket_count(__bkt_count) { } 01256 01257 void 01258 _M_incr() 01259 { 01260 _M_cur = _M_cur->_M_next(); 01261 if (_M_cur) 01262 { 01263 std::size_t __bkt = _M_h2()(_M_cur->_M_hash_code, _M_bucket_count); 01264 if (__bkt != _M_bucket) 01265 _M_cur = nullptr; 01266 } 01267 } 01268 01269 const _H2& _M_h2() const 01270 { return *this; } 01271 01272 _Hash_node<_Value, true>* _M_cur; 01273 std::size_t _M_bucket; 01274 std::size_t _M_bucket_count; 01275 }; 01276 01277 /// Specialization. 01278 template<typename _Key, typename _Value, typename _ExtractKey, 01279 typename _H1, typename _H2, typename _Hash> 01280 struct _Local_iterator_base<_Key, _Value, _ExtractKey, 01281 _H1, _H2, _Hash, false> 01282 // See PR53067. 01283 : public _Hash_code_base<_Key, _Value, _ExtractKey, 01284 _H1, _H2, _Hash, false> 01285 { 01286 _Local_iterator_base() = default; 01287 _Local_iterator_base(_Hash_node<_Value, false>* __p, 01288 std::size_t __bkt, std::size_t __bkt_count) 01289 : _M_cur(__p), _M_bucket(__bkt), _M_bucket_count(__bkt_count) { } 01290 01291 void 01292 _M_incr() 01293 { 01294 _M_cur = _M_cur->_M_next(); 01295 if (_M_cur) 01296 { 01297 std::size_t __bkt = this->_M_bucket_index(_M_cur, _M_bucket_count); 01298 if (__bkt != _M_bucket) 01299 _M_cur = nullptr; 01300 } 01301 } 01302 01303 _Hash_node<_Value, false>* _M_cur; 01304 std::size_t _M_bucket; 01305 std::size_t _M_bucket_count; 01306 }; 01307 01308 template<typename _Key, typename _Value, typename _ExtractKey, 01309 typename _H1, typename _H2, typename _Hash, bool __cache> 01310 inline bool 01311 operator==(const _Local_iterator_base<_Key, _Value, _ExtractKey, 01312 _H1, _H2, _Hash, __cache>& __x, 01313 const _Local_iterator_base<_Key, _Value, _ExtractKey, 01314 _H1, _H2, _Hash, __cache>& __y) 01315 { return __x._M_cur == __y._M_cur; } 01316 01317 template<typename _Key, typename _Value, typename _ExtractKey, 01318 typename _H1, typename _H2, typename _Hash, bool __cache> 01319 inline bool 01320 operator!=(const _Local_iterator_base<_Key, _Value, _ExtractKey, 01321 _H1, _H2, _Hash, __cache>& __x, 01322 const _Local_iterator_base<_Key, _Value, _ExtractKey, 01323 _H1, _H2, _Hash, __cache>& __y) 01324 { return __x._M_cur != __y._M_cur; } 01325 01326 /// local iterators 01327 template<typename _Key, typename _Value, typename _ExtractKey, 01328 typename _H1, typename _H2, typename _Hash, 01329 bool __constant_iterators, bool __cache> 01330 struct _Local_iterator 01331 : public _Local_iterator_base<_Key, _Value, _ExtractKey, 01332 _H1, _H2, _Hash, __cache> 01333 { 01334 typedef _Value value_type; 01335 typedef typename std::conditional<__constant_iterators, 01336 const _Value*, _Value*>::type 01337 pointer; 01338 typedef typename std::conditional<__constant_iterators, 01339 const _Value&, _Value&>::type 01340 reference; 01341 typedef std::ptrdiff_t difference_type; 01342 typedef std::forward_iterator_tag iterator_category; 01343 01344 _Local_iterator() = default; 01345 01346 explicit 01347 _Local_iterator(_Hash_node<_Value, __cache>* __p, 01348 std::size_t __bkt, std::size_t __bkt_count) 01349 : _Local_iterator_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, 01350 __cache>(__p, __bkt, __bkt_count) 01351 { } 01352 01353 reference 01354 operator*() const 01355 { return this->_M_cur->_M_v; } 01356 01357 pointer 01358 operator->() const 01359 { return std::__addressof(this->_M_cur->_M_v); } 01360 01361 _Local_iterator& 01362 operator++() 01363 { 01364 this->_M_incr(); 01365 return *this; 01366 } 01367 01368 _Local_iterator 01369 operator++(int) 01370 { 01371 _Local_iterator __tmp(*this); 01372 this->_M_incr(); 01373 return __tmp; 01374 } 01375 }; 01376 01377 /// local const_iterators 01378 template<typename _Key, typename _Value, typename _ExtractKey, 01379 typename _H1, typename _H2, typename _Hash, 01380 bool __constant_iterators, bool __cache> 01381 struct _Local_const_iterator 01382 : public _Local_iterator_base<_Key, _Value, _ExtractKey, 01383 _H1, _H2, _Hash, __cache> 01384 { 01385 typedef _Value value_type; 01386 typedef const _Value* pointer; 01387 typedef const _Value& reference; 01388 typedef std::ptrdiff_t difference_type; 01389 typedef std::forward_iterator_tag iterator_category; 01390 01391 _Local_const_iterator() = default; 01392 01393 explicit 01394 _Local_const_iterator(_Hash_node<_Value, __cache>* __p, 01395 std::size_t __bkt, std::size_t __bkt_count) 01396 : _Local_iterator_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, 01397 __cache>(__p, __bkt, __bkt_count) 01398 { } 01399 01400 _Local_const_iterator(const _Local_iterator<_Key, _Value, _ExtractKey, 01401 _H1, _H2, _Hash, 01402 __constant_iterators, 01403 __cache>& __x) 01404 : _Local_iterator_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, 01405 __cache>(__x._M_cur, __x._M_bucket, 01406 __x._M_bucket_count) 01407 { } 01408 01409 reference 01410 operator*() const 01411 { return this->_M_cur->_M_v; } 01412 01413 pointer 01414 operator->() const 01415 { return std::__addressof(this->_M_cur->_M_v); } 01416 01417 _Local_const_iterator& 01418 operator++() 01419 { 01420 this->_M_incr(); 01421 return *this; 01422 } 01423 01424 _Local_const_iterator 01425 operator++(int) 01426 { 01427 _Local_const_iterator __tmp(*this); 01428 this->_M_incr(); 01429 return __tmp; 01430 } 01431 }; 01432 01433 /** 01434 * Primary class template _Hashtable_base. 01435 * 01436 * Helper class adding management of _Equal functor to 01437 * _Hash_code_base type. 01438 * 01439 * Base class templates are: 01440 * - __detail::_Hash_code_base 01441 * - __detail::_Hashtable_ebo_helper 01442 */ 01443 template<typename _Key, typename _Value, 01444 typename _ExtractKey, typename _Equal, 01445 typename _H1, typename _H2, typename _Hash, typename _Traits> 01446 struct _Hashtable_base 01447 // See PR53067. 01448 : public _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, 01449 _Traits::__hash_cached::value>, 01450 public _Hashtable_ebo_helper<0, _Equal> 01451 { 01452 public: 01453 typedef _Key key_type; 01454 typedef _Value value_type; 01455 typedef _Equal key_equal; 01456 typedef std::size_t size_type; 01457 typedef std::ptrdiff_t difference_type; 01458 01459 using __traits_type = _Traits; 01460 using __hash_cached = typename __traits_type::__hash_cached; 01461 using __constant_iterators = typename __traits_type::__constant_iterators; 01462 using __unique_keys = typename __traits_type::__unique_keys; 01463 01464 using __hash_code_base = _Hash_code_base<_Key, _Value, _ExtractKey, 01465 _H1, _H2, _Hash, 01466 __hash_cached::value>; 01467 01468 using __hash_code = typename __hash_code_base::__hash_code; 01469 using __node_type = typename __hash_code_base::__node_type; 01470 01471 using iterator = __detail::_Node_iterator<value_type, 01472 __constant_iterators::value, 01473 __hash_cached::value>; 01474 01475 using const_iterator = __detail::_Node_const_iterator<value_type, 01476 __constant_iterators::value, 01477 __hash_cached::value>; 01478 01479 using local_iterator = __detail::_Local_iterator<key_type, value_type, 01480 _ExtractKey, _H1, _H2, _Hash, 01481 __constant_iterators::value, 01482 __hash_cached::value>; 01483 01484 using const_local_iterator = __detail::_Local_const_iterator<key_type, 01485 value_type, 01486 _ExtractKey, _H1, _H2, _Hash, 01487 __constant_iterators::value, 01488 __hash_cached::value>; 01489 01490 using __ireturn_type = typename std::conditional<__unique_keys::value, 01491 std::pair<iterator, bool>, 01492 iterator>::type; 01493 01494 using __iconv_type = typename std::conditional<__unique_keys::value, 01495 std::_Select1st<__ireturn_type>, 01496 std::_Identity<__ireturn_type> 01497 >::type; 01498 private: 01499 using _EqualEBO = _Hashtable_ebo_helper<0, _Equal>; 01500 using _EqualHelper = _Equal_helper<_Key, _Value, _ExtractKey, _Equal, 01501 __hash_code, __hash_cached::value>; 01502 01503 protected: 01504 using __node_base = __detail::_Hash_node_base; 01505 using __bucket_type = __node_base*; 01506 01507 _Hashtable_base(const _ExtractKey& __ex, const _H1& __h1, const _H2& __h2, 01508 const _Hash& __hash, const _Equal& __eq) 01509 : __hash_code_base(__ex, __h1, __h2, __hash), _EqualEBO(__eq) 01510 { } 01511 01512 bool 01513 _M_equals(const _Key& __k, __hash_code __c, __node_type* __n) const 01514 { 01515 return _EqualHelper::_S_equals(_M_eq(), this->_M_extract(), 01516 __k, __c, __n); 01517 } 01518 01519 void 01520 _M_swap(_Hashtable_base& __x) 01521 { 01522 __hash_code_base::_M_swap(__x); 01523 std::swap(_M_eq(), __x._M_eq()); 01524 } 01525 01526 const _Equal& 01527 _M_eq() const { return _EqualEBO::_S_cget(*this); } 01528 01529 _Equal& 01530 _M_eq() { return _EqualEBO::_S_get(*this); } 01531 }; 01532 01533 /** 01534 * struct _Equality_base. 01535 * 01536 * Common types and functions for class _Equality. 01537 */ 01538 struct _Equality_base 01539 { 01540 protected: 01541 template<typename _Uiterator> 01542 static bool 01543 _S_is_permutation(_Uiterator, _Uiterator, _Uiterator); 01544 }; 01545 01546 // See std::is_permutation in N3068. 01547 template<typename _Uiterator> 01548 bool 01549 _Equality_base:: 01550 _S_is_permutation(_Uiterator __first1, _Uiterator __last1, 01551 _Uiterator __first2) 01552 { 01553 for (; __first1 != __last1; ++__first1, ++__first2) 01554 if (!(*__first1 == *__first2)) 01555 break; 01556 01557 if (__first1 == __last1) 01558 return true; 01559 01560 _Uiterator __last2 = __first2; 01561 std::advance(__last2, std::distance(__first1, __last1)); 01562 01563 for (_Uiterator __it1 = __first1; __it1 != __last1; ++__it1) 01564 { 01565 _Uiterator __tmp = __first1; 01566 while (__tmp != __it1 && !bool(*__tmp == *__it1)) 01567 ++__tmp; 01568 01569 // We've seen this one before. 01570 if (__tmp != __it1) 01571 continue; 01572 01573 std::ptrdiff_t __n2 = 0; 01574 for (__tmp = __first2; __tmp != __last2; ++__tmp) 01575 if (*__tmp == *__it1) 01576 ++__n2; 01577 01578 if (!__n2) 01579 return false; 01580 01581 std::ptrdiff_t __n1 = 0; 01582 for (__tmp = __it1; __tmp != __last1; ++__tmp) 01583 if (*__tmp == *__it1) 01584 ++__n1; 01585 01586 if (__n1 != __n2) 01587 return false; 01588 } 01589 return true; 01590 } 01591 01592 /** 01593 * Primary class template _Equality. 01594 * 01595 * This is for implementing equality comparison for unordered 01596 * containers, per N3068, by John Lakos and Pablo Halpern. 01597 * Algorithmically, we follow closely the reference implementations 01598 * therein. 01599 */ 01600 template<typename _Key, typename _Value, typename _Alloc, 01601 typename _ExtractKey, typename _Equal, 01602 typename _H1, typename _H2, typename _Hash, 01603 typename _RehashPolicy, typename _Traits, 01604 bool _Unique_keys = _Traits::__unique_keys::value> 01605 struct _Equality; 01606 01607 /// Specialization. 01608 template<typename _Key, typename _Value, typename _Alloc, 01609 typename _ExtractKey, typename _Equal, 01610 typename _H1, typename _H2, typename _Hash, 01611 typename _RehashPolicy, typename _Traits> 01612 struct _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, 01613 _H1, _H2, _Hash, _RehashPolicy, _Traits, true> 01614 { 01615 using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, 01616 _H1, _H2, _Hash, _RehashPolicy, _Traits>; 01617 01618 bool 01619 _M_equal(const __hashtable&) const; 01620 }; 01621 01622 template<typename _Key, typename _Value, typename _Alloc, 01623 typename _ExtractKey, typename _Equal, 01624 typename _H1, typename _H2, typename _Hash, 01625 typename _RehashPolicy, typename _Traits> 01626 bool 01627 _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, 01628 _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: 01629 _M_equal(const __hashtable& __other) const 01630 { 01631 const __hashtable* __this = static_cast<const __hashtable*>(this); 01632 01633 if (__this->size() != __other.size()) 01634 return false; 01635 01636 for (auto __itx = __this->begin(); __itx != __this->end(); ++__itx) 01637 { 01638 const auto __ity = __other.find(_ExtractKey()(*__itx)); 01639 if (__ity == __other.end() || !bool(*__ity == *__itx)) 01640 return false; 01641 } 01642 return true; 01643 } 01644 01645 /// Specialization. 01646 template<typename _Key, typename _Value, typename _Alloc, 01647 typename _ExtractKey, typename _Equal, 01648 typename _H1, typename _H2, typename _Hash, 01649 typename _RehashPolicy, typename _Traits> 01650 struct _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, 01651 _H1, _H2, _Hash, _RehashPolicy, _Traits, false> 01652 : public _Equality_base 01653 { 01654 using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, 01655 _H1, _H2, _Hash, _RehashPolicy, _Traits>; 01656 01657 bool 01658 _M_equal(const __hashtable&) const; 01659 }; 01660 01661 template<typename _Key, typename _Value, typename _Alloc, 01662 typename _ExtractKey, typename _Equal, 01663 typename _H1, typename _H2, typename _Hash, 01664 typename _RehashPolicy, typename _Traits> 01665 bool 01666 _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, 01667 _H1, _H2, _Hash, _RehashPolicy, _Traits, false>:: 01668 _M_equal(const __hashtable& __other) const 01669 { 01670 const __hashtable* __this = static_cast<const __hashtable*>(this); 01671 01672 if (__this->size() != __other.size()) 01673 return false; 01674 01675 for (auto __itx = __this->begin(); __itx != __this->end();) 01676 { 01677 const auto __xrange = __this->equal_range(_ExtractKey()(*__itx)); 01678 const auto __yrange = __other.equal_range(_ExtractKey()(*__itx)); 01679 01680 if (std::distance(__xrange.first, __xrange.second) 01681 != std::distance(__yrange.first, __yrange.second)) 01682 return false; 01683 01684 if (!_S_is_permutation(__xrange.first, __xrange.second, 01685 __yrange.first)) 01686 return false; 01687 01688 __itx = __xrange.second; 01689 } 01690 return true; 01691 } 01692 01693 //@} hashtable-detail 01694 _GLIBCXX_END_NAMESPACE_VERSION 01695 } // namespace __detail 01696 } // namespace std 01697 01698 #endif // _HASHTABLE_POLICY_H