00001
00002
00003
00004
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>
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
00075
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 }
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 }
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>
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
00246
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
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>
00308 closed_hash_set(I f, I l) { header() = 0; insert(f, l); }
00309
00310 template <typename I>
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>
00339 closed_hash_set(I f, I l, move_ctor) { header() = 0; move_insert(f, l); }
00340 #endif
00341
00342
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>
00446 void insert(I first, I last)
00447 { while (first != last) { insert(*first); ++first; } }
00448
00449 template <typename I>
00450 void move_insert(I first, I last)
00451 { while (first != last) { insert(move(*first)); ++first; } }
00452
00453
00454
00455
00456
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);
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
00504 default:
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
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
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
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
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
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
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
00676 default:
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>
00730 closed_hash_map(I f, I l) : set_type(f, l) { }
00731
00732 #if 0
00733 template <typename I>
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
00751
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 }
00781
00782 #endif
00783
00784
00785
00786 }
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 }
00823
00824
00825
00826 #endif
00827
00828