hashtable
来自「Mac OS X 10.4.9 for x86 Source Code gcc」· 代码 · 共 1,432 行 · 第 1/4 页
TXT
1,432 行
// is always at most one, false if it may be an arbitrary number. This// true for unordered_set and unordered_map, false for unordered_multiset// and unordered_multimap.template <typename Key, typename Value, typename Allocator, typename ExtractKey, typename Equal, typename H1, typename H2, typename H, typename RehashPolicy, bool cache_hash_code, bool mutable_iterators, bool unique_keys>class hashtable : public Internal::rehash_base<RehashPolicy, hashtable<Key, Value, Allocator, ExtractKey, Equal, H1, H2, H, RehashPolicy, cache_hash_code, mutable_iterators, unique_keys> >, public Internal::hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, H, cache_hash_code>, public Internal::map_base<Key, Value, ExtractKey, unique_keys, hashtable<Key, Value, Allocator, ExtractKey, Equal, H1, H2, H, RehashPolicy, cache_hash_code, mutable_iterators, unique_keys> >{public: typedef Allocator allocator_type; typedef Value value_type; typedef Key key_type; typedef Equal key_equal; // mapped_type, if present, comes from map_base. // hasher, if present, comes from hash_code_base. typedef typename Allocator::difference_type difference_type; typedef typename Allocator::size_type size_type; typedef typename Allocator::reference reference; typedef typename Allocator::const_reference const_reference; typedef Internal::node_iterator<value_type, !mutable_iterators, cache_hash_code> local_iterator; typedef Internal::node_iterator<value_type, false, cache_hash_code> const_local_iterator; typedef Internal::hashtable_iterator<value_type, !mutable_iterators, cache_hash_code> iterator; typedef Internal::hashtable_iterator<value_type, false, cache_hash_code> const_iterator;private: typedef Internal::hash_node<Value, cache_hash_code> node; typedef typename Allocator::template rebind<node>::other node_allocator_t; typedef typename Allocator::template rebind<node*>::other bucket_allocator_t;private: node_allocator_t m_node_allocator; node** m_buckets; size_type m_bucket_count; size_type m_element_count; RehashPolicy m_rehash_policy; node* m_allocate_node (const value_type& v); void m_deallocate_node (node* n); void m_deallocate_nodes (node**, size_type); node** m_allocate_buckets (size_type n); void m_deallocate_buckets (node**, size_type n);public: // Constructor, destructor, assignment, swap hashtable(size_type bucket_hint, const H1&, const H2&, const H&, const Equal&, const ExtractKey&, const allocator_type&); template <typename InIter> hashtable(InIter first, InIter last, size_type bucket_hint, const H1&, const H2&, const H&, const Equal&, const ExtractKey&, const allocator_type&); hashtable(const hashtable&); hashtable& operator=(const hashtable&); ~hashtable(); void swap(hashtable&);public: // Basic container operations iterator begin() { iterator i(m_buckets); if (!i.m_cur_node) i.m_incr_bucket(); return i; } const_iterator begin() const { const_iterator i(m_buckets); if (!i.m_cur_node) i.m_incr_bucket(); return i; } iterator end() { return iterator(m_buckets + m_bucket_count); } const_iterator end() const { return const_iterator(m_buckets + m_bucket_count); } size_type size() const { return m_element_count; } bool empty() const { return size() == 0; } allocator_type get_allocator() const { return m_node_allocator; } size_type max_size() const { return m_node_allocator.max_size(); }public: // Bucket operations size_type bucket_count() const { return m_bucket_count; } size_type max_bucket_count() const { return max_size(); } size_type bucket_size (size_type n) const { return std::distance(begin(n), end(n)); } size_type bucket (const key_type& k) const { return this->bucket_index (k, this->m_hash_code, this->m_bucket_count); } local_iterator begin(size_type n) { return local_iterator(m_buckets[n]); } local_iterator end(size_type n) { return local_iterator(0); } const_local_iterator begin(size_type n) const { return const_local_iterator(m_buckets[n]); } const_local_iterator end(size_type n) const { return const_local_iterator(0); } float load_factor() const { return static_cast<float>(size()) / static_cast<float>(bucket_count()); } // max_load_factor, if present, comes from rehash_base. // Generalization of max_load_factor. Extension, not found in TR1. Only // useful if RehashPolicy is something other than the default. const RehashPolicy& rehash_policy() const { return m_rehash_policy; } void rehash_policy (const RehashPolicy&);public: // lookup iterator find(const key_type&); const_iterator find(const key_type& k) const; size_type count(const key_type& k) const; std::pair<iterator, iterator> equal_range(const key_type& k); std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const;private: // Insert and erase helper functions // ??? This dispatching is a workaround for the fact that we don't // have partial specialization of member templates; it would be // better to just specialize insert on unique_keys. There may be a // cleaner workaround. typedef typename Internal::IF<unique_keys, std::pair<iterator, bool>, iterator>::type Insert_Return_Type; node* find_node (node* p, const key_type& k, typename hashtable::hash_code_t c); std::pair<iterator, bool> insert (const value_type&, std::tr1::true_type); iterator insert (const value_type&, std::tr1::false_type);public: // Insert and erase Insert_Return_Type insert (const value_type& v) { return this->insert (v, std::tr1::integral_constant<bool, unique_keys>()); } Insert_Return_Type insert (const_iterator, const value_type& v) { return this->insert(v); } template <typename InIter> void insert(InIter first, InIter last); void erase(const_iterator); size_type erase(const key_type&); void erase(const_iterator, const_iterator); void clear();public: // Set number of buckets to be apropriate for container of n element. void rehash (size_type n);private: // Unconditionally change size of bucket array to n. void m_rehash (size_type n);};//----------------------------------------------------------------------// Definitions of class template hashtable's out-of-line member functions.template <typename K, typename V, typename A, typename Ex, typename Eq, typename H1, typename H2, typename H, typename RP, bool c, bool m, bool u>typename hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::node*hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::m_allocate_node (const value_type& v){ node* n = m_node_allocator.allocate(1); try { get_allocator().construct(&n->m_v, v); n->m_next = 0; return n; } catch(...) { m_node_allocator.deallocate(n, 1); throw; }}template <typename K, typename V, typename A, typename Ex, typename Eq, typename H1, typename H2, typename H, typename RP, bool c, bool m, bool u>voidhashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::m_deallocate_node (node* n){ get_allocator().destroy(&n->m_v); m_node_allocator.deallocate(n, 1);}template <typename K, typename V, typename A, typename Ex, typename Eq, typename H1, typename H2, typename H, typename RP, bool c, bool m, bool u>voidhashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::m_deallocate_nodes (node** array, size_type n){ for (size_type i = 0; i < n; ++i) { node* p = array[i]; while (p) { node* tmp = p; p = p->m_next; m_deallocate_node (tmp); } array[i] = 0; }}template <typename K, typename V, typename A, typename Ex, typename Eq, typename H1, typename H2, typename H, typename RP, bool c, bool m, bool u>typename hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::node**hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::m_allocate_buckets (size_type n){ bucket_allocator_t alloc(m_node_allocator); // We allocate one extra bucket to hold a sentinel, an arbitrary // non-null pointer. Iterator increment relies on this. node** p = alloc.allocate(n+1); std::fill(p, p+n, (node*) 0); p[n] = reinterpret_cast<node*>(0x1000); return p;}template <typename K, typename V, typename A, typename Ex, typename Eq, typename H1, typename H2, typename H, typename RP, bool c, bool m, bool u>voidhashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::m_deallocate_buckets (node** p, size_type n){ bucket_allocator_t alloc(m_node_allocator); alloc.deallocate(p, n+1);}template <typename K, typename V, typename A, typename Ex, typename Eq, typename H1, typename H2, typename H, typename RP, bool c, bool m, bool u>hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::hashtable(size_type bucket_hint, const H1& h1, const H2& h2, const H& h, const Eq& eq, const Ex& exk, const allocator_type& a) : Internal::rehash_base<RP,hashtable> (), Internal::hash_code_base<K,V,Ex,Eq,H1,H2,H,c> (exk, eq, h1, h2, h), Internal::map_base<K,V,Ex,u,hashtable> (), m_node_allocator(a), m_bucket_count (0), m_element_count (0), m_rehash_policy (){ m_bucket_count = m_rehash_policy.next_bkt(bucket_hint); m_buckets = m_allocate_buckets (m_bucket_count);}template <typename K, typename V, typename A, typename Ex, typename Eq, typename H1, typename H2, typename H, typename RP, bool c, bool m, bool u>template <typename InIter>hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::hashtable(InIter f, InIter l, size_type bucket_hint, const H1& h1, const H2& h2, const H& h, const Eq& eq, const Ex& exk, const allocator_type& a) : Internal::rehash_base<RP,hashtable> (), Internal::hash_code_base<K,V,Ex,Eq,H1,H2,H,c> (exk, eq, h1, h2, h), Internal::map_base<K,V,Ex,u,hashtable> (), m_node_allocator(a), m_bucket_count (0), m_element_count (0), m_rehash_policy (){ m_bucket_count = std::max(m_rehash_policy.next_bkt(bucket_hint), m_rehash_policy.bkt_for_elements(Internal::distance_fw(f, l))); m_buckets = m_allocate_buckets (m_bucket_count); try { for (; f != l; ++f) this->insert (*f); } catch(...) { clear(); m_deallocate_buckets (m_buckets, m_bucket_count); throw; }}template <typename K, typename V, typename A, typename Ex, typename Eq, typename H1, typename H2, typename H, typename RP, bool c, bool m, bool u>hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::hashtable(const hashtable& ht) : Internal::rehash_base<RP,hashtable> (ht), Internal::hash_code_base<K,V,Ex,Eq,H1,H2,H,c> (ht), Internal::map_base<K,V,Ex,u,hashtable> (ht), m_node_allocator(ht.get_allocator()), m_bucket_count (ht.m_bucket_count), m_element_count (ht.m_element_count), m_rehash_policy (ht.m_rehash_policy){ m_buckets = m_allocate_buckets (m_bucket_count); try { for (size_t i = 0; i < ht.m_bucket_count; ++i) { node* n = ht.m_buckets[i]; node** tail = m_buckets + i; while (n) { *tail = m_allocate_node (n); (*tail).copy_code_from (n); tail = &((*tail)->m_next); n = n->m_next; } } } catch (...) { clear(); m_deallocate_buckets (m_buckets, m_bucket_count); throw; }}template <typename K, typename V, typename A, typename Ex, typename Eq, typename H1, typename H2, typename H, typename RP, bool c, bool m, bool u>hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>&hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::operator= (const hashtable& ht){ hashtable tmp(ht); this->swap(tmp); return *this;}template <typename K, typename V, typename A, typename Ex, typename Eq, typename H1, typename H2, typename H, typename RP, bool c, bool m, bool u>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?