| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
 | 
					
						
							| 
									
										
										
										
											2011-06-04 16:17:07 +00:00
										 |  |  | // Copyright (C) 2005-2011 Daniel James
 | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  | // Distributed under the Boost Software License, Version 1.0. (See accompanying
 | 
					
						
							|  |  |  | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
 | 
					
						
							|  |  |  | #define BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <boost/unordered/detail/extract_key.hpp>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | namespace boost { namespace unordered { namespace detail { | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 20:12:40 +00:00
										 |  |  |     template <class T> | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |     class equivalent_table : public T::table_base | 
					
						
							| 
									
										
										
										
											2010-05-06 20:12:40 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |     public: | 
					
						
							|  |  |  |         typedef BOOST_DEDUCED_TYPENAME T::hasher hasher; | 
					
						
							|  |  |  |         typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal; | 
					
						
							|  |  |  |         typedef BOOST_DEDUCED_TYPENAME T::value_allocator value_allocator; | 
					
						
							|  |  |  |         typedef BOOST_DEDUCED_TYPENAME T::key_type key_type; | 
					
						
							|  |  |  |         typedef BOOST_DEDUCED_TYPENAME T::value_type value_type; | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |         typedef BOOST_DEDUCED_TYPENAME T::table_base table_base; | 
					
						
							| 
									
										
										
										
											2010-05-06 20:12:40 +00:00
										 |  |  |         typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor; | 
					
						
							| 
									
										
										
										
											2011-08-11 21:18:43 +00:00
										 |  |  |         typedef BOOST_DEDUCED_TYPENAME T::node_allocator node_allocator; | 
					
						
							| 
									
										
										
										
											2010-05-06 20:12:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         typedef BOOST_DEDUCED_TYPENAME T::node node; | 
					
						
							|  |  |  |         typedef BOOST_DEDUCED_TYPENAME T::node_ptr node_ptr; | 
					
						
							|  |  |  |         typedef BOOST_DEDUCED_TYPENAME T::bucket_ptr bucket_ptr; | 
					
						
							|  |  |  |         typedef BOOST_DEDUCED_TYPENAME T::extractor extractor; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Constructors
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         equivalent_table(std::size_t n, | 
					
						
							| 
									
										
										
										
											2010-05-06 20:12:40 +00:00
										 |  |  |             hasher const& hf, key_equal const& eq, value_allocator const& a) | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |           : table_base(n, hf, eq, a) {} | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         equivalent_table(equivalent_table const& x) | 
					
						
							| 
									
										
										
										
											2011-08-11 21:18:19 +00:00
										 |  |  |           : table_base(x, | 
					
						
							|  |  |  |                 allocator_traits<node_allocator>:: | 
					
						
							|  |  |  |                 select_on_container_copy_construction(x.node_alloc())) {} | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         equivalent_table(equivalent_table const& x, | 
					
						
							| 
									
										
										
										
											2010-05-06 20:12:40 +00:00
										 |  |  |             value_allocator const& a) | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |           : table_base(x, a) {} | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         equivalent_table(equivalent_table& x, move_tag m) | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |           : table_base(x, m) {} | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         equivalent_table(equivalent_table& x, | 
					
						
							| 
									
										
										
										
											2010-05-06 20:12:40 +00:00
										 |  |  |             value_allocator const& a, move_tag m) | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |           : table_base(x, a, m) {} | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         ~equivalent_table() {} | 
					
						
							| 
									
										
										
										
											2010-05-06 20:12:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         // Equality
 | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         bool equals(equivalent_table const& other) const | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             if(this->size_ != other.size_) return false; | 
					
						
							|  |  |  |             if(!this->size_) return true; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             for(node_ptr n1 = this->buckets_[this->bucket_count_].next_; n1;) | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  |             { | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                 node_ptr n2 = other.find_matching_node(n1); | 
					
						
							| 
									
										
										
										
											2011-04-17 16:23:25 +00:00
										 |  |  |                 if (!n2) return false; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                 node_ptr end1 = node::next_group(n1); | 
					
						
							|  |  |  |                 node_ptr end2 = node::next_group(n2); | 
					
						
							| 
									
										
										
										
											2011-04-17 16:23:25 +00:00
										 |  |  |                 if (!group_equals(n1, end1, n2, end2)) return false; | 
					
						
							|  |  |  |                 n1 = end1;     | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |      | 
					
						
							|  |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-04-17 16:23:25 +00:00
										 |  |  |          | 
					
						
							|  |  |  |         static bool group_equals(node_ptr n1, node_ptr end1, | 
					
						
							|  |  |  |                 node_ptr n2, node_ptr end2) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             for(;;) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 if (node::get_value(n1) != node::get_value(n2)) | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 n1 = n1->next_; | 
					
						
							|  |  |  |                 n2 = n2->next_; | 
					
						
							|  |  |  |              | 
					
						
							|  |  |  |                 if (n1 == end1) return n2 == end2; | 
					
						
							|  |  |  |                 if (n2 == end2) return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |              | 
					
						
							|  |  |  |             for(node_ptr n1a = n1, n2a = n2;;) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 n1a = n1a->next_; | 
					
						
							|  |  |  |                 n2a = n2a->next_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (n1a == end1) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     if (n2a == end2) break; | 
					
						
							|  |  |  |                     else return false; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (n2a == end2) return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             node_ptr start = n1; | 
					
						
							|  |  |  |             for(;n1 != end2; n1 = n1->next_) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 value_type const& v = node::get_value(n1); | 
					
						
							|  |  |  |                 if (find(start, n1, v)) continue; | 
					
						
							| 
									
										
										
										
											2011-04-17 21:27:38 +00:00
										 |  |  |                 std::size_t matches = count_equal(n2, end2, v); | 
					
						
							| 
									
										
										
										
											2011-04-29 11:03:29 +00:00
										 |  |  |                 if (!matches || matches != 1 + count_equal(n1->next_, end1, v)) | 
					
						
							| 
									
										
										
										
											2011-04-17 16:23:25 +00:00
										 |  |  |                     return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |              | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         static bool find(node_ptr n, node_ptr end, value_type const& v) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             for(;n != end; n = n->next_) | 
					
						
							|  |  |  |                 if (node::get_value(n) == v) | 
					
						
							|  |  |  |                     return true; | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2011-04-17 21:27:38 +00:00
										 |  |  |         static std::size_t count_equal(node_ptr n, node_ptr end, value_type const& v) | 
					
						
							| 
									
										
										
										
											2011-04-17 16:23:25 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |             std::size_t count = 0; | 
					
						
							|  |  |  |             for(;n != end; n = n->next_) | 
					
						
							|  |  |  |                 if (node::get_value(n) == v) ++count; | 
					
						
							|  |  |  |             return count; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         ////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |         // A convenience method for adding nodes.
 | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         inline node_ptr add_node( | 
					
						
							|  |  |  |                 node_constructor& a, | 
					
						
							|  |  |  |                 std::size_t bucket_index, | 
					
						
							|  |  |  |                 std::size_t hash, | 
					
						
							|  |  |  |                 node_ptr pos) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             node_ptr n = a.release(); | 
					
						
							|  |  |  |             node::set_hash(n, hash); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             if(BOOST_UNORDERED_BORLAND_BOOL(pos)) { | 
					
						
							|  |  |  |                 node::add_after_node(n, pos); | 
					
						
							|  |  |  |                 if (n->next_) { | 
					
						
							|  |  |  |                     std::size_t next_bucket = | 
					
						
							|  |  |  |                         node::get_hash(n->next_) % this->bucket_count_; | 
					
						
							|  |  |  |                     if (next_bucket != bucket_index) { | 
					
						
							|  |  |  |                         this->buckets_[next_bucket].next_ = n; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 bucket_ptr b = this->get_bucket(bucket_index); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |                 if (!b->next_) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     bucket_ptr start_node = | 
					
						
							|  |  |  |                         this->get_bucket(this->bucket_count_); | 
					
						
							|  |  |  |                      | 
					
						
							|  |  |  |                     if (BOOST_UNORDERED_BORLAND_BOOL(start_node->next_)) { | 
					
						
							|  |  |  |                         this->buckets_[ | 
					
						
							|  |  |  |                             node::get_hash(start_node->next_) % | 
					
						
							|  |  |  |                                 this->bucket_count_].next_ = n; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |                     b->next_ = start_node; | 
					
						
							|  |  |  |                     n->next_ = start_node->next_; | 
					
						
							|  |  |  |                     start_node->next_ = n; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     n->next_ = b->next_->next_; | 
					
						
							|  |  |  |                     b->next_->next_ = n; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             ++this->size_; | 
					
						
							|  |  |  |             return n; | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         ////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |         // Insert methods
 | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         node_ptr emplace_impl(node_constructor& a) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             key_type const& k = this->get_key(a.value()); | 
					
						
							|  |  |  |             std::size_t hash = this->hash_function()(k); | 
					
						
							|  |  |  |             std::size_t bucket_index = hash % this->bucket_count_; | 
					
						
							|  |  |  |             node_ptr position = this->find_node(bucket_index, hash, k); | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |             // reserve has basic exception safety if the hash function
 | 
					
						
							|  |  |  |             // throws, strong otherwise.
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             if(this->reserve_for_insert(this->size_ + 1)) { | 
					
						
							|  |  |  |                 bucket_index = hash % this->bucket_count_; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             return add_node(a, bucket_index, hash, position); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         void emplace_impl_no_rehash(node_constructor& a) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             key_type const& k = this->get_key(a.value()); | 
					
						
							|  |  |  |             std::size_t hash = this->hash_function()(k); | 
					
						
							|  |  |  |             std::size_t bucket_index = hash % this->bucket_count_; | 
					
						
							|  |  |  |             add_node(a, bucket_index, hash, | 
					
						
							|  |  |  |                 this->find_node(bucket_index, hash, k)); | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-07 08:55:28 +00:00
										 |  |  | #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
 | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         template <class... Args> | 
					
						
							|  |  |  |         node_ptr emplace(Args&&... args) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // Create the node before rehashing in case it throws an
 | 
					
						
							|  |  |  |             // exception (need strong safety in such a case).
 | 
					
						
							|  |  |  |             node_constructor a(*this); | 
					
						
							|  |  |  |             a.construct(std::forward<Args>(args)...); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             return emplace_impl(a); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _)                       \
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)>             \ | 
					
						
							|  |  |  |         node_ptr emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params))    \ | 
					
						
							|  |  |  |         {                                                                   \ | 
					
						
							|  |  |  |             node_constructor a(*this);                                      \ | 
					
						
							|  |  |  |             a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params));        \ | 
					
						
							|  |  |  |             return emplace_impl(a);                                         \ | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, | 
					
						
							|  |  |  |             BOOST_UNORDERED_INSERT_IMPL, _) | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #undef BOOST_UNORDERED_INSERT_IMPL
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         ////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |         // Insert range methods
 | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         // if hash function throws, or inserting > 1 element, basic exception
 | 
					
						
							|  |  |  |         // safety. Strong otherwise
 | 
					
						
							|  |  |  |         template <class I> | 
					
						
							|  |  |  |         void insert_for_range(I i, I j, forward_traversal_tag) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if(i == j) return; | 
					
						
							|  |  |  |             std::size_t distance = ::boost::unordered::detail::distance(i, j); | 
					
						
							|  |  |  |             if(distance == 1) { | 
					
						
							|  |  |  |                 emplace(*i); | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                 // Only require basic exception safety here
 | 
					
						
							|  |  |  |                 this->reserve_for_insert(this->size_ + distance); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 node_constructor a(*this);     | 
					
						
							|  |  |  |                 for (; i != j; ++i) { | 
					
						
							|  |  |  |                     a.construct(*i); | 
					
						
							|  |  |  |                     emplace_impl_no_rehash(a); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         template <class I> | 
					
						
							|  |  |  |         void insert_for_range(I i, I j, ::boost::incrementable_traversal_tag) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             node_constructor a(*this); | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |             for (; i != j; ++i) { | 
					
						
							|  |  |  |                 a.construct(*i); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                 emplace_impl(a); | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         // If hash function throws, or inserting > 1 element, basic exception
 | 
					
						
							|  |  |  |         // safety. Strong otherwise
 | 
					
						
							|  |  |  |         template <class I> | 
					
						
							|  |  |  |         void insert_range(I i, I j) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             BOOST_DEDUCED_TYPENAME ::boost::iterator_traversal<I>::type | 
					
						
							|  |  |  |                 iterator_traversal_tag; | 
					
						
							|  |  |  |             insert_for_range(i, j, iterator_traversal_tag); | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template <class H, class P, class A> | 
					
						
							|  |  |  |     struct multiset : public types< | 
					
						
							| 
									
										
										
										
											2011-08-11 21:17:57 +00:00
										 |  |  |         BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type, | 
					
						
							|  |  |  |         BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type, | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         H, P, A, | 
					
						
							| 
									
										
										
										
											2011-08-11 21:17:57 +00:00
										 |  |  |         set_extractor<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>, | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         false> | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         typedef equivalent_table<multiset<H, P, A> > impl; | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |         typedef table<multiset<H, P, A> > table_base; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template <class K, class H, class P, class A> | 
					
						
							|  |  |  |     struct multimap : public types< | 
					
						
							| 
									
										
										
										
											2011-08-11 21:17:57 +00:00
										 |  |  |         K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type, | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         H, P, A, | 
					
						
							| 
									
										
										
										
											2011-08-11 21:17:57 +00:00
										 |  |  |         map_extractor<K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>, | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         false> | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         typedef equivalent_table<multimap<K, H, P, A> > impl; | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |         typedef table<multimap<K, H, P, A> > table_base; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |     }; | 
					
						
							|  |  |  | }}} | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #endif
 |