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(adobe::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     std::pair<iterator, bool> insert(value_type x)
00460     {
00461         if (capacity() == size()) reserve(size() ? 2 * size() : 3);
00462 
00463         iterator node = bucket(key_function()(x));
00464 
00465         switch (node.state())
00466         {
00467         case state_home:
00468             {
00469             iterator found = find(node, key_function()(x));
00470             if (found != end()) {
00471                 *found = adobe::move(x);
00472                 return std::make_pair(found, false);
00473             }
00474 
00475             iterator free(begin_free());
00476             insert_raw(free, adobe::move(x), state_misplaced);
00477             unsafe::splice_node_range(node, free, free);
00478             node = free;
00479             }
00480             break;
00481         case state_misplaced:
00482             {
00483             iterator free(begin_free());
00484             insert_raw(free, adobe::move(*node), state_misplaced);
00485 
00486             unsafe::set_next(boost::prior(node), free);
00487             unsafe::set_next(free, boost::next(node));
00488 
00489             erase_raw(node);
00490             }
00491             // fall through
00492         default: // state_free
00493             {
00494             insert_raw(node, adobe::move(x), state_home);
00495             unsafe::splice_node_range(end(), node, node);
00496             }
00497         }
00498         header()->size() += 1;
00499         return std::make_pair(node, true);
00500     }
00501 
00502     iterator insert(iterator, value_type x)
00503     {
00504         return insert(adobe::move(x)).first;
00505     }
00506 
00507     ~closed_hash_set()
00508     {
00509         if (header())
00510         {
00511             for(iterator first(begin()), last(end()); first != last; ++first) destroy(&*first);
00512             raw_allocator alloc(get_allocator());
00513             alloc.deallocate(reinterpret_cast<char*>(header()), 0);
00514         }
00515     }
00516 
00517     friend void swap(closed_hash_set& x, closed_hash_set& y)
00518     {
00519         std::swap(x.data_m, y.data_m);
00520     }
00521 
00522     friend bool operator==(const closed_hash_set& x, const closed_hash_set& y)
00523     {
00524         if (x.size() != y.size()) return false;
00525         for (const_iterator first(x.begin()), last(x.end()); first != last; ++first)
00526         {
00527             const_iterator iter(y.find(y.key_function()(*first)));
00528             if (iter == y.end() || !(*first == *iter)) return false;
00529         }
00530         return true;
00531     }
00532  private:
00533 
00534     typedef typename allocator_type::template rebind<char>::other raw_allocator;
00535 
00536 
00537     void allocate(const allocator_type& a, size_type n)
00538     {
00539         // table of primes such that p[n + 1] = next_prime(2 * p[n])
00540 
00541         static const std::size_t prime_table[] = { 3UL, 7UL, 17UL, 37UL, 79UL, 163UL, 331UL, 673UL,
00542             1361UL, 2729UL, 5471UL, 10949UL, 21911UL, 43853UL, 87719UL, 175447UL, 350899UL,
00543             701819UL, 1403641UL, 2807303UL, 5614657UL, 11229331UL, 22458671UL, 44917381UL,
00544             89834777UL, 179669557UL, 359339171UL, 718678369UL, 1437356741UL, 2874713497UL,
00545             ULONG_MAX
00546         };
00547 
00548         assert(!header() && "WARNING (sparent@adobe.com) : About to write over allocated header.");
00549 
00550         if (n == 0 && a == allocator_type()) return;
00551 
00552         n = *adobe::lower_bound(prime_table, n);
00553 
00554         raw_allocator alloc(a);
00555 
00556         header() = reinterpret_cast<header_t*>(alloc.allocate(sizeof(header_t) - sizeof(node_t)
00557             + sizeof(node_t) * n));
00558         header()->capacity() = n;
00559         header()->size() = 0;
00560         construct(&header()->free_tail());
00561         construct(&header()->used_tail());
00562         construct(&header()->allocator(), a);
00563 
00564         node_t* prior = header()->free_tail().address();
00565         for (node_ptr first(&header()->storage_m[0]), last(&header()->storage_m[0]+ n);
00566                 first != last; ++first)
00567         {
00568             set_next_raw(*prior, *first);
00569             prior = first;
00570             // first->set_state(state_free);
00571         }
00572         set_next_raw(*prior, header()->free_tail());
00573 
00574     }
00575 
00576     iterator bucket(const key_type& key)
00577     {
00578         std::size_t slot(hash_function()(key) % capacity());
00579         return iterator(&header()->storage_m[0] + slot);
00580     }
00581 
00582     iterator find(iterator node, const key_type& key)
00583     {
00584         do
00585         {
00586             if (key_eq()(key, key_function()(*node))) return node;
00587             ++node;
00588         } while ((node != end()) && (node.state() != std::size_t(state_home)));
00589 
00590         return end();
00591     }
00592 
00593     // location points to a free node
00594     static void insert_raw(iterator location, value_type x, std::size_t state)
00595     {
00596         construct<value_type>(&*location, adobe::move(x));
00597         location.set_state(state);
00598         unsafe::skip_node(location);
00599     }
00600 
00601     // location points to a used but detatched node
00602     void erase_raw(iterator location)
00603     {
00604         destroy(&*location);
00605         location.set_state(state_free);
00606         unsafe::splice_node_range(end_free(), location, location);
00607     }
00608 
00609     iterator begin_free() { return iterator(header() ? header()->free_tail().next() : 0); }
00610     iterator end_free() { return iterator(header() ? header()->free_tail().address() : 0); }
00611 };
00612 
00613 /*************************************************************************************************/
00614 
00633 template<typename Key,
00634          typename T,
00635          typename Hash,
00636          typename Pred,
00637          typename A>
00638 class closed_hash_map : public closed_hash_set<pair<Key, T>,
00639                                                get_element<0, pair<Key, T> >,
00640                                                Hash,
00641                                                Pred,
00642                                                A>
00643 {
00644     typedef closed_hash_set<pair<Key, T>,
00645                             get_element<0, pair<Key, T> >,
00646                             Hash,
00647                             Pred,
00648                             A> set_type;
00649  public:
00650     typedef T mapped_type;
00651 
00652     closed_hash_map() { }
00653 
00654     template <typename I> // I models InputIterator
00655     closed_hash_map(I f, I l) : set_type(f, l) { }
00656 
00657 #if 0
00658     template <typename I> // I models ForwardIterator
00659     closed_hash_map(I f, I l, move_ctor) : set_type(f, l, move_ctor()) { }
00660 #endif
00661 
00662     closed_hash_map(const closed_hash_map& x) : set_type(x) { }
00663     closed_hash_map(move_from<closed_hash_map> x) : set_type(move_from<set_type>(x.source)) { }
00664     closed_hash_map& operator=(closed_hash_map x)
00665     { swap(x, *this); return *this; }
00666 
00667     friend void swap(closed_hash_map& x, closed_hash_map& y)
00668     { swap(static_cast<set_type&>(x), static_cast<set_type&>(y)); }
00669 
00670 
00671     friend bool operator==(const closed_hash_map& x, const closed_hash_map& y)
00672     { return static_cast<const set_type&>(x) == static_cast<const set_type&>(y); }
00673 
00674     /*
00675         NOTE (sparent) : Can't use boost::equality_comparable without introducing extra base class
00676         overhead.
00677     */
00678 
00679     friend bool operator!=(const closed_hash_map& x, const closed_hash_map& y)
00680     { return !(x == y); }
00681 
00682 #ifndef ADOBE_CLOSED_HASH_MAP_INDEX
00683 #define ADOBE_CLOSED_HASH_MAP_INDEX 1
00684 #endif
00685 
00686 #if ADOBE_CLOSED_HASH_MAP_INDEX
00687 
00688     mapped_type& operator[](const Key& x)
00689     {
00690         typename set_type::iterator i = this->find(x);
00691         if (i == this->end()) return insert(adobe::make_pair(x, mapped_type())).first->second;
00692         return i->second;
00693     }
00694 
00695 #endif
00696 };
00697 
00698 /*************************************************************************************************/
00699 
00700 BOOST_STATIC_ASSERT(sizeof(closed_hash_set<int>) == sizeof(void*));
00701 
00702 
00703 #ifndef ADOBE_NO_DOCUMENTATION
00704 
00705 } // namespace version_1
00706 
00707 #endif
00708 
00709 /*************************************************************************************************/
00710 
00711 } // namespace adobe
00712 
00713 /*************************************************************************************************/
00714 
00715 ADOBE_NAME_TYPE_1("closed_hash_set:version_1:adobe",
00716     adobe::version_1::closed_hash_set<T0, adobe::identity<const T0>, boost::hash<T0>, std::equal_to<T0>,
00717         adobe::capture_allocator<T0> >);
00718 ADOBE_NAME_TYPE_2("closed_hash_map:version_1:adobe",
00719     adobe::version_1::closed_hash_map<T0, T1, boost::hash<T0>, std::equal_to<T0>,
00720             adobe::capture_allocator<adobe::pair<T0, T1> > >);
00721 
00722 ADOBE_NAME_TYPE_5("closed_hash_set:version_1:adobe",
00723     adobe::version_1::closed_hash_set<T0, T1, T2, T3, T4 >);
00724 ADOBE_NAME_TYPE_5("closed_hash_map:version_1:adobe",
00725     adobe::version_1::closed_hash_map<T0, T1, T2, T3, T4 >);
00726 
00727 /*************************************************************************************************/
00728 
00729 namespace boost {
00730 
00731 template<   typename T,
00732             typename KeyTransform,
00733             typename Hash,
00734             typename Pred,
00735             typename A>
00736 struct has_nothrow_constructor<adobe::version_1::closed_hash_set<T, KeyTransform, Hash, Pred, A> >
00737         : boost::mpl::true_ { };
00738 
00739 template<typename Key,
00740          typename T,
00741          typename Hash,
00742          typename Pred,
00743          typename A>
00744 struct has_nothrow_constructor<adobe::version_1::closed_hash_map<Key, T, Hash, Pred, A> >
00745     : boost::mpl::true_ { };
00746 
00747 } // namespace boost
00748 
00749 /*************************************************************************************************/
00750 
00751 #endif
00752 
00753 /*************************************************************************************************/

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