| 
									
										
										
										
											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_UNIQUE_HPP_INCLUDED
 | 
					
						
							|  |  |  | #define BOOST_UNORDERED_DETAIL_UNIQUE_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 unique_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; | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         typedef std::pair<node_ptr, bool> emplace_return; | 
					
						
							| 
									
										
										
										
											2010-05-06 20:12:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Constructors
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         unique_table(std::size_t n, hasher const& hf, key_equal const& eq, | 
					
						
							| 
									
										
										
										
											2010-05-06 20:12:40 +00:00
										 |  |  |             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
										 |  |  |         unique_table(unique_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
										 |  |  |         unique_table(unique_table const& x, value_allocator const& a) | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |           : table_base(x, a) {} | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         unique_table(unique_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
										 |  |  |         unique_table(unique_table& x, value_allocator const& a, | 
					
						
							| 
									
										
										
										
											2010-05-06 20:12:40 +00:00
										 |  |  |             move_tag m) | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |           : table_base(x, a, m) {} | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         ~unique_table() {} | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 20:12:40 +00:00
										 |  |  |         // equals
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         bool equals(unique_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->get_bucket(this->bucket_count_)->next_; | 
					
						
							|  |  |  |                 n1; n1 = n1->next_) | 
					
						
							| 
									
										
										
										
											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 || node::get_value(n1) != node::get_value(n2)) | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  |                     return false; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |      | 
					
						
							|  |  |  |             return true; | 
					
						
							| 
									
										
										
										
											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
										 |  |  |         node_ptr add_node( | 
					
						
							|  |  |  |                 node_constructor& a, | 
					
						
							|  |  |  |                 std::size_t bucket_index, | 
					
						
							|  |  |  |                 std::size_t hash)         | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             bucket_ptr b = this->get_bucket(bucket_index); | 
					
						
							|  |  |  |             node_ptr n = a.release(); | 
					
						
							|  |  |  |             node::set_hash(n, hash); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             if (!b->next_) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 bucket_ptr start_node = this->get_bucket(this->bucket_count_); | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |                 if (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
										 |  |  |         // if hash function throws, basic exception safety
 | 
					
						
							|  |  |  |         // strong otherwise
 | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         value_type& operator[](key_type const& k) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             typedef BOOST_DEDUCED_TYPENAME value_type::second_type mapped_type; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             std::size_t hash = this->hash_function()(k); | 
					
						
							|  |  |  |             std::size_t bucket_index = hash % this->bucket_count_; | 
					
						
							|  |  |  |             node_ptr pos = this->find_node(bucket_index, hash, k); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             if (BOOST_UNORDERED_BORLAND_BOOL(pos)) { | 
					
						
							|  |  |  |                 return node::get_value(pos); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |             // Create the node before rehashing in case it throws an
 | 
					
						
							|  |  |  |             // exception (need strong safety in such a case).
 | 
					
						
							|  |  |  |             node_constructor a(*this); | 
					
						
							|  |  |  |             a.construct_pair(k, (mapped_type*) 0); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |             // reserve has basic exception safety if the hash function
 | 
					
						
							|  |  |  |             // throws, strong otherwise.
 | 
					
						
							|  |  |  |             if(this->reserve_for_insert(this->size_ + 1)) | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                 bucket_index = hash % this->bucket_count_; | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |             // Nothing after this point can throw.
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |      | 
					
						
							|  |  |  |             return node::get_value(add_node(a, bucket_index, hash)); | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         emplace_return emplace_impl_with_node(node_constructor& a) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // No side effects in this initial code
 | 
					
						
							|  |  |  |             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 pos = this->find_node(bucket_index, hash, k); | 
					
						
							|  |  |  |              | 
					
						
							|  |  |  |             if (BOOST_UNORDERED_BORLAND_BOOL(pos)) { | 
					
						
							|  |  |  |                 // Found an existing key, return it (no throw).
 | 
					
						
							|  |  |  |                 return emplace_return(pos, false); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |             // reserve has basic exception safety if the hash function
 | 
					
						
							|  |  |  |             // throws, strong otherwise.
 | 
					
						
							|  |  |  |             if(this->reserve_for_insert(this->size_ + 1)) | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                 bucket_index = hash % this->bucket_count_; | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |             // Nothing after this point can throw.
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |      | 
					
						
							|  |  |  |             return emplace_return(add_node(a, bucket_index, hash), true); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         emplace_return insert(value_type const& v) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             key_type const& k = extractor::extract(v); | 
					
						
							|  |  |  |             std::size_t hash = this->hash_function()(k); | 
					
						
							|  |  |  |             std::size_t bucket_index = hash % this->bucket_count_; | 
					
						
							|  |  |  |             node_ptr pos = this->find_node(bucket_index, hash, k); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             if (BOOST_UNORDERED_BORLAND_BOOL(pos)) { | 
					
						
							|  |  |  |                 // Found an existing key, return it (no throw).
 | 
					
						
							|  |  |  |                 return emplace_return(pos, false); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             // Isn't in table, add to bucket.
 | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             // Create the node before rehashing in case it throws an
 | 
					
						
							|  |  |  |             // exception (need strong safety in such a case).
 | 
					
						
							|  |  |  |             node_constructor a(*this); | 
					
						
							|  |  |  |             a.construct(v); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             // reserve has basic exception safety if the hash function
 | 
					
						
							|  |  |  |             // throws, strong otherwise.
 | 
					
						
							|  |  |  |             if(this->reserve_for_insert(this->size_ + 1)) | 
					
						
							|  |  |  |                 bucket_index = hash % this->bucket_count_; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             // Nothing after this point can throw.
 | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             return emplace_return(add_node(a, bucket_index, hash), true); | 
					
						
							| 
									
										
										
										
											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> | 
					
						
							|  |  |  |         emplace_return emplace(Args&&... args) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return emplace_impl( | 
					
						
							|  |  |  |                     extractor::extract(std::forward<Args>(args)...), | 
					
						
							|  |  |  |                     std::forward<Args>(args)...); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         template<class... Args> | 
					
						
							|  |  |  |         emplace_return emplace_impl(key_type const& k, Args&&... args) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // No side effects in this initial code
 | 
					
						
							|  |  |  |             std::size_t hash = this->hash_function()(k); | 
					
						
							|  |  |  |             std::size_t bucket_index = hash % this->bucket_count_; | 
					
						
							|  |  |  |             node_ptr pos = this->find_node(bucket_index, hash, k); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             if (BOOST_UNORDERED_BORLAND_BOOL(pos)) { | 
					
						
							|  |  |  |                 // Found an existing key, return it (no throw).
 | 
					
						
							|  |  |  |                 return emplace_return(pos, false); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |             // Doesn't already exist, add to bucket.
 | 
					
						
							|  |  |  |             // Side effects only in this block.
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |             // 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)...); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |             // reserve has basic exception safety if the hash function
 | 
					
						
							|  |  |  |             // throws, strong otherwise.
 | 
					
						
							|  |  |  |             if(this->reserve_for_insert(this->size_ + 1)) | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                 bucket_index = hash % this->bucket_count_; | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |             // Nothing after this point can throw.
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |      | 
					
						
							|  |  |  |             return emplace_return(add_node(a, bucket_index, hash), true); | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         template<class... Args> | 
					
						
							|  |  |  |         emplace_return emplace_impl(no_key, Args&&... args) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // Construct the node regardless - in order to get the key.
 | 
					
						
							|  |  |  |             // It will be discarded if it isn't used
 | 
					
						
							|  |  |  |             node_constructor a(*this); | 
					
						
							|  |  |  |             a.construct(std::forward<Args>(args)...); | 
					
						
							|  |  |  |             return emplace_impl_with_node(a); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         template <class Arg0> | 
					
						
							| 
									
										
										
										
											2011-08-18 19:29:02 +00:00
										 |  |  |         emplace_return emplace(BOOST_FWD_REF(Arg0) arg0) | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2011-08-18 19:29:02 +00:00
										 |  |  |             return emplace_impl( | 
					
						
							|  |  |  |                 extractor::extract(boost::forward<Arg0>(arg0)), | 
					
						
							|  |  |  |                 boost::forward<Arg0>(arg0)); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | #define BOOST_UNORDERED_INSERT1_IMPL(z, n, _)                               \
 | 
					
						
							|  |  |  |         template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)>                      \ | 
					
						
							|  |  |  |         emplace_return emplace(                                             \ | 
					
						
							|  |  |  |             BOOST_UNORDERED_FUNCTION_PARAMS(z, n))                          \ | 
					
						
							|  |  |  |         {                                                                   \ | 
					
						
							|  |  |  |             return emplace_impl(extractor::extract(arg0, arg1),             \ | 
					
						
							|  |  |  |                     BOOST_UNORDERED_CALL_PARAMS(z, n));                     \ | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | #define BOOST_UNORDERED_INSERT2_IMPL(z, n, _)                               \
 | 
					
						
							|  |  |  |         template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)>                      \ | 
					
						
							|  |  |  |         emplace_return emplace_impl(key_type const& k,                      \ | 
					
						
							|  |  |  |            BOOST_UNORDERED_FUNCTION_PARAMS(z, n))                           \ | 
					
						
							|  |  |  |         {                                                                   \ | 
					
						
							|  |  |  |             std::size_t hash = this->hash_function()(k);                    \ | 
					
						
							|  |  |  |             std::size_t bucket_index = hash % this->bucket_count_;          \ | 
					
						
							|  |  |  |             node_ptr pos = this->find_node(bucket_index, hash, k);          \ | 
					
						
							|  |  |  |                                                                             \ | 
					
						
							|  |  |  |             if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {                        \ | 
					
						
							|  |  |  |                 return emplace_return(pos, false);                          \ | 
					
						
							|  |  |  |             } else {                                                        \ | 
					
						
							|  |  |  |                 node_constructor a(*this);                                  \ | 
					
						
							|  |  |  |                 a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n));             \ | 
					
						
							|  |  |  |                                                                             \ | 
					
						
							|  |  |  |                 if(this->reserve_for_insert(this->size_ + 1))               \ | 
					
						
							|  |  |  |                     bucket_index = hash % this->bucket_count_;              \ | 
					
						
							|  |  |  |                                                                             \ | 
					
						
							|  |  |  |                 return emplace_return(                                      \ | 
					
						
							|  |  |  |                     add_node(a, bucket_index, hash),                        \ | 
					
						
							|  |  |  |                     true);                                                  \ | 
					
						
							|  |  |  |             }                                                               \ | 
					
						
							|  |  |  |         }                                                                   \ | 
					
						
							|  |  |  |                                                                             \ | 
					
						
							|  |  |  |         template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)>                      \ | 
					
						
							|  |  |  |         emplace_return emplace_impl(no_key,                                 \ | 
					
						
							|  |  |  |            BOOST_UNORDERED_FUNCTION_PARAMS(z, n))                           \ | 
					
						
							|  |  |  |         {                                                                   \ | 
					
						
							|  |  |  |             node_constructor a(*this);                                      \ | 
					
						
							|  |  |  |             a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n));                 \ | 
					
						
							|  |  |  |             return emplace_impl_with_node(a);                               \ | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT, | 
					
						
							|  |  |  |             BOOST_UNORDERED_INSERT1_IMPL, _) | 
					
						
							|  |  |  |         BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, | 
					
						
							|  |  |  |             BOOST_UNORDERED_INSERT2_IMPL, _) | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | #undef BOOST_UNORDERED_INSERT1_IMPL
 | 
					
						
							|  |  |  | #undef BOOST_UNORDERED_INSERT2_IMPL
 | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-10-21 20:23:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         ////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |         // Insert range methods
 | 
					
						
							|  |  |  |         //
 | 
					
						
							|  |  |  |         // if hash function throws, or inserting > 1 element, basic exception
 | 
					
						
							|  |  |  |         // safety strong otherwise
 | 
					
						
							| 
									
										
										
										
											2010-10-21 20:23:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         template <class InputIt> | 
					
						
							|  |  |  |         void insert_range(InputIt i, InputIt j) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if(i != j) | 
					
						
							|  |  |  |                 return insert_range_impl(extractor::extract(*i), i, j); | 
					
						
							| 
									
										
										
										
											2010-10-21 20:23:37 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         template <class InputIt> | 
					
						
							|  |  |  |         void insert_range_impl(key_type const&, InputIt i, InputIt j) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             node_constructor a(*this); | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // Special case for empty buckets so that we can use
 | 
					
						
							|  |  |  |             // max_load_ (which isn't valid when buckets_ is null).
 | 
					
						
							|  |  |  |             if (!this->buckets_) { | 
					
						
							|  |  |  |                 insert_range_empty(a, extractor::extract(*i), i, j); | 
					
						
							|  |  |  |                 if (++i == j) return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             do { | 
					
						
							|  |  |  |                 // Note: can't use get_key as '*i' might not be value_type - it
 | 
					
						
							|  |  |  |                 // could be a pair with first_types as key_type without const or a
 | 
					
						
							|  |  |  |                 // different second_type.
 | 
					
						
							|  |  |  |                 //
 | 
					
						
							|  |  |  |                 // TODO: Might be worth storing the value_type instead of the key
 | 
					
						
							|  |  |  |                 // here. Could be more efficient if '*i' is expensive. Could be
 | 
					
						
							|  |  |  |                 // less efficient if copying the full value_type is expensive.
 | 
					
						
							|  |  |  |                 insert_range_impl2(a, extractor::extract(*i), i, j); | 
					
						
							|  |  |  |             } while(++i != j); | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:29 +00:00
										 |  |  |         template <class InputIt> | 
					
						
							|  |  |  |         void insert_range_empty(node_constructor& a, key_type const& k, | 
					
						
							|  |  |  |             InputIt i, InputIt j) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             std::size_t hash = this->hash_function()(k); | 
					
						
							|  |  |  |             a.construct(*i); | 
					
						
							|  |  |  |             this->reserve_for_insert(this->size_ + insert_size(i, j)); | 
					
						
							|  |  |  |             add_node(a, hash % this->bucket_count_, hash); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         template <class InputIt> | 
					
						
							|  |  |  |         void insert_range_impl2(node_constructor& a, key_type const& k, | 
					
						
							|  |  |  |             InputIt i, InputIt j) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // No side effects in this initial code
 | 
					
						
							|  |  |  |             std::size_t hash = this->hash_function()(k); | 
					
						
							|  |  |  |             std::size_t bucket_index = hash % this->bucket_count_; | 
					
						
							|  |  |  |             node_ptr pos = this->find_node(bucket_index, hash, k); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             if (!BOOST_UNORDERED_BORLAND_BOOL(pos)) { | 
					
						
							|  |  |  |                 // Doesn't already exist, add to bucket.
 | 
					
						
							|  |  |  |                 // Side effects only in this block.
 | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |                 // Create the node before rehashing in case it throws an
 | 
					
						
							|  |  |  |                 // exception (need strong safety in such a case).
 | 
					
						
							|  |  |  |                 a.construct(*i); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |                 // reserve has basic exception safety if the hash function
 | 
					
						
							|  |  |  |                 // throws, strong otherwise.
 | 
					
						
							|  |  |  |                 if(this->size_ + 1 >= this->max_load_) { | 
					
						
							|  |  |  |                     this->reserve_for_insert(this->size_ + insert_size(i, j)); | 
					
						
							|  |  |  |                     bucket_index = hash % this->bucket_count_; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |                 // Nothing after this point can throw.
 | 
					
						
							|  |  |  |                 add_node(a, bucket_index, hash); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         template <class InputIt> | 
					
						
							|  |  |  |         void insert_range_impl(no_key, InputIt i, InputIt j) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             node_constructor a(*this); | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             do { | 
					
						
							|  |  |  |                 // No side effects in this initial code
 | 
					
						
							|  |  |  |                 a.construct(*i); | 
					
						
							|  |  |  |                 emplace_impl_with_node(a); | 
					
						
							|  |  |  |             } while(++i != j); | 
					
						
							| 
									
										
										
										
											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 H, class P, class A> | 
					
						
							|  |  |  |     struct set : 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
										 |  |  |         true> | 
					
						
							|  |  |  |     {         | 
					
						
							|  |  |  |         typedef ::boost::unordered::detail::unique_table<set<H, P, A> > impl; | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |         typedef ::boost::unordered::detail::table<set<H, P, A> > table_base; | 
					
						
							| 
									
										
										
										
											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 K, class H, class P, class A> | 
					
						
							|  |  |  |     struct map : 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
										 |  |  |         true> | 
					
						
							| 
									
										
										
										
											2010-05-21 07:06:33 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         typedef ::boost::unordered::detail::unique_table<map<K, H, P, A> > impl; | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |         typedef ::boost::unordered::detail::table<map<K, H, P, A> > table_base; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |     }; | 
					
						
							|  |  |  | }}} | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #endif
 |