stlab.adobe.com Adobe Systems Incorporated

closed_hash.hpp

Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2007 Adobe Systems Incorporated
00003     Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
00004     or a copy at http://stlab.adobe.com/licenses.html)
00005 */
00006 
00007 /*************************************************************************************************/
00008 
00009 #ifndef ADOBE_CLOSED_HASH_HPP
00010 #define ADOBE_CLOSED_HASH_HPP
00011 
00012 /*************************************************************************************************/
00013 
00014 #include <adobe/config.hpp>
00015 
00016 #include <adobe/closed_hash_fwd.hpp>
00017 
00018 #include <climits>
00019 #include <cstddef>
00020 #include <limits>
00021 
00022 #include <boost/compressed_pair.hpp>
00023 #include <boost/functional/hash.hpp>
00024 #include <boost/iterator/iterator_adaptor.hpp>
00025 #include <boost/iterator/iterator_facade.hpp>
00026 #include <boost/static_assert.hpp>
00027 #include <boost/type_traits/has_nothrow_constructor.hpp>
00028 #include <boost/type_traits/remove_reference.hpp>
00029 #include <boost/operators.hpp>
00030 #include <boost/next_prior.hpp>
00031 
00032 #include <adobe/algorithm/lower_bound.hpp>
00033 #include <adobe/conversion.hpp>
00034 #include <adobe/cstdint.hpp>
00035 #include <adobe/empty.hpp>
00036 #include <adobe/functional.hpp>
00037 #include <adobe/iterator/set_next.hpp>
00038 #include <adobe/memory.hpp>
00039 #include <adobe/move.hpp>
00040 #include <adobe/utility.hpp>
00041 
00042 #include <adobe/implementation/swap.hpp>
00043 
00044 /*************************************************************************************************/
00045 
00046 namespace adobe {
00047 
00048 /*************************************************************************************************/
00049 
00050 namespace implementation {
00051 
00052 /*************************************************************************************************/
00053 
00054 template <typename T, typename V> // V is value_type(T) const qualified
00055 class closed_hash_iterator : public boost::iterator_facade<closed_hash_iterator<T, V>, V,
00056                                                            std::bidirectional_iterator_tag>
00057 {
00058     typedef boost::iterator_facade<closed_hash_iterator<T, V>, V,
00059                                    std::bidirectional_iterator_tag> inherited_t;
00060 
00061     typedef typename T::node_t node_t;
00062  public:
00063     typedef typename inherited_t::reference         reference;
00064     typedef typename inherited_t::difference_type   difference_type;
00065     typedef typename inherited_t::value_type        value_type;
00066 
00067     closed_hash_iterator() : node_m(0) { }
00068 
00069     template <typename O>
00070     closed_hash_iterator(const closed_hash_iterator<T, O>& x) : node_m(x.node_m) { }
00071 
00072  public:
00073     /*
00074         REVISIT (sparent@adobe.com) : node_m should be private but
00075         "gcc version 4.0.1 (Apple Inc. build 5465)" doesn't like it.
00076     */
00077 
00078     node_t* node_m;
00079 
00080  private:
00081     
00082     reference dereference() const { return node_m->value_m; }
00083     void increment() { node_m = node_m->next(); }           
00084     void decrement() { node_m = node_m->prior(); }
00085 
00086     template< typename O>
00087     bool equal(const closed_hash_iterator<T, O>& y) const { return node_m == y.node_m; }
00088     
00089     std::size_t state() const { return node_m->state(); }
00090     void set_state(std::size_t x) { return node_m->set_state(x); }
00091 
00092     explicit closed_hash_iterator(node_t* node) : node_m(node) { }
00093     
00094     friend class version_1::closed_hash_set<value_type, typename T::key_transform, typename T::hasher,
00095             typename T::key_equal, typename T::allocator_type>;
00096     friend class boost::iterator_core_access;
00097     friend struct unsafe::set_next_fn<closed_hash_iterator>;
00098 };
00099 
00100 /*************************************************************************************************/
00101 
00102 } // namespace implementation
00103 
00104 /*************************************************************************************************/
00105 
00106 namespace unsafe {
00107 
00108 template <typename T, typename V>
00109 struct set_next_fn<implementation::closed_hash_iterator<T, V> >
00110 {
00111     typedef typename implementation::closed_hash_iterator<T, V> iterator;
00112 
00113     void operator()(iterator x, iterator y) const
00114     { set_next(*x.node_m, *y.node_m); }
00115 };
00116 
00117 } // namespace unsafe
00118 
00119 /*************************************************************************************************/
00120 
00121 #ifndef ADOBE_NO_DOCUMENTATION
00122 
00123 namespace version_1 {
00124 
00125 #endif
00126 
00127 /*************************************************************************************************/
00128 
00152 template<   typename T,
00153             typename KeyTransform,
00154             typename Hash,
00155             typename Pred,
00156             typename A>
00157 class closed_hash_set : boost::equality_comparable<closed_hash_set<T, KeyTransform, Hash, Pred, A>,
00158                                         closed_hash_set<T, KeyTransform, Hash, Pred, A>,
00159                                         empty_base<closed_hash_set<T, KeyTransform, Hash, Pred, A> > >
00160 {
00161  public:
00162     typedef KeyTransform                        key_transform;
00163 
00164     typedef typename boost::remove_reference<typename key_transform::result_type>::type
00165                                                 key_type;
00166 
00167     typedef T                                   value_type;
00168     typedef Hash                                hasher;
00169     typedef Pred                                key_equal;
00170     typedef A                                   allocator_type;
00171     typedef value_type*                         pointer;
00172     typedef const value_type*                   const_pointer;
00173     typedef value_type&                         reference;
00174     typedef const value_type&                   const_reference;
00175     typedef std::size_t                         size_type;
00176     typedef std::ptrdiff_t                      difference_type;
00177 
00178     friend class implementation::closed_hash_iterator<closed_hash_set, value_type>;
00179     friend class implementation::closed_hash_iterator<closed_hash_set, const value_type>;
00180     
00181     typedef implementation::closed_hash_iterator<closed_hash_set, value_type>       iterator;
00182     typedef implementation::closed_hash_iterator<closed_hash_set, const value_type> const_iterator;
00183 
00184     typedef std::reverse_iterator<iterator>         reverse_iterator;
00185     typedef std::reverse_iterator<const_iterator>   const_reverse_iterator;
00186 
00187  private:
00188     enum
00189     {
00190         state_free          = 0,
00191         state_home          = 1,
00192         state_misplaced     = 2
00193     };
00194     
00195     template <typename U> // U is derived node
00196     struct list_node_base
00197     {
00198         list_node_base() { next_m = static_cast<U*>(this); prior_m = static_cast<U*>(this); }
00199         
00200         U* address() { return static_cast<U*>(this); }
00201         const U* address() const { return static_cast<const U*>(this); }
00202         
00203         operator U& () { return *static_cast<U*>(this); }
00204         operator const U& () const { return *static_cast<const U*>(this); }
00205         
00206         friend inline void set_next(U& x, U& y)
00207         { x.next_m = reinterpret_cast<U*>(uintptr_t(&y) | uintptr_t(x.state())); y.prior_m = &x; }
00208             
00209         friend inline void set_next_raw(U& x, U& y)
00210         { x.next_m = &y; y.prior_m = &x; }
00211         
00212         std::size_t state() const { return std::size_t(uintptr_t(next_m) & uintptr_t(0x03UL)); }
00213         void set_state(std::size_t x)
00214         {
00215             assert(x < 0x04UL);
00216             next_m = reinterpret_cast<U*>(uintptr_t(next()) | uintptr_t(x));
00217         }
00218         
00219         U* next() const { return reinterpret_cast<U*>(reinterpret_cast<uintptr_t>(next_m) & ~uintptr_t(0x03UL)); }
00220         U* prior() const { return prior_m; }
00221 
00222      private:
00223         U* next_m;
00224         U* prior_m;
00225     };
00226     
00227     struct node_t : list_node_base<node_t>
00228     {
00229         T           value_m;
00230     };
00231     
00232     typedef list_node_base<node_t> node_base_t;
00233     
00234     struct header_t
00235     {
00236         struct compact_header_t
00237         {
00238             boost::compressed_pair<allocator_type, node_base_t> alloc_free_tail_m;
00239             node_base_t used_tail_m;
00240             std::size_t capacity_m;
00241             std::size_t size_m;
00242         };
00243         
00244         /*
00245         NOTE (sparent) - the assumption is that the initial items are pointers and that size_t is
00246         either equal to the sizeof a pointer or a lower power of two so this packs tightly.
00247         */
00248         
00249         BOOST_STATIC_ASSERT(!(sizeof(A) == sizeof(void*) || sizeof(A) == 0)
00250             || (sizeof(compact_header_t) == (sizeof(allocator_type) + 2 * sizeof(node_base_t) + 2 *
00251                 sizeof(std::size_t))));
00252         
00253         aligned_storage<compact_header_t> header_m;
00254         node_t      storage_m[1];
00255         
00256         allocator_type&  allocator() { return header_m.get().alloc_free_tail_m.first(); }
00257         const allocator_type& allocator() const { return header_m.get().alloc_free_tail_m.first(); }
00258         node_base_t&  free_tail() { return header_m.get().alloc_free_tail_m.second(); }
00259         const node_base_t& free_tail() const { return header_m.get().alloc_free_tail_m.second(); }
00260         node_base_t&  used_tail() { return header_m.get().used_tail_m; }
00261         const node_base_t& used_tail() const { return header_m.get().used_tail_m; }
00262         std::size_t&  capacity() { return header_m.get().capacity_m; }
00263         const std::size_t& capacity() const { return header_m.get().capacity_m; }
00264         std::size_t&  size() { return header_m.get().size_m; }
00265         const std::size_t& size() const { return header_m.get().size_m; }
00266     };
00267     
00268     typedef node_t* node_ptr;
00269 
00270     typedef boost::compressed_pair< hasher,
00271                                     boost::compressed_pair< key_equal,
00272                                                             boost::compressed_pair< key_transform,
00273                                                                                     header_t*
00274                                                                                   >
00275                                                           >
00276                                   > data_t;
00277 
00278     data_t  data_m;
00279 
00280     typedef header_t* header_pointer;
00281    
00282     const header_pointer& header() const { return data_m.second().second().second(); }
00283     header_pointer& header() { return data_m.second().second().second(); }
00284     
00285  public:
00286     // construct/destroy/copy
00287 
00288     closed_hash_set() { header() = 0; }
00289     
00290     explicit closed_hash_set(size_type n)
00291     {
00292         header() = 0;
00293         allocate(allocator_type(), n);
00294     }
00295     
00296     closed_hash_set(size_type n, const hasher& hf, const key_equal& eq = key_equal(),
00297                                                    const key_transform& kf = key_transform(),
00298                                                    const allocator_type& a = allocator_type())
00299     {
00300         header() = 0;
00301         data_m.first() = hf;
00302         data_m.second().first() = eq;
00303         data_m.second().second().first() = kf;
00304         allocate(a, n);
00305     }
00306 
00307     template <typename I> // I models InputIterator
00308     closed_hash_set(I f, I l) { header() = 0; insert(f, l); }
00309 
00310     template <typename I> // I models InputIterator
00311     closed_hash_set(I f, I l, size_type n, const hasher& hf = hasher(),
00312                                            const key_equal& eq = key_equal(),
00313                                            const key_transform& kf = key_transform(),
00314                                            const allocator_type& a = allocator_type())
00315     {
00316         header() = 0;
00317         data_m.first() = hf;
00318         data_m.second().first() = eq;
00319         data_m.second().second().first() = kf;
00320         allocate(a, n);
00321         insert(f, l);
00322     }
00323     
00324     closed_hash_set(const closed_hash_set& x) : data_m(x.data_m)
00325     {
00326         header() = 0;
00327         allocate(x.get_allocator(), x.size());
00328         insert(x.begin(), x.end());
00329     }
00330     closed_hash_set& operator=(closed_hash_set x) { swap(x, *this); return *this; }
00331 
00332     allocator_type get_allocator() const
00333     { return header() ? header()->allocator() : allocator_type(); }
00334 
00335     closed_hash_set(move_from<closed_hash_set> x) : data_m(x.source.data_m) { x.source.header() = 0; }
00336 
00337 #if 0
00338     template <typename I> // I models ForwardIterator
00339     closed_hash_set(I f, I l, move_ctor) { header() = 0; move_insert(f, l); }
00340 #endif
00341 
00342     // size and capacity
00343 
00344     size_type size() const { return header() ? header()->size() : 0; }
00345     size_type max_size() const { return size_type(-1) / sizeof(node_t); }
00346     bool empty() const { return size() == 0; }
00347     size_type capacity() const { return header() ? header()->capacity() : 0; }
00348 
00349     void reserve(size_type n)
00350     {
00351         if (n <= capacity()) return;
00352         
00353         if (!header()) allocate(allocator_type(), n);
00354         else
00355         {
00356             closed_hash_set tmp(n, hash_function(), key_eq(), key_function(), get_allocator());
00357             tmp.move_insert(begin(), end());
00358             swap(*this, tmp);
00359         }
00360     }
00361     
00362     key_transform key_function() const { return data_m.second().second().first(); }
00363     hasher hash_function() const { return data_m.first(); }
00364     key_equal key_eq() const { return data_m.second().first(); }
00365     
00366     iterator begin() { return iterator(header() ? header()->used_tail().next() : 0); }
00367     iterator end() { return iterator(header() ? header()->used_tail().address() : 0); }
00368     
00369     const_iterator begin() const { return iterator(header() ? header()->used_tail().next() : 0); }
00370     const_iterator end() const { return iterator(header() ? const_cast<node_t*>(header()->used_tail().address()) : 0); }
00371     
00372     reverse_iterator rbegin() { return reverse_iterator(end()); }
00373     reverse_iterator rend() { return reverse_iterator(begin()); }
00374     
00375     const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
00376     const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
00377     
00378     iterator erase(iterator location)
00379     {
00380         iterator next(boost::next(location));
00381         iterator result = next;
00382     
00383         if ((location.state() == std::size_t(state_home)) && (next != end())
00384                 && (next.state() == std::size_t(state_misplaced)))
00385         {
00386             swap(*next, *location);
00387             result = location;
00388             location = next;
00389         }
00390     
00391         unsafe::skip_node(location);
00392         erase_raw(location);
00393         
00394         --header()->size();
00395         
00396         return result;
00397     }
00398     
00399     std::size_t erase(const key_type& key)
00400     {
00401         iterator node(find(key));
00402         if (node == end()) return 0;
00403         erase(node);
00404         return 1;
00405     }
00406     
00407     void clear()
00408     {
00409         for(iterator first(begin()), last(end()); first != last; first = erase(first)) ;
00410     }
00411     
00412     const_iterator find(const key_type& key) const
00413     {
00414         return adobe::remove_const(*this).find(key);
00415     }
00416     
00417     iterator find(const key_type& key)
00418     {
00419         if (empty()) return end();
00420         
00421         iterator node(bucket(key));
00422         
00423         if (node.state() != std::size_t(state_home)) return end();
00424         
00425         return find(node, key);
00426     }
00427     
00428     std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const
00429     {
00430         const_iterator result = find(key);
00431         if (result == end()) return std::make_pair(result, result);
00432         return std::make_pair(result, boost::next(result));
00433     }
00434     
00435     std::pair<iterator, iterator> equal_range(const key_type& key)
00436     {
00437         iterator result = find(key);
00438         if (result == end()) return std::make_pair(result, result);
00439         return std::make_pair(result, boost::next(result));
00440     }
00441     
00442     std::size_t count(const key_type& key) const
00443     { return std::size_t(find(key) != end()); }
00444     
00445     template <typename I> // I models InputIterator
00446     void insert(I first, I last)
00447     { while (first != last) { insert(*first); ++first; } }
00448     
00449     template <typename I> // I models ForwardIterator
00450     void move_insert(I first, I last)
00451     { while (first != last) { insert(move(*first)); ++first; } }
00452     
00453     /*
00454         NOTE (sparent): If there is not enough space for one element we will reserve the space
00455         prior to attempting the insert even if the item is already in the hash table. Without
00456         recalculating the bucket (a potentially expensive operation) there is no other solution.
00457     */
00458     
00459     template <typename U>
00460     std::pair<iterator, bool> insert(const U& x, typename copy_sink<U, value_type>::type = 0)
00461     {
00462         if (capacity() == size()) {
00463             value_type tmp(x); // Make a copy incase resize moves the element.
00464             reserve(size() ? 2 * size() : 3);
00465             return unsafe_copy_insert(tmp);
00466         }
00467         return unsafe_copy_insert(x);
00468     }
00469     
00470     template <typename U>
00471     std::pair<iterator, bool> insert(U x, typename move_sink<U, value_type>::type = 0)
00472     {
00473         if (capacity() == size()) reserve(size() ? 2 * size() : 3);
00474         
00475         iterator node = bucket(key_function()(x));
00476         
00477         switch (node.state())
00478         {
00479         case state_home:
00480             {
00481             iterator found = find(node, key_function()(x));
00482             if (found != end()) {
00483                 *found = move(x);
00484                 return std::make_pair(found, false);
00485             }
00486             
00487             iterator free(begin_free());
00488             insert_raw(free, move(x), state_misplaced);
00489             unsafe::splice_node_range(node, free, free);
00490             node = free;
00491             }
00492             break;
00493         case state_misplaced:
00494             {
00495             iterator free(begin_free());
00496             insert_raw(free, move(*node), state_misplaced);
00497             
00498             unsafe::set_next(boost::prior(node), free);
00499             unsafe::set_next(free, boost::next(node));
00500             
00501             erase_raw(node);
00502             }
00503             // fall through
00504         default: // state_free
00505             {
00506             insert_raw(node, move(x), state_home);
00507             unsafe::splice_node_range(end(), node, node);
00508             }
00509         }
00510         header()->size() += 1;
00511         return std::make_pair(node, true);
00512     }
00513     
00514     template <typename U>
00515     iterator insert(iterator, const U& x, typename copy_sink<U, value_type>::type = 0)
00516     {
00517         return insert(x).first;
00518     }
00519     
00520     template <typename U>
00521     iterator insert(iterator, U x, typename move_sink<U, value_type>::type = 0)
00522     {
00523         return insert(move(x)).first;
00524     }
00525     
00526     ~closed_hash_set()
00527     {
00528         if (header())
00529         {
00530             for(iterator first(begin()), last(end()); first != last; ++first) destroy(&*first);
00531             raw_allocator alloc(get_allocator());
00532             alloc.deallocate(reinterpret_cast<char*>(header()), 0);
00533         }
00534     }
00535         
00536     friend void swap(closed_hash_set& x, closed_hash_set& y)
00537     {
00538         std::swap(x.data_m, y.data_m);
00539     }
00540     
00541     friend bool operator==(const closed_hash_set& x, const closed_hash_set& y)
00542     {
00543         if (x.size() != y.size()) return false;
00544         for (const_iterator first(x.begin()), last(x.end()); first != last; ++first)
00545         {
00546             const_iterator iter(y.find(y.key_function()(*first)));
00547             if (iter == y.end() || !(*first == *iter)) return false;
00548         }
00549         return true;
00550     }
00551  private:
00552  
00553     typedef typename allocator_type::template rebind<char>::other raw_allocator;
00554 
00555 
00556     void allocate(const allocator_type& a, size_type n)
00557     {
00558         // table of primes such that p[n + 1] = next_prime(2 * p[n])
00559     
00560         static const std::size_t prime_table[] = { 3UL, 7UL, 17UL, 37UL, 79UL, 163UL, 331UL, 673UL,
00561             1361UL, 2729UL, 5471UL, 10949UL, 21911UL, 43853UL, 87719UL, 175447UL, 350899UL,
00562             701819UL, 1403641UL, 2807303UL, 5614657UL, 11229331UL, 22458671UL, 44917381UL,
00563             89834777UL, 179669557UL, 359339171UL, 718678369UL, 1437356741UL, 2874713497UL,
00564             ULONG_MAX
00565         };
00566 
00567         assert(!header() && "WARNING (sparent@adobe.com) : About to write over allocated header.");
00568 
00569         if (n == 0 && a == allocator_type()) return;
00570 
00571         n = *adobe::lower_bound(prime_table, n);
00572             
00573         raw_allocator alloc(a);
00574     
00575         header() = reinterpret_cast<header_t*>(alloc.allocate(sizeof(header_t) - sizeof(node_t)
00576             + sizeof(node_t) * n));
00577         header()->capacity() = n;
00578         header()->size() = 0;
00579         construct(&header()->free_tail());
00580         construct(&header()->used_tail());
00581         construct(&header()->allocator(), a);
00582         
00583         node_t* prior = header()->free_tail().address();
00584         for (node_ptr first(&header()->storage_m[0]), last(&header()->storage_m[0]+ n);
00585                 first != last; ++first)
00586         {
00587             set_next_raw(*prior, *first);
00588             prior = first;
00589             // first->set_state(state_free);
00590         }
00591         set_next_raw(*prior, header()->free_tail());
00592 
00593     }
00594  
00595     iterator bucket(const key_type& key)
00596     {
00597         std::size_t slot(hash_function()(key) % capacity());
00598         return iterator(&header()->storage_m[0] + slot);
00599     }
00600  
00601     iterator find(iterator node, const key_type& key)
00602     {
00603         do
00604         {
00605             if (key_eq()(key, key_function()(*node))) return node;
00606             ++node;
00607         } while ((node != end()) && (node.state() != std::size_t(state_home)));
00608         
00609         return end();
00610     }
00611  
00612     // location points to a free node
00613     template <typename U>
00614     static void insert_raw(iterator location, const U& x, std::size_t state,
00615         typename copy_sink<U, value_type>::type = 0)
00616     {
00617         ::new (&(*location)) value_type(x);
00618         location.set_state(state);
00619         unsafe::skip_node(location);
00620     }
00621  
00622     // location points to a free node
00623     template <typename U>
00624     static void insert_raw(iterator location, U x, std::size_t state,
00625         typename move_sink<U, value_type>::type = 0)
00626     {
00627         move_construct<value_type>(&*location, x);
00628         location.set_state(state);
00629         unsafe::skip_node(location);
00630     }
00631     
00632     // location points to a used but detatched node
00633     void erase_raw(iterator location)
00634     {
00635         destroy(&*location);
00636         location.set_state(state_free);
00637         unsafe::splice_node_range(end_free(), location, location);
00638     }
00639  
00640     iterator begin_free() { return iterator(header() ? header()->free_tail().next() : 0); }
00641     iterator end_free() { return iterator(header() ? header()->free_tail().address() : 0); }
00642 
00643 
00644     std::pair<iterator, bool> unsafe_copy_insert(const value_type& x)
00645     {
00646         // pre-condition is that there is capacity for the element.
00647         iterator node = bucket(key_function()(x));
00648         
00649         switch (node.state())
00650         {
00651         case state_home:
00652             {
00653             iterator found = find(node, key_function()(x));
00654             if (found != end()) {
00655                 *found = x;
00656                 return std::make_pair(found, false);
00657             }
00658             
00659             iterator free(begin_free());
00660             insert_raw(free, x, state_misplaced);
00661             unsafe::splice_node_range(node, free, free);
00662             node = free;
00663             }
00664             break;
00665         case state_misplaced:
00666             {
00667             iterator free(begin_free());
00668             insert_raw(free, *node, state_misplaced);
00669             
00670             unsafe::set_next(boost::prior(node), free);
00671             unsafe::set_next(free, boost::next(node));
00672             
00673             erase_raw(node);
00674             }
00675             // fall through
00676         default: // state_free
00677             {
00678             insert_raw(node, x, state_home);
00679             unsafe::splice_node_range(end(), node, node);
00680             }
00681         }
00682         header()->size() += 1;
00683         return std::make_pair(node, true);
00684     }
00685 
00686 };
00687 
00688 /*************************************************************************************************/
00689 
00708 template<typename Key,
00709          typename T,
00710          typename Hash,
00711          typename Pred,
00712          typename A>
00713 class closed_hash_map : public closed_hash_set<pair<Key, T>,
00714                                                get_element<0, pair<Key, T> >,
00715                                                Hash,
00716                                                Pred,
00717                                                A>
00718 {
00719     typedef closed_hash_set<pair<Key, T>,
00720                             get_element<0, pair<Key, T> >,
00721                             Hash,
00722                             Pred,
00723                             A> set_type;
00724  public:
00725     typedef T mapped_type;
00726  
00727     closed_hash_map() { }
00728     
00729     template <typename I> // I models InputIterator
00730     closed_hash_map(I f, I l) : set_type(f, l) { }
00731     
00732 #if 0
00733     template <typename I> // I models ForwardIterator
00734     closed_hash_map(I f, I l, move_ctor) : set_type(f, l, move_ctor()) { }
00735 #endif
00736         
00737     closed_hash_map(const closed_hash_map& x) : set_type(x) { }
00738     closed_hash_map(move_from<closed_hash_map> x) : set_type(move_from<set_type>(x.source)) { }
00739     closed_hash_map& operator=(closed_hash_map x)
00740     { swap(x, *this); return *this; }
00741             
00742     friend void swap(closed_hash_map& x, closed_hash_map& y)
00743     { swap(static_cast<set_type&>(x), static_cast<set_type&>(y)); }
00744     
00745     
00746     friend bool operator==(const closed_hash_map& x, const closed_hash_map& y)
00747     { return static_cast<const set_type&>(x) == static_cast<const set_type&>(y); }
00748     
00749     /*
00750         NOTE (sparent) : Can't use boost::equality_comparable without introducing extra base class
00751         overhead.
00752     */
00753     
00754     friend bool operator!=(const closed_hash_map& x, const closed_hash_map& y)
00755     { return !(x == y); }
00756 
00757 #ifndef ADOBE_CLOSED_HASH_MAP_INDEX
00758 #define ADOBE_CLOSED_HASH_MAP_INDEX 1
00759 #endif
00760 
00761 #if ADOBE_CLOSED_HASH_MAP_INDEX
00762         
00763     mapped_type& operator[](const Key& x)
00764     {
00765         typename set_type::iterator i = this->find(x);
00766         if (i == this->end()) return insert(adobe::make_pair(x, mapped_type())).first->second;
00767         return i->second;
00768     }
00769     
00770 #endif
00771 };
00772 
00773 /*************************************************************************************************/
00774 
00775 BOOST_STATIC_ASSERT(sizeof(closed_hash_set<int>) == sizeof(void*));
00776 
00777 
00778 #ifndef ADOBE_NO_DOCUMENTATION
00779 
00780 } // namespace version_1
00781 
00782 #endif
00783 
00784 /*************************************************************************************************/
00785 
00786 } // namespace adobe
00787 
00788 /*************************************************************************************************/
00789 
00790 ADOBE_NAME_TYPE_1("closed_hash_set:version_1:adobe",
00791     adobe::version_1::closed_hash_set<T0, adobe::identity<const T0>, boost::hash<T0>, std::equal_to<T0>,
00792         adobe::capture_allocator<T0> >);
00793 ADOBE_NAME_TYPE_2("closed_hash_map:version_1:adobe",
00794     adobe::version_1::closed_hash_map<T0, T1, boost::hash<T0>, std::equal_to<T0>,
00795             adobe::capture_allocator<adobe::pair<T0, T1> > >);
00796 
00797 ADOBE_NAME_TYPE_5("closed_hash_set:version_1:adobe",
00798     adobe::version_1::closed_hash_set<T0, T1, T2, T3, T4 >);
00799 ADOBE_NAME_TYPE_5("closed_hash_map:version_1:adobe",
00800     adobe::version_1::closed_hash_map<T0, T1, T2, T3, T4 >);
00801 
00802 /*************************************************************************************************/
00803 
00804 namespace boost {
00805 
00806 template<   typename T,
00807             typename KeyTransform,
00808             typename Hash,
00809             typename Pred,
00810             typename A>
00811 struct has_nothrow_constructor<adobe::version_1::closed_hash_set<T, KeyTransform, Hash, Pred, A> >
00812         : boost::mpl::true_ { };
00813 
00814 template<typename Key,
00815          typename T,
00816          typename Hash,
00817          typename Pred,
00818          typename A>
00819 struct has_nothrow_constructor<adobe::version_1::closed_hash_map<Key, T, Hash, Pred, A> >
00820     : boost::mpl::true_ { };
00821 
00822 } // namespace boost
00823 
00824 /*************************************************************************************************/
00825 
00826 #endif
00827 
00828 /*************************************************************************************************/

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google