Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r56329 - in trunk: boost/unordered boost/unordered/detail libs/unordered/test/helpers libs/unordered/test/unordered
From: daniel_james_at_[hidden]
Date: 2009-09-20 17:55:18


Author: danieljames
Date: 2009-09-20 17:55:15 EDT (Sun, 20 Sep 2009)
New Revision: 56329
URL: http://svn.boost.org/trac/boost/changeset/56329

Log:
Since all the compilers support out of line template members use them
and lots of other things.
Added:
   trunk/boost/unordered/detail/equivalent.hpp (contents, props changed)
   trunk/boost/unordered/detail/unique.hpp (contents, props changed)
Removed:
   trunk/boost/unordered/detail/insert.hpp
Text files modified:
   trunk/boost/unordered/detail/allocator_helpers.hpp | 3
   trunk/boost/unordered/detail/buckets.hpp | 263 ++++---------
   trunk/boost/unordered/detail/extract_key.hpp | 25 +
   trunk/boost/unordered/detail/fwd.hpp | 715 +++++++++++++++++++++++++++++++--------
   trunk/boost/unordered/detail/move.hpp | 2
   trunk/boost/unordered/detail/node.hpp | 151 +++-----
   trunk/boost/unordered/detail/table.hpp | 648 ++++++++++++++++++-----------------
   trunk/boost/unordered/detail/util.hpp | 108 ++---
   trunk/boost/unordered/unordered_map.hpp | 320 ++++++++++-------
   trunk/boost/unordered/unordered_set.hpp | 295 +++++++++-------
   trunk/libs/unordered/test/helpers/list.hpp | 13
   trunk/libs/unordered/test/unordered/erase_equiv_tests.cpp | 2
   trunk/libs/unordered/test/unordered/out_of_line.cpp | 2
   13 files changed, 1462 insertions(+), 1085 deletions(-)

Modified: trunk/boost/unordered/detail/allocator_helpers.hpp
==============================================================================
--- trunk/boost/unordered/detail/allocator_helpers.hpp (original)
+++ trunk/boost/unordered/detail/allocator_helpers.hpp 2009-09-20 17:55:15 EDT (Sun, 20 Sep 2009)
@@ -99,7 +99,8 @@
         }
     private:
         allocator_array_constructor(allocator_array_constructor const&);
- allocator_array_constructor& operator=(allocator_array_constructor const&);
+ allocator_array_constructor& operator=(
+ allocator_array_constructor const&);
     };
 }}
 

Modified: trunk/boost/unordered/detail/buckets.hpp
==============================================================================
--- trunk/boost/unordered/detail/buckets.hpp (original)
+++ trunk/boost/unordered/detail/buckets.hpp 2009-09-20 17:55:15 EDT (Sun, 20 Sep 2009)
@@ -14,199 +14,56 @@
 namespace boost { namespace unordered_detail {
     
     ////////////////////////////////////////////////////////////////////////////
- // Explicitly call a destructor
-
-#if defined(BOOST_MSVC)
-# define BOOST_UNORDERED_DESTRUCT(x, type) (x)->~type();
-#else
-# define BOOST_UNORDERED_DESTRUCT(x, type) boost::unordered_detail::destroy(x)
- template <class T>
- void destroy(T* x) {
- x->~T();
- }
-#endif
-
- // Constructors
-
- template <class A, class G>
- hash_buckets<A, G>::hash_buckets(node_allocator const& a, std::size_t bucket_count)
- : buckets_(), allocators_(a,a)
- {
- // The array constructor will clean up in the event of an
- // exception.
- allocator_array_constructor<bucket_allocator>
- constructor(bucket_alloc());
-
- // Creates an extra bucket to act as a sentinel.
- constructor.construct(bucket(), bucket_count + 1);
-
- // Set up the sentinel (node_ptr cast)
- bucket_ptr sentinel = constructor.get() + static_cast<ptrdiff_t>(bucket_count);
- sentinel->next_ = sentinel;
-
- // Only release the buckets once everything is successfully
- // done.
- this->buckets_ = constructor.release();
- this->bucket_count_ = bucket_count;
- }
-
- template <class A, class G>
- hash_buckets<A, G>::hash_buckets(hash_buckets& x, move_tag)
- : buckets_(), allocators_(x.allocators_)
- {
- this->buckets_ = x.buckets_;
- this->bucket_count_ = x.bucket_count_;
- x.buckets_ = bucket_ptr();
- x.bucket_count_ = 0;
- }
-
- template <class A, class G>
- hash_buckets<A, G>::hash_buckets(hash_buckets& x, value_allocator const& a, move_tag) :
- buckets_(), allocators_(a,a)
- {
- if(this->node_alloc() == x.node_alloc()) {
- this->buckets_ = x.buckets_;
- this->bucket_count_ = x.bucket_count_;
- x.buckets_ = bucket_ptr();
- x.bucket_count_ = 0;
- }
- }
-
- template <class A, class G>
- hash_buckets<A, G>::~hash_buckets()
- {
- if(this->buckets_) { delete_buckets(); }
- }
-
- // no throw
- template <class A, class G>
- inline void hash_buckets<A, G>::move(hash_buckets& other)
- {
- BOOST_ASSERT(node_alloc() == other.node_alloc());
- delete_buckets();
- this->buckets_ = other.buckets_;
- this->bucket_count_ = other.bucket_count_;
- other.buckets_ = bucket_ptr();
- other.bucket_count_ = 0;
- }
-
- template <class A, class G>
- inline void hash_buckets<A, G>::swap(hash_buckets<A, G>& other)
- {
- BOOST_ASSERT(node_alloc() == other.node_alloc());
- std::swap(buckets_, other.buckets_);
- std::swap(bucket_count_, other.bucket_count_);
- }
-
     // Buckets
+ // TODO: Are these needed?
     
     template <class A, class G>
- inline std::size_t hash_buckets<A, G>::bucket_count() const
- {
- return bucket_count_;
- }
-
- template <class A, class G>
- inline std::size_t hash_buckets<A, G>::bucket_from_hash(std::size_t hashed) const
+ inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
+ hash_buckets<A, G>::get_bucket(std::size_t n) const
     {
- return hashed % bucket_count_;
+ return buckets_ + static_cast<std::ptrdiff_t>(n);
     }
 
     template <class A, class G>
     inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
         hash_buckets<A, G>::bucket_ptr_from_hash(std::size_t hashed) const
     {
- return buckets_ + static_cast<std::ptrdiff_t>(
- bucket_from_hash(hashed));
+ return get_bucket(hashed % bucket_count_);
     }
     
     template <class A, class G>
- inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
- hash_buckets<A, G>::buckets_begin() const
- {
- return buckets_;
- }
-
- template <class A, class G>
- inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
- hash_buckets<A, G>::buckets_end() const
- {
- return buckets_ + static_cast<std::ptrdiff_t>(bucket_count_);
- }
-
- template <class A, class G>
     inline std::size_t hash_buckets<A, G>::bucket_size(std::size_t index) const
     {
- bucket_ptr ptr = (buckets_ + static_cast<std::ptrdiff_t>(index))->next_;
+ if(!buckets_) return 0;
+ bucket_ptr ptr = get_bucket(index)->next_;
         std::size_t count = 0;
         while(ptr) {
             ++count;
- ptr = next_node(ptr);
+ ptr = ptr->next_;
         }
         return count;
     }
 
     template <class A, class G>
- inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
- hash_buckets<A, G>::get_bucket(std::size_t n) const
- {
- return buckets_ + static_cast<std::ptrdiff_t>(n);
- }
-
- template <class A, class G>
     inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::node_ptr
         hash_buckets<A, G>::bucket_begin(std::size_t n) const
     {
- return (buckets_ + static_cast<std::ptrdiff_t>(n))->next_;
+ return buckets_ ? get_bucket(n)->next_ : node_ptr();
     }
 
- template <class A, class G>
- inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::node_ptr
- hash_buckets<A, G>::bucket_end(std::size_t) const
- {
- return node_ptr();
- }
+ ////////////////////////////////////////////////////////////////////////////
+ // Delete
 
- // Construct/destruct
-
     template <class A, class G>
- inline void hash_buckets<A, G>::destruct_node(node_ptr b)
+ inline void hash_buckets<A, G>::delete_node(node_ptr b)
     {
         node* raw_ptr = static_cast<node*>(&*b);
- BOOST_UNORDERED_DESTRUCT(&raw_ptr->value(), value_type);
+ boost::unordered_detail::destroy(&raw_ptr->value());
         real_node_ptr n(node_alloc().address(*raw_ptr));
         node_alloc().destroy(n);
         node_alloc().deallocate(n, 1);
     }
 
- // Delete and clear buckets
-
- template <class A, class G>
- inline void hash_buckets<A, G>::delete_group(node_ptr first_node)
- {
- delete_nodes(first_node, node::next_group(first_node));
- }
-
- template <class A, class G>
- inline void hash_buckets<A, G>::delete_nodes(node_ptr begin, node_ptr end)
- {
- while(begin != end) {
- node_ptr node = begin;
- begin = next_node(begin);
- destruct_node(node);
- }
- }
-
- template <class A, class G>
- inline void hash_buckets<A, G>::delete_to_bucket_end(node_ptr begin)
- {
- while(BOOST_UNORDERED_BORLAND_BOOL(begin)) {
- node_ptr node = begin;
- begin = next_node(begin);
- destruct_node(node);
- }
- }
-
     template <class A, class G>
     inline void hash_buckets<A, G>::clear_bucket(bucket_ptr b)
     {
@@ -214,48 +71,106 @@
         b->next_ = node_ptr();
 
         while(node_it) {
- node_ptr node_to_destruct = node_it;
- node_it = next_node(node_it);
- destruct_node(node_to_destruct);
+ node_ptr node_to_delete = node_it;
+ node_it = node_it->next_;
+ delete_node(node_to_delete);
         }
     }
 
     template <class A, class G>
     inline void hash_buckets<A, G>::delete_buckets()
     {
- for(bucket_ptr begin = this->buckets_begin(), end = this->buckets_end(); begin != end; ++begin) {
+ bucket_ptr end = this->get_bucket(this->bucket_count_);
+
+ for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
             clear_bucket(begin);
         }
 
         // Destroy the buckets (including the sentinel bucket).
- bucket_ptr end = this->buckets_end();
         ++end;
- for(bucket_ptr begin = this->buckets_begin(); begin != end; ++begin) {
+ for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
             bucket_alloc().destroy(begin);
         }
 
- bucket_alloc().deallocate(this->buckets_begin(), this->bucket_count() + 1);
+ bucket_alloc().deallocate(this->buckets_, this->bucket_count_ + 1);
 
         this->buckets_ = bucket_ptr();
     }
 
+ template <class A, class G>
+ inline std::size_t hash_buckets<A, G>::delete_nodes(
+ node_ptr begin, node_ptr end)
+ {
+ std::size_t count = 0;
+ while(begin != end) {
+ node_ptr node = begin;
+ begin = begin->next_;
+ delete_node(node);
+ ++count;
+ }
+ return count;
+ }
+
     ////////////////////////////////////////////////////////////////////////////
- // hash_iterator_base implementation
+ // Constructors and Destructors
+
+ template <class A, class G>
+ inline hash_buckets<A, G>::hash_buckets(
+ node_allocator const& a, std::size_t bucket_count)
+ : buckets_(),
+ bucket_count_(bucket_count),
+ allocators_(a,a)
+ {
+ }
+
+ template <class A, class G>
+ inline hash_buckets<A, G>::~hash_buckets()
+ {
+ if(this->buckets_) { this->delete_buckets(); }
+ }
     
- template <class BucketPtr>
- inline void hash_iterator_base<BucketPtr>::increment(node_ptr node) {
- while(!node) {
- ++bucket_;
- node = bucket_->next_;
- }
+ template <class A, class G>
+ inline void hash_buckets<A, G>::create_buckets()
+ {
+ // The array constructor will clean up in the event of an
+ // exception.
+ allocator_array_constructor<bucket_allocator>
+ constructor(bucket_alloc());
+
+ // Creates an extra bucket to act as a sentinel.
+ constructor.construct(bucket(), this->bucket_count_ + 1);
+
+ // Set up the sentinel (node_ptr cast)
+ bucket_ptr sentinel = constructor.get() +
+ static_cast<ptrdiff_t>(this->bucket_count_);
+ sentinel->next_ = sentinel;
+
+ // Only release the buckets once everything is successfully
+ // done.
+ this->buckets_ = constructor.release();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Constructors and Destructors
 
- node_ = node;
+ // no throw
+ template <class A, class G>
+ inline void hash_buckets<A, G>::move(hash_buckets& other)
+ {
+ BOOST_ASSERT(node_alloc() == other.node_alloc());
+ if(this->buckets_) { this->delete_buckets(); }
+ this->buckets_ = other.buckets_;
+ this->bucket_count_ = other.bucket_count_;
+ other.buckets_ = bucket_ptr();
+ other.bucket_count_ = 0;
     }
 
- template <class BucketPtr>
- inline void hash_iterator_base<BucketPtr>::increment()
+ template <class A, class G>
+ inline void hash_buckets<A, G>::swap(hash_buckets<A, G>& other)
     {
- increment(next_node(node_));
+ BOOST_ASSERT(node_alloc() == other.node_alloc());
+ std::swap(buckets_, other.buckets_);
+ std::swap(bucket_count_, other.bucket_count_);
     }
 }}
 

Added: trunk/boost/unordered/detail/equivalent.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/unordered/detail/equivalent.hpp 2009-09-20 17:55:15 EDT (Sun, 20 Sep 2009)
@@ -0,0 +1,271 @@
+
+// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
+// Copyright (C) 2005-2009 Daniel James
+// 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/table.hpp>
+#include <boost/unordered/detail/extract_key.hpp>
+
+namespace boost { namespace unordered_detail {
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Equality
+
+ template <class H, class P, class A, class K>
+ bool hash_equivalent_table<H, P, A, K>
+ ::equals(hash_equivalent_table<H, P, A, K> const& other) const
+ {
+ if(this->size_ != other.size_) return false;
+ if(!this->size_) return true;
+
+ bucket_ptr end = this->get_bucket(this->bucket_count_);
+ for(bucket_ptr i = this->cached_begin_bucket_; i != end; ++i)
+ {
+ node_ptr it1 = i->next_;
+ while(BOOST_UNORDERED_BORLAND_BOOL(it1))
+ {
+ node_ptr it2 = other.find_iterator(get_key_from_ptr(it1));
+ if(!BOOST_UNORDERED_BORLAND_BOOL(it2)) return false;
+
+ node_ptr end1 = node::next_group(it1);
+ node_ptr end2 = node::next_group(it2);
+
+ do {
+ if(!extractor::compare_mapped(
+ node::get_value(it1), node::get_value(it2)))
+ return false;
+ it1 = it1->next_;
+ it2 = it2->next_;
+ } while(it1 != end1 && it2 != end2);
+ if(it1 != end1 || it2 != end2) return false;
+ }
+ }
+
+ return true;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // A convenience method for adding nodes.
+
+ template <class H, class P, class A, class K>
+ inline BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::node_ptr
+ hash_equivalent_table<H, P, A, K>
+ ::add_node(node_constructor& a, bucket_ptr bucket, node_ptr pos)
+ {
+ node_ptr n = a.release();
+ if(BOOST_UNORDERED_BORLAND_BOOL(pos)) {
+ node::add_after_node(n, pos);
+ }
+ else {
+ node::add_to_bucket(n, *bucket);
+ if(bucket < this->cached_begin_bucket_)
+ this->cached_begin_bucket_ = bucket;
+ }
+ ++this->size_;
+ return n;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Insert methods
+
+ template <class H, class P, class A, class K>
+ inline BOOST_DEDUCED_TYPENAME
+ hash_equivalent_table<H, P, A, K>::iterator_base
+ hash_equivalent_table<H, P, A, K>::emplace_impl(node_constructor& a)
+ {
+ key_type const& k = get_key(a.value());
+ std::size_t hash_value = this->hash_function()(k);
+
+ if(!this->size_) {
+ return this->emplace_empty_impl_with_node(a, 1);
+ }
+ else {
+ bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
+ node_ptr position = find_iterator(bucket, k);
+
+ // reserve has basic exception safety if the hash function
+ // throws, strong otherwise.
+ if(this->reserve_for_insert(this->size_ + 1))
+ bucket = this->bucket_ptr_from_hash(hash_value);
+
+ return iterator_base(bucket, add_node(a, bucket, position));
+ }
+ }
+
+ template <class H, class P, class A, class K>
+ inline BOOST_DEDUCED_TYPENAME
+ hash_equivalent_table<H, P, A, K>::iterator_base
+ hash_equivalent_table<H, P, A, K>
+ ::emplace_hint_impl(iterator_base const& it, node_constructor& a)
+ {
+ // equal can throw, but with no effects
+ if (!it.node_ || !equal(get_key(a.value()), *it)) {
+ // Use the standard emplace if the iterator doesn't point
+ // to a matching key.
+ return emplace_impl(a);
+ }
+ else {
+ // Find the first node in the group - so that the node
+ // will be added at the end of the group.
+
+ node_ptr start = node::first_in_group(it.node_);
+
+ // reserve has basic exception safety if the hash function
+ // throws, strong otherwise.
+ bucket_ptr bucket = this->reserve_for_insert(this->size_ + 1) ?
+ get_bucket(this->bucket_index(get_key(a.value()))) :
+ it.bucket_;
+
+ // Nothing after this point can throw
+
+ return iterator_base(bucket, add_node(a, bucket, start));
+ }
+ }
+
+ template <class H, class P, class A, class K>
+ inline void hash_equivalent_table<H, P, A, K>
+ ::emplace_impl_no_rehash(node_constructor& a)
+ {
+ key_type const& k = get_key(a.value());
+ bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
+ add_node(a, bucket, find_iterator(bucket, k));
+ }
+
+#if defined(BOOST_UNORDERED_STD_FORWARD)
+
+ // Emplace (equivalent key containers)
+ // (I'm using an overloaded emplace for both 'insert' and 'emplace')
+
+ // if hash function throws, basic exception safety
+ // strong otherwise
+ template <class H, class P, class A, class K>
+ template <class... Args>
+ BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::iterator_base
+ hash_equivalent_table<H, P, A, K>
+ ::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);
+ }
+
+ // Emplace (equivalent key containers)
+ // (I'm using an overloaded emplace for both 'insert' and 'emplace')
+
+ // if hash function throws, basic exception safety
+ // strong otherwise
+ template <class H, class P, class A, class K>
+ template <class... Args>
+ BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::iterator_base
+ hash_equivalent_table<H, P, A, K>
+ ::emplace_hint(iterator_base const& it, 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_hint_impl(it, a);
+ }
+
+#else
+
+#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
+ template <class H, class P, class A, class K> \
+ template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
+ BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::iterator_base \
+ hash_equivalent_table<H, P, A, K> \
+ ::emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
+ { \
+ node_constructor a(*this); \
+ a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
+ return emplace_impl(a); \
+ } \
+ \
+ template <class H, class P, class A, class K> \
+ template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
+ BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::iterator_base \
+ hash_equivalent_table<H, P, A, K> \
+ ::emplace_hint(iterator_base const& it, \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
+ { \
+ node_constructor a(*this); \
+ a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
+ return emplace_hint_impl(it, a); \
+ }
+
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
+ BOOST_UNORDERED_INSERT_IMPL, _)
+
+#undef BOOST_UNORDERED_INSERT_IMPL
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Insert range methods
+
+ // if hash function throws, or inserting > 1 element, basic exception safety
+ // strong otherwise
+ template <class H, class P, class A, class K>
+ template <class I>
+ inline void hash_equivalent_table<H, P, A, K>
+ ::insert_for_range(I i, I j, forward_traversal_tag)
+ {
+ if(i == j) return;
+ std::size_t distance = unordered_detail::distance(i, j);
+ if(distance == 1) {
+ emplace(*i);
+ }
+ else {
+ node_constructor a(*this);
+
+ // Only require basic exception safety here
+ if(this->size_) {
+ this->reserve_for_insert(this->size_ + distance);
+ }
+ else {
+ a.construct(*i++);
+ this->emplace_empty_impl_with_node(a, distance);
+ }
+
+ for (; i != j; ++i) {
+ a.construct(*i);
+ emplace_impl_no_rehash(a);
+ }
+ }
+ }
+
+ // if hash function throws, or inserting > 1 element, basic exception safety
+ // strong otherwise
+ template <class H, class P, class A, class K>
+ template <class I>
+ inline void hash_equivalent_table<H, P, A, K>
+ ::insert_for_range(I i, I j, boost::incrementable_traversal_tag)
+ {
+ node_constructor a(*this);
+ for (; i != j; ++i) {
+ a.construct(*i);
+ emplace_impl(a);
+ }
+ }
+
+ // if hash function throws, or inserting > 1 element, basic exception safety
+ // strong otherwise
+ // TODO: Should I special case an empty container?
+ template <class H, class P, class A, class K>
+ template <class I>
+ void hash_equivalent_table<H, P, A, K>::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);
+ }
+}}
+
+#endif

Modified: trunk/boost/unordered/detail/extract_key.hpp
==============================================================================
--- trunk/boost/unordered/detail/extract_key.hpp (original)
+++ trunk/boost/unordered/detail/extract_key.hpp 2009-09-20 17:55:15 EDT (Sun, 20 Sep 2009)
@@ -66,6 +66,11 @@
                 return no_key();
             }
     #endif
+
+ static bool compare_mapped(value_type const&, value_type const&)
+ {
+ return true;
+ }
         };
     };
 
@@ -75,7 +80,9 @@
         struct apply
         {
             typedef ValueType value_type;
- typedef BOOST_DEDUCED_TYPENAME remove_const<BOOST_DEDUCED_TYPENAME ValueType::first_type>::type key_type;
+ typedef BOOST_DEDUCED_TYPENAME
+ remove_const<BOOST_DEDUCED_TYPENAME ValueType::first_type>::type
+ key_type;
 
             static key_type const& extract(value_type const& v)
             {
@@ -94,19 +101,22 @@
             }
 
             template <class Second>
- static key_type const& extract(std::pair<key_type const, Second> const& v)
+ static key_type const& extract(
+ std::pair<key_type const, Second> const& v)
             {
                 return v.first;
             }
 /*
             template <class Second>
- static key_type const& extract(std::pair<key_type&, Second> const& v)
+ static key_type const& extract(
+ std::pair<key_type&, Second> const& v)
             {
                 return v.first;
             }
 
             template <class Second>
- static key_type const& extract(std::pair<key_type const&, Second> const& v)
+ static key_type const& extract(
+ std::pair<key_type const&, Second> const& v)
             {
                 return v.first;
             }
@@ -114,7 +124,8 @@
 
 #if defined(BOOST_UNORDERED_STD_FORWARD)
             template <class Arg1, class... Args>
- static key_type const& extract(key_type const& k, Arg1 const&, Args const&...)
+ static key_type const& extract(key_type const& k,
+ Arg1 const&, Args const&...)
             {
                 return k;
             }
@@ -149,6 +160,10 @@
             }
 #endif
 
+ static bool compare_mapped(value_type const& x, value_type const& y)
+ {
+ return x.second == y.second;
+ }
         };
     };
 }}

Modified: trunk/boost/unordered/detail/fwd.hpp
==============================================================================
--- trunk/boost/unordered/detail/fwd.hpp (original)
+++ trunk/boost/unordered/detail/fwd.hpp 2009-09-20 17:55:15 EDT (Sun, 20 Sep 2009)
@@ -18,6 +18,7 @@
 #include <boost/type_traits/aligned_storage.hpp>
 #include <boost/type_traits/alignment_of.hpp>
 #include <boost/unordered/detail/allocator_helpers.hpp>
+#include <algorithm>
 
 // This header defines most of the classes used to implement the unordered
 // containers. It doesn't include the insert methods as they require a lot
@@ -31,8 +32,6 @@
 // G = Grouped/Ungrouped
 // K = Key Extractor
 
-#include <boost/config.hpp>
-
 #if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
 # if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
         // STLport doesn't have std::forward.
@@ -45,12 +44,51 @@
 #define BOOST_UNORDERED_EMPLACE_LIMIT 10
 #endif
 
+#if !defined(BOOST_UNORDERED_STD_FORWARD)
+
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+
+#define BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, class Arg)
+#define BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
+ BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, const& arg)
+#define BOOST_UNORDERED_CALL_PARAMS(z, n) \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, arg)
+
+#endif
+
 namespace boost { namespace unordered_detail {
 
     static const float minimum_max_load_factor = 1e-3f;
- static const std::size_t default_initial_bucket_count = 11;
+ static const std::size_t default_bucket_count = 11;
     struct move_tag {};
 
+ template <class Alloc, class Grouped>
+ class hash_node_constructor;
+ struct set_extractor;
+ struct map_extractor;
+ struct no_key;
+
+ // Explicitly call a destructor
+
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+#if BOOST_MSVC >= 1400
+#pragma warning(disable:4100) // unreferenced formal parameter
+#endif
+#endif
+
+ template <class T>
+ inline void destroy(T* x) {
+ x->~T();
+ }
+
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#endif
+
     // hash_bucket
     
     template <class A>
@@ -70,8 +108,11 @@
         hash_bucket() : next_() {}
         
         // Only copy construct when allocating.
- hash_bucket(hash_bucket const& x) : next_()
- { BOOST_ASSERT(!x.next_); }
+ hash_bucket(hash_bucket const& x)
+ : next_()
+ {
+ BOOST_ASSERT(!x.next_);
+ }
     };
 
     template <class A>
@@ -84,12 +125,10 @@
         static inline node_ptr& next_group(node_ptr ptr);
         static inline std::size_t group_count(node_ptr ptr);
         static inline void add_to_bucket(node_ptr n, bucket& b);
- static inline void add_group_to_bucket(node_ptr n, bucket& b);
         static inline void add_after_node(node_ptr n, node_ptr position);
         static void unlink_node(bucket& b, node_ptr node);
         static void unlink_nodes(bucket& b, node_ptr begin, node_ptr end);
         static void unlink_nodes(bucket& b, node_ptr end);
- static inline void unlink_group(node_ptr* b);
     };
 
     template <class A>
@@ -102,21 +141,20 @@
         node_ptr group_prev_;
 
         grouped_node_base() : bucket(), group_prev_() {}
- static inline node_ptr& group_prev(node_ptr ptr);
         static inline node_ptr& next_group(node_ptr ptr);
+ static inline node_ptr first_in_group(node_ptr n);
         static inline std::size_t group_count(node_ptr ptr);
         static inline void add_to_bucket(node_ptr n, bucket& b);
- static inline void add_group_to_bucket(node_ptr n, bucket& b);
         static inline void add_after_node(node_ptr n, node_ptr position);
         static void unlink_node(bucket& b, node_ptr node);
         static void unlink_nodes(bucket& b, node_ptr begin, node_ptr end);
         static void unlink_nodes(bucket& b, node_ptr end);
- static inline void unlink_group(node_ptr* b);
 
     private:
         static inline node_ptr split_group(node_ptr split);
- static inline grouped_node_base& get(node_ptr ptr)
- { return static_cast<grouped_node_base&>(*ptr); }
+ static inline grouped_node_base& get(node_ptr ptr) {
+ return static_cast<grouped_node_base&>(*ptr);
+ }
     };
 
     struct ungrouped
@@ -143,44 +181,73 @@
             sizeof(value_type),
             ::boost::alignment_of<value_type>::value>::type data_;
 
- void* address() { return this; }
- value_type& value() { return *(ValueType*) this; }
+ void* address() {
+ return this;
+ }
+ value_type& value() {
+ return *(ValueType*) this;
+ }
     };
 
     // Node
-
- template <class NodeBase, class ValueType>
- class hash_node : public NodeBase, public value_base<ValueType>
+
+ template <class A, class G>
+ class hash_node :
+ public G::BOOST_NESTED_TEMPLATE base<A>::type,
+ public value_base<BOOST_DEDUCED_TYPENAME A::value_type>
     {
     public:
- typedef ValueType value_type;
- typedef BOOST_DEDUCED_TYPENAME NodeBase::node_ptr node_ptr;
+ typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
+ typedef BOOST_DEDUCED_TYPENAME hash_bucket<A>::node_ptr node_ptr;
 
- static value_type& get_value(node_ptr p) { return static_cast<hash_node&>(*p).value(); }
+ static value_type& get_value(node_ptr p) {
+ return static_cast<hash_node&>(*p).value();
+ }
     };
 
     // Iterator Base
 
- template <class BucketPtr>
+ template <class A, class G>
     class hash_iterator_base
     {
     public:
- typedef BucketPtr bucket_ptr;
- typedef BucketPtr node_ptr;
+ typedef A value_allocator;
+ typedef hash_bucket<A> bucket;
+ typedef hash_node<A, G> node;
+ typedef BOOST_DEDUCED_TYPENAME node::value_type value_type;
+ typedef BOOST_DEDUCED_TYPENAME node::bucket_ptr bucket_ptr;
+ typedef BOOST_DEDUCED_TYPENAME node::node_ptr node_ptr;
 
         bucket_ptr bucket_;
         node_ptr node_;
 
         hash_iterator_base() : bucket_(), node_() {}
- explicit hash_iterator_base(bucket_ptr b) : bucket_(b), node_(b->next_) {}
- hash_iterator_base(bucket_ptr b, node_ptr n) : bucket_(b), node_(n) {}
-
- bool operator==(hash_iterator_base const& x) const { return node_ == x.node_; }
- bool operator!=(hash_iterator_base const& x) const { return node_ != x.node_; }
- bool is_end() const { return node_ == bucket_; }
- node_ptr get() const { return node_; }
- void increment(node_ptr node);
- void increment();
+ explicit hash_iterator_base(bucket_ptr b)
+ : bucket_(b),
+ node_(b ? b->next_ : node_ptr()) {}
+ hash_iterator_base(bucket_ptr b, node_ptr n)
+ : bucket_(b),
+ node_(n) {}
+
+ bool operator==(hash_iterator_base const& x) const {
+ return node_ == x.node_; }
+ bool operator!=(hash_iterator_base const& x) const {
+ return node_ != x.node_; }
+ value_type& operator*() const {
+ return node::get_value(node_);
+ }
+
+ void increment_bucket(node_ptr node) {
+ while(!node) {
+ ++bucket_;
+ node = bucket_->next_;
+ }
+ node_ = bucket_ == node ? node_ptr() : node;
+ }
+
+ void increment() {
+ increment_bucket(node_->next_);
+ }
     };
 
     // hash_buckets
@@ -188,9 +255,10 @@
     // This is responsible for allocating and deallocating buckets and nodes.
     //
     // Notes:
- // 1. For the sake exception safety the allocators themselves don't allocate anything.
- // 2. It's the callers responsibility to allocate the buckets before calling any of the
- // methods (other than getters and setters).
+ // 1. For the sake exception safety the allocators themselves don't allocate
+ // anything.
+ // 2. It's the callers responsibility to allocate the buckets before calling
+ // any of the methods (other than getters and setters).
 
     template <class A, class G>
     class hash_buckets
@@ -201,22 +269,19 @@
         // Types
 
         typedef A value_allocator;
- typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
-
         typedef hash_bucket<A> bucket;
- typedef BOOST_DEDUCED_TYPENAME G::BOOST_NESTED_TEMPLATE base<A>::type
- node_base;
- typedef hash_node<node_base, value_type> node;
+ typedef hash_iterator_base<A, G> iterator_base;
+ typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
+ typedef BOOST_DEDUCED_TYPENAME iterator_base::node node;
 
         typedef BOOST_DEDUCED_TYPENAME node::bucket_allocator bucket_allocator;
         typedef BOOST_DEDUCED_TYPENAME node::bucket_ptr bucket_ptr;
         typedef BOOST_DEDUCED_TYPENAME node::node_ptr node_ptr;
 
- typedef BOOST_DEDUCED_TYPENAME rebind_wrap<value_allocator, node>::type node_allocator;
+ typedef BOOST_DEDUCED_TYPENAME rebind_wrap<value_allocator, node>::type
+ node_allocator;
         typedef BOOST_DEDUCED_TYPENAME node_allocator::pointer real_node_ptr;
 
- typedef hash_iterator_base<bucket_ptr> iterator_base;
-
         // Members
 
         bucket_ptr buckets_;
@@ -225,124 +290,194 @@
         
         // Data access
 
- bucket_allocator const& bucket_alloc() const { return allocators_.first(); }
- node_allocator const& node_alloc() const { return allocators_.second(); }
- bucket_allocator& bucket_alloc() { return allocators_.first(); }
- node_allocator& node_alloc() { return allocators_.second(); }
+ bucket_allocator const& bucket_alloc() const {
+ return allocators_.first(); }
+ node_allocator const& node_alloc() const {
+ return allocators_.second(); }
+ bucket_allocator& bucket_alloc() {
+ return allocators_.first(); }
+ node_allocator& node_alloc() {
+ return allocators_.second(); }
         std::size_t max_bucket_count() const {
             // -1 to account for the sentinel.
             return prev_prime(this->bucket_alloc().max_size() - 1);
         }
 
         // Constructors
- //
- // The copy constructor doesn't copy the buckets.
 
         hash_buckets(node_allocator const& a, std::size_t n);
- hash_buckets(hash_buckets& x, move_tag m);
- hash_buckets(hash_buckets& x, value_allocator const& a, move_tag m);
+ void create_buckets();
         ~hash_buckets();
         
         // no throw
         void swap(hash_buckets& other);
         void move(hash_buckets& other);
 
- // Buckets
+ // For the remaining functions, buckets_ must not be null.
         
- std::size_t bucket_count() const;
- std::size_t bucket_from_hash(std::size_t hashed) const;
+ bucket_ptr get_bucket(std::size_t n) const;
         bucket_ptr bucket_ptr_from_hash(std::size_t hashed) const;
- bucket_ptr buckets_begin() const;
- bucket_ptr buckets_end() const;
         std::size_t bucket_size(std::size_t index) const;
- bucket_ptr get_bucket(std::size_t n) const;
         node_ptr bucket_begin(std::size_t n) const;
- node_ptr bucket_end(std::size_t) const;
 
         // Alloc/Dealloc
         
- void destruct_node(node_ptr);
+ void delete_node(node_ptr);
 
         //
         void delete_buckets();
         void clear_bucket(bucket_ptr);
- void delete_group(node_ptr first_node);
- void delete_nodes(node_ptr begin, node_ptr end);
- void delete_to_bucket_end(node_ptr begin);
+ std::size_t delete_nodes(node_ptr begin, node_ptr end);
+ std::size_t delete_to_bucket_end(node_ptr begin);
+ };
+
+ template <class H, class P> class set_hash_functions;
+
+ template <class H, class P>
+ class hash_buffered_functions
+ {
+ friend class set_hash_functions<H, P>;
+ hash_buffered_functions& operator=(hash_buffered_functions const&);
+
+ typedef boost::compressed_pair<H, P> function_pair;
+ typedef BOOST_DEDUCED_TYPENAME boost::aligned_storage<
+ sizeof(function_pair),
+ ::boost::alignment_of<function_pair>::value>::type aligned_function;
+
+ bool current_; // The currently active functions.
+ aligned_function funcs_[2];
+
+ function_pair const& current() const {
+ return *static_cast<function_pair const*>(
+ static_cast<void const*>(&funcs_[current_]));
+ }
+
+ void construct(bool which, H const& hf, P const& eq)
+ {
+ new((void*) &funcs_[which]) function_pair(hf, eq);
+ }
+
+ void construct(bool which, function_pair const& f)
+ {
+ new((void*) &funcs_[which]) function_pair(f);
+ }
+
+ void destroy(bool which)
+ {
+ boost::unordered_detail::destroy((function_pair*)(&funcs_[which]));
+ }
+
+ public:
+
+ hash_buffered_functions(H const& hf, P const& eq)
+ : current_(false)
+ {
+ construct(current_, hf, eq);
+ }
+
+ hash_buffered_functions(hash_buffered_functions const& bf)
+ : current_(false)
+ {
+ construct(current_, bf.current());
+ }
+
+ ~hash_buffered_functions() {
+ destroy(current_);
+ }
+
+ H const& hash_function() const {
+ return current().first();
+ }
+
+ P const& key_eq() const {
+ return current().second();
+ }
+ };
+
+ template <class H, class P>
+ class set_hash_functions
+ {
+ set_hash_functions(set_hash_functions const&);
+ set_hash_functions& operator=(set_hash_functions const&);
+
+ typedef hash_buffered_functions<H, P> buffered_functions;
+ buffered_functions& buffered_functions_;
+ bool tmp_functions_;
+
+ public:
+
+ set_hash_functions(buffered_functions& f, H const& h, P const& p)
+ : buffered_functions_(f),
+ tmp_functions_(!f.current_)
+ {
+ f.construct(tmp_functions_, h, p);
+ }
+
+ set_hash_functions(buffered_functions& f,
+ buffered_functions const& other)
+ : buffered_functions_(f),
+ tmp_functions_(!f.current_)
+ {
+ f.construct(tmp_functions_, other.current());
+ }
+
+ ~set_hash_functions()
+ {
+ buffered_functions_.destroy(tmp_functions_);
+ }
+
+ void commit()
+ {
+ buffered_functions_.current_ = tmp_functions_;
+ tmp_functions_ = !tmp_functions_;
+ }
     };
 
     template <class H, class P, class A, class G, class K>
     class hash_table :
- public hash_buckets<A, G>
-
+ public hash_buckets<A, G>,
+ public hash_buffered_functions<H, P>
     {
+ hash_table(hash_table const&);
     public:
         typedef H hasher;
         typedef P key_equal;
         typedef A value_allocator;
         typedef G grouped;
         typedef K key_extractor;
+ typedef hash_buffered_functions<H, P> base;
         typedef hash_buckets<A, G> buckets;
         
         typedef BOOST_DEDUCED_TYPENAME value_allocator::value_type value_type;
- typedef BOOST_DEDUCED_TYPENAME key_extractor::BOOST_NESTED_TEMPLATE apply<value_type>
- extractor;
+ typedef BOOST_DEDUCED_TYPENAME key_extractor::BOOST_NESTED_TEMPLATE
+ apply<value_type> extractor;
         typedef BOOST_DEDUCED_TYPENAME extractor::key_type key_type;
 
         typedef BOOST_DEDUCED_TYPENAME buckets::node node;
         typedef BOOST_DEDUCED_TYPENAME buckets::bucket bucket;
         typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
         typedef BOOST_DEDUCED_TYPENAME buckets::bucket_ptr bucket_ptr;
-
         typedef BOOST_DEDUCED_TYPENAME buckets::iterator_base iterator_base;
-
- // Types for storing functions
-
- typedef boost::compressed_pair<hasher, key_equal> functions;
- typedef bool functions_ptr;
-
- typedef BOOST_DEDUCED_TYPENAME boost::aligned_storage<
- sizeof(functions),
- ::boost::alignment_of<functions>::value>::type aligned_function;
+ typedef BOOST_DEDUCED_TYPENAME buckets::node_allocator node_allocator;
+ typedef hash_node_constructor<A, G> node_constructor;
+ typedef std::pair<iterator_base, iterator_base> iterator_pair;
 
         // Members
         
- bool func_; // The currently active functions.
- aligned_function funcs_[2];
- bucket_ptr cached_begin_bucket_;
         std::size_t size_;
         float mlf_;
+ // Cached data - invalid if !this->buckets_
+ bucket_ptr cached_begin_bucket_;
         std::size_t max_load_;
-
- // Buffered Functions
-
- functions* get_functions(bool which) {
- return static_cast<functions*>(static_cast<void*>(&this->funcs_[which]));
- }
- functions const* get_functions(bool which) const {
- return static_cast<functions const*>(static_cast<void const*>(&this->funcs_[which]));
- }
- functions const& current() const {
- return *this->get_functions(this->func_);
- }
- hasher const& hash_function() const {
- return this->current().first();
- }
- key_equal const& key_eq() const {
- return this->current().second();
- }
- functions_ptr buffer_functions(hash_table const& x) {
- functions_ptr ptr = !func_;
- *this->get_functions(ptr) = x.current();
- return ptr;
- }
- void set_functions(functions_ptr ptr) {
- BOOST_ASSERT(ptr != func_);
- func_ = ptr;
- }
 
         // Helper methods
 
+ key_type const& get_key(value_type const& v) const {
+ return extractor::extract(v);
+ }
+ key_type const& get_key_from_ptr(node_ptr n) const {
+ return extractor::extract(node::get_value(n));
+ }
         bool equal(key_type const& k, value_type const& v) const;
         node_ptr find_iterator(bucket_ptr bucket, key_type const& k) const;
         node_ptr find_iterator(key_type const& k) const;
@@ -354,31 +489,40 @@
         std::size_t bucket_index(key_type const& k) const;
         void max_load_factor(float z);
         std::size_t min_buckets_for_size(std::size_t n) const;
- void calculate_max_load();
+ std::size_t calculate_max_load();
 
         // Constructors
 
- hash_table(std::size_t n, hasher const& hf, key_equal const& eq, value_allocator const& a);
- hash_table(hash_table const& x);
- hash_table(hash_table const& x, value_allocator const& a);
+ hash_table(std::size_t n, hasher const& hf, key_equal const& eq,
+ node_allocator const& a);
+ hash_table(hash_table const& x, node_allocator const& a);
         hash_table(hash_table& x, move_tag m);
- hash_table(hash_table& x, value_allocator const& a, move_tag m);
- ~hash_table();
+ hash_table(hash_table& x, node_allocator const& a, move_tag m);
+ ~hash_table() {}
         hash_table& operator=(hash_table const&);
 
         // Iterators
 
- iterator_base begin() const { return iterator_base(this->cached_begin_bucket_); }
- iterator_base end() const { return iterator_base(this->buckets_end()); }
+ iterator_base begin() const {
+ return this->size_ ?
+ iterator_base(this->cached_begin_bucket_) :
+ iterator_base();
+ }
+ iterator_base end() const {
+ return iterator_base();
+ }
 
         // Swap & Move
 
         void swap(hash_table& x);
+ void fast_swap(hash_table& other);
+ void slow_swap(hash_table& other);
+ void partial_swap(hash_table& other);
         void move(hash_table& x);
 
         // Reserve and rehash
 
- bool reserve(std::size_t n);
+ void create_for_insert(std::size_t n);
         bool reserve_for_insert(std::size_t n);
         void rehash(std::size_t n);
         void rehash_impl(std::size_t n);
@@ -393,7 +537,7 @@
         std::size_t count(key_type const& k) const;
         iterator_base find(key_type const& k) const;
         value_type& at(key_type const& k) const;
- std::pair<iterator_base, iterator_base> equal_range(key_type const& k) const;
+ iterator_pair equal_range(key_type const& k) const;
 
         // Erase
         //
@@ -407,7 +551,7 @@
 
         // recompute_begin_bucket
 
- void recompute_begin_bucket();
+ void init_buckets();
 
         // After an erase cached_begin_bucket_ might be left pointing to
         // an empty bucket, so this is called to update it
@@ -424,6 +568,203 @@
         
         // no throw
         float load_factor() const;
+
+ iterator_base emplace_empty_impl_with_node(
+ node_constructor&, std::size_t);
+ };
+
+ template <class H, class P, class A, class K>
+ class hash_unique_table :
+ public hash_table<H, P, A, boost::unordered_detail::ungrouped, K>
+
+ {
+ public:
+ typedef H hasher;
+ typedef P key_equal;
+ typedef A value_allocator;
+ typedef K key_extractor;
+
+ typedef hash_table<H, P, A, ungrouped, K> table;
+ typedef hash_node_constructor<A, ungrouped> node_constructor;
+
+ typedef BOOST_DEDUCED_TYPENAME table::key_type key_type;
+ typedef BOOST_DEDUCED_TYPENAME table::value_type value_type;
+ typedef BOOST_DEDUCED_TYPENAME table::node node;
+ typedef BOOST_DEDUCED_TYPENAME table::node_ptr node_ptr;
+ typedef BOOST_DEDUCED_TYPENAME table::bucket_ptr bucket_ptr;
+ typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base;
+ typedef BOOST_DEDUCED_TYPENAME table::extractor extractor;
+
+ typedef std::pair<iterator_base, bool> emplace_return;
+
+ // Constructors
+
+ hash_unique_table(std::size_t n, hasher const& hf, key_equal const& eq,
+ value_allocator const& a)
+ : table(n, hf, eq, a) {}
+ hash_unique_table(hash_unique_table const& x)
+ : table(x, x.node_alloc()) {}
+ hash_unique_table(hash_unique_table const& x, value_allocator const& a)
+ : table(x, a) {}
+ hash_unique_table(hash_unique_table& x, move_tag m)
+ : table(x, m) {}
+ hash_unique_table(hash_unique_table& x, value_allocator const& a,
+ move_tag m)
+ : table(x, a, m) {}
+ ~hash_unique_table() {}
+
+ // Insert methods
+
+ emplace_return emplace_impl_with_node(node_constructor& a);
+ value_type& operator[](key_type const& k);
+
+ // equals
+
+ bool equals(hash_unique_table const&) const;
+
+ node_ptr add_node(node_constructor& a, bucket_ptr bucket);
+
+#if defined(BOOST_UNORDERED_STD_FORWARD)
+
+ template<class... Args>
+ emplace_return emplace(Args&&... args);
+ template<class... Args>
+ iterator_base emplace_hint(iterator_base const&, Args&&... args);
+ template<class... Args>
+ emplace_return emplace_impl(key_type const& k, Args&&... args);
+ template<class... Args>
+ emplace_return emplace_impl(no_key, Args&&... args);
+ template<class... Args>
+ emplace_return emplace_empty_impl(Args&&... args);
+#else
+ template <class Arg0>
+ emplace_return emplace(Arg0 const& arg0);
+ template <class Arg0>
+ iterator_base emplace_hint(iterator_base const&, Arg0 const& arg0);
+
+#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
+ template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
+ emplace_return emplace( \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \
+ template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
+ iterator_base emplace_hint(iterator_base const& it, \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \
+ BOOST_UNORDERED_INSERT_IMPL2(z, n, _)
+
+#define BOOST_UNORDERED_INSERT_IMPL2(z, n, _) \
+ template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
+ emplace_return emplace_impl(key_type const& k, \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \
+ template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
+ emplace_return emplace_impl(no_key, \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \
+ template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
+ emplace_return emplace_empty_impl( \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n));
+
+ BOOST_UNORDERED_INSERT_IMPL2(1, 1, _)
+
+ BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT,
+ BOOST_UNORDERED_INSERT_IMPL, _)
+
+#undef BOOST_UNORDERED_INSERT_IMPL
+#undef BOOST_UNORDERED_INSERT_IMPL2
+
+#endif
+
+ // if hash function throws, or inserting > 1 element, basic exception
+ // safety strong otherwise
+ template <class InputIt>
+ void insert_range(InputIt i, InputIt j);
+ template <class InputIt>
+ void insert_range_impl(key_type const&, InputIt i, InputIt j);
+ template <class InputIt>
+ void insert_range_impl(no_key, InputIt i, InputIt j);
+ };
+
+ template <class H, class P, class A, class K>
+ class hash_equivalent_table :
+ public hash_table<H, P, A, boost::unordered_detail::grouped, K>
+
+ {
+ public:
+ typedef H hasher;
+ typedef P key_equal;
+ typedef A value_allocator;
+ typedef K key_extractor;
+
+ typedef hash_table<H, P, A, boost::unordered_detail::grouped, K> table;
+ typedef hash_node_constructor<A, boost::unordered_detail::grouped>
+ node_constructor;
+ typedef hash_iterator_base<A, grouped> iterator_base;
+
+ typedef BOOST_DEDUCED_TYPENAME table::key_type key_type;
+ typedef BOOST_DEDUCED_TYPENAME table::value_type value_type;
+ typedef BOOST_DEDUCED_TYPENAME table::node node;
+ typedef BOOST_DEDUCED_TYPENAME table::node_ptr node_ptr;
+ typedef BOOST_DEDUCED_TYPENAME table::bucket_ptr bucket_ptr;
+ typedef BOOST_DEDUCED_TYPENAME table::extractor extractor;
+
+ // Constructors
+
+ hash_equivalent_table(std::size_t n,
+ hasher const& hf, key_equal const& eq, value_allocator const& a)
+ : table(n, hf, eq, a) {}
+ hash_equivalent_table(hash_equivalent_table const& x)
+ : table(x, x.node_alloc()) {}
+ hash_equivalent_table(hash_equivalent_table const& x,
+ value_allocator const& a)
+ : table(x, a) {}
+ hash_equivalent_table(hash_equivalent_table& x, move_tag m)
+ : table(x, m) {}
+ hash_equivalent_table(hash_equivalent_table& x,
+ value_allocator const& a, move_tag m)
+ : table(x, a, m) {}
+ ~hash_equivalent_table() {}
+
+ // Insert methods
+
+ iterator_base emplace_impl(node_constructor& a);
+ iterator_base emplace_hint_impl(iterator_base const& it,
+ node_constructor& a);
+ void emplace_impl_no_rehash(node_constructor& a);
+
+ // equals
+
+ bool equals(hash_equivalent_table const&) const;
+
+ inline node_ptr add_node(node_constructor& a,
+ bucket_ptr bucket, node_ptr pos);
+
+#if defined(BOOST_UNORDERED_STD_FORWARD)
+
+ template <class... Args>
+ iterator_base emplace(Args&&... args);
+ template <class... Args>
+ iterator_base emplace_hint(iterator_base const& it, Args&&... args);
+
+#else
+
+#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
+ template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
+ iterator_base emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \
+ \
+ template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
+ iterator_base emplace_hint(iterator_base const& it, \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n));
+
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
+ BOOST_UNORDERED_INSERT_IMPL, _)
+
+#undef BOOST_UNORDERED_INSERT_IMPL
+#endif
+
+ template <class I>
+ void insert_for_range(I i, I j, forward_traversal_tag);
+ template <class I>
+ void insert_for_range(I i, I j, boost::incrementable_traversal_tag);
+ template <class I>
+ void insert_range(I i, I j);
     };
 
     // Iterator Access
@@ -432,7 +773,9 @@
     {
     public:
         template <class Iterator>
- static BOOST_DEDUCED_TYPENAME Iterator::base const& get(Iterator const& it) {
+ static BOOST_DEDUCED_TYPENAME Iterator::base const&
+ get(Iterator const& it)
+ {
             return it.base_;
         }
     };
@@ -462,25 +805,39 @@
 
     private:
         typedef hash_buckets<A, G> buckets;
- typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr ptr;
+ typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
         typedef BOOST_DEDUCED_TYPENAME buckets::node node;
         typedef hash_const_local_iterator<A, G> const_local_iterator;
 
         friend class hash_const_local_iterator<A, G>;
- ptr ptr_;
+ node_ptr ptr_;
 
     public:
         hash_local_iterator() : ptr_() {}
- explicit hash_local_iterator(ptr x) : ptr_(x) {}
- BOOST_DEDUCED_TYPENAME A::reference operator*() const
- { return node::get_value(ptr_); }
- value_type* operator->() const { return &node::get_value(ptr_); }
- hash_local_iterator& operator++() { ptr_ = next_node(ptr_); return *this; }
- hash_local_iterator operator++(int) { hash_local_iterator tmp(ptr_); ptr_ = next_node(ptr_); return tmp; }
- bool operator==(hash_local_iterator x) const { return ptr_ == x.ptr_; }
- bool operator==(const_local_iterator x) const { return ptr_ == x.ptr_; }
- bool operator!=(hash_local_iterator x) const { return ptr_ != x.ptr_; }
- bool operator!=(const_local_iterator x) const { return ptr_ != x.ptr_; }
+ explicit hash_local_iterator(node_ptr x) : ptr_(x) {}
+ BOOST_DEDUCED_TYPENAME A::reference operator*() const {
+ return node::get_value(ptr_);
+ }
+ value_type* operator->() const {
+ return &node::get_value(ptr_);
+ }
+ hash_local_iterator& operator++() {
+ ptr_ = ptr_->next_; return *this;
+ }
+ hash_local_iterator operator++(int) {
+ hash_local_iterator tmp(ptr_); ptr_ = ptr_->next_; return tmp; }
+ bool operator==(hash_local_iterator x) const {
+ return ptr_ == x.ptr_;
+ }
+ bool operator==(const_local_iterator x) const {
+ return ptr_ == x.ptr_;
+ }
+ bool operator!=(hash_local_iterator x) const {
+ return ptr_ != x.ptr_;
+ }
+ bool operator!=(const_local_iterator x) const {
+ return ptr_ != x.ptr_;
+ }
     };
 
     template <class A, class G>
@@ -508,14 +865,30 @@
         explicit hash_const_local_iterator(ptr x) : ptr_(x) {}
         hash_const_local_iterator(local_iterator x) : ptr_(x.ptr_) {}
         BOOST_DEDUCED_TYPENAME A::const_reference
- operator*() const { return node::get_value(ptr_); }
- value_type const* operator->() const { return &node::get_value(ptr_); }
- hash_const_local_iterator& operator++() { ptr_ = next_node(ptr_); return *this; }
- hash_const_local_iterator operator++(int) { hash_const_local_iterator tmp(ptr_); ptr_ = next_node(ptr_); return tmp; }
- bool operator==(local_iterator x) const { return ptr_ == x.ptr_; }
- bool operator==(hash_const_local_iterator x) const { return ptr_ == x.ptr_; }
- bool operator!=(local_iterator x) const { return ptr_ != x.ptr_; }
- bool operator!=(hash_const_local_iterator x) const { return ptr_ != x.ptr_; }
+ operator*() const {
+ return node::get_value(ptr_);
+ }
+ value_type const* operator->() const {
+ return &node::get_value(ptr_);
+ }
+ hash_const_local_iterator& operator++() {
+ ptr_ = ptr_->next_; return *this;
+ }
+ hash_const_local_iterator operator++(int) {
+ hash_const_local_iterator tmp(ptr_); ptr_ = ptr_->next_; return tmp;
+ }
+ bool operator==(local_iterator x) const {
+ return ptr_ == x.ptr_;
+ }
+ bool operator==(hash_const_local_iterator x) const {
+ return ptr_ == x.ptr_;
+ }
+ bool operator!=(local_iterator x) const {
+ return ptr_ != x.ptr_;
+ }
+ bool operator!=(hash_const_local_iterator x) const {
+ return ptr_ != x.ptr_;
+ }
     };
 
     // iterators
@@ -547,15 +920,30 @@
 
         hash_iterator() : base_() {}
         explicit hash_iterator(base const& x) : base_(x) {}
- BOOST_DEDUCED_TYPENAME A::reference
- operator*() const { return node::get_value(base_.get()); }
- value_type* operator->() const { return &node::get_value(base_.get()); }
- hash_iterator& operator++() { base_.increment(); return *this; }
- hash_iterator operator++(int) { hash_iterator tmp(base_); base_.increment(); return tmp; }
- bool operator==(hash_iterator const& x) const { return base_ == x.base_; }
- bool operator==(const_iterator const& x) const { return base_ == x.base_; }
- bool operator!=(hash_iterator const& x) const { return base_ != x.base_; }
- bool operator!=(const_iterator const& x) const { return base_ != x.base_; }
+ BOOST_DEDUCED_TYPENAME A::reference operator*() const {
+ return *base_;
+ }
+ value_type* operator->() const {
+ return &*base_;
+ }
+ hash_iterator& operator++() {
+ base_.increment(); return *this;
+ }
+ hash_iterator operator++(int) {
+ hash_iterator tmp(base_); base_.increment(); return tmp;
+ }
+ bool operator==(hash_iterator const& x) const {
+ return base_ == x.base_;
+ }
+ bool operator==(const_iterator const& x) const {
+ return base_ == x.base_;
+ }
+ bool operator!=(hash_iterator const& x) const {
+ return base_ != x.base_;
+ }
+ bool operator!=(const_iterator const& x) const {
+ return base_ != x.base_;
+ }
     };
 
     template <class A, class G>
@@ -584,15 +972,30 @@
         hash_const_iterator() : base_() {}
         explicit hash_const_iterator(base const& x) : base_(x) {}
         hash_const_iterator(iterator const& x) : base_(x.base_) {}
- BOOST_DEDUCED_TYPENAME A::const_reference
- operator*() const { return node::get_value(base_.get()); }
- value_type const* operator->() const { return &node::get_value(base_.get()); }
- hash_const_iterator& operator++() { base_.increment(); return *this; }
- hash_const_iterator operator++(int) { hash_const_iterator tmp(base_); base_.increment(); return tmp; }
- bool operator==(iterator const& x) const { return base_ == x.base_; }
- bool operator==(hash_const_iterator const& x) const { return base_ == x.base_; }
- bool operator!=(iterator const& x) const { return base_ != x.base_; }
- bool operator!=(hash_const_iterator const& x) const { return base_ != x.base_; }
+ BOOST_DEDUCED_TYPENAME A::const_reference operator*() const {
+ return *base_;
+ }
+ value_type const* operator->() const {
+ return &*base_;
+ }
+ hash_const_iterator& operator++() {
+ base_.increment(); return *this;
+ }
+ hash_const_iterator operator++(int) {
+ hash_const_iterator tmp(base_); base_.increment(); return tmp;
+ }
+ bool operator==(iterator const& x) const {
+ return base_ == x.base_;
+ }
+ bool operator==(hash_const_iterator const& x) const {
+ return base_ == x.base_;
+ }
+ bool operator!=(iterator const& x) const {
+ return base_ != x.base_;
+ }
+ bool operator!=(hash_const_iterator const& x) const {
+ return base_ != x.base_;
+ }
     };
 }}
 

Deleted: trunk/boost/unordered/detail/insert.hpp
==============================================================================
--- trunk/boost/unordered/detail/insert.hpp 2009-09-20 17:55:15 EDT (Sun, 20 Sep 2009)
+++ (empty file)
@@ -1,678 +0,0 @@
-
-// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
-// Copyright (C) 2005-2009 Daniel James
-// 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_INSERT_HPP_INCLUDED
-#define BOOST_UNORDERED_DETAIL_INSERT_HPP_INCLUDED
-
-#include <boost/unordered/detail/table.hpp>
-#include <boost/unordered/detail/extract_key.hpp>
-
-namespace boost { namespace unordered_detail {
-
- ////////////////////////////////////////////////////////////////////////////
- // A couple of convenience methods for adding nodes.
-
- // H = Has Func
- // P = Predicate
- // A = Value Allocator
- // K = Key Extractor
-
- template <class H, class P, class A, class K>
- class hash_unique_table :
- public hash_table<H, P, A, boost::unordered_detail::ungrouped, K>
-
- {
- public:
- typedef H hasher;
- typedef P key_equal;
- typedef A value_allocator;
- typedef K key_extractor;
-
- typedef hash_table<H, P, A, boost::unordered_detail::ungrouped, K> table;
- typedef hash_node_constructor<A, boost::unordered_detail::ungrouped> node_constructor;
-
- typedef BOOST_DEDUCED_TYPENAME table::key_type key_type;
- typedef BOOST_DEDUCED_TYPENAME table::value_type value_type;
- typedef BOOST_DEDUCED_TYPENAME table::node node;
- typedef BOOST_DEDUCED_TYPENAME table::node_ptr node_ptr;
- typedef BOOST_DEDUCED_TYPENAME table::bucket_ptr bucket_ptr;
- typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base;
- typedef BOOST_DEDUCED_TYPENAME table::extractor extractor;
-
- // Constructors
-
- hash_unique_table(std::size_t n, hasher const& hf, key_equal const& eq, value_allocator const& a)
- : table(n, hf, eq, a) {}
- hash_unique_table(hash_unique_table const& x)
- : table(x) {}
- hash_unique_table(hash_unique_table const& x, value_allocator const& a)
- : table(x, a) {}
- hash_unique_table(hash_unique_table& x, move_tag m)
- : table(x, m) {}
- hash_unique_table(hash_unique_table& x, value_allocator const& a, move_tag m)
- : table(x, a, m) {}
- ~hash_unique_table() {}
-
- // Insert methods
-
- std::pair<iterator_base, bool> emplace_impl_with_node(node_constructor& a);
- value_type& operator[](key_type const& k);
-
- // equals
-
- bool equals(hash_unique_table const&) const;
- static bool group_equals(node_ptr it1, node_ptr it2, set_extractor*);
- static bool group_equals(node_ptr it1, node_ptr it2, map_extractor*);
-
- inline node_ptr add_node(node_constructor& a, bucket_ptr bucket)
- {
- node_ptr n = a.release();
- node::add_to_bucket(n, *bucket);
- ++this->size_;
- if(bucket < this->cached_begin_bucket_) this->cached_begin_bucket_ = bucket;
- return n;
- }
-
-#if defined(BOOST_UNORDERED_STD_FORWARD)
-
- // Emplace (unique keys)
- // (I'm using an overloaded emplace for both 'insert' and 'emplace')
-
- // if hash function throws, basic exception safety
- // strong otherwise
- template<class... Args>
- std::pair<iterator_base, bool> emplace(Args&&... args)
- {
- return emplace_impl(
- extractor::extract(std::forward<Args>(args)...),
- std::forward<Args>(args)...);
- }
-
- // Insert (unique keys)
- // (I'm using an overloaded emplace for both 'insert' and 'emplace')
- // I'm just ignoring hints here for now.
-
- // if hash function throws, basic exception safety
- // strong otherwise
- template<class... Args>
- iterator_base emplace_hint(iterator_base const&, Args&&... args)
- {
- return emplace_impl(
- extractor::extract(std::forward<Args>(args)...),
- std::forward<Args>(args)...).first;
- }
-
- template<class... Args>
- std::pair<iterator_base, bool> emplace_impl(key_type const& k, Args&&... args)
- {
- // No side effects in this initial code
- std::size_t hash_value = this->hash_function()(k);
- bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
- node_ptr pos = find_iterator(bucket, k);
-
- if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
- // Found an existing key, return it (no throw).
- return std::pair<iterator_base, bool>(
- iterator_base(bucket, pos), false);
-
- } else {
- // 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).
- node_constructor a(*this);
- a.construct(std::forward<Args>(args)...);
-
- // reserve has basic exception safety if the hash function
- // throws, strong otherwise.
- if(reserve_for_insert(this->size_ + 1))
- bucket = this->bucket_ptr_from_hash(hash_value);
-
- // Nothing after this point can throw.
-
- return std::pair<iterator_base, bool>(iterator_base(bucket,
- add_node(a, bucket)), true);
- }
- }
-
- template<class... Args>
- std::pair<iterator_base, bool> 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);
- }
-#else
- template <class Arg0>
- std::pair<iterator_base, bool> emplace(Arg0 const& arg0)
- {
- return emplace_impl(extractor::extract(arg0), arg0);
- }
-
- template <class Arg0>
- iterator_base emplace_hint(iterator_base const&, Arg0 const& arg0)
- {
- return emplace_impl(extractor::extract(arg0), arg0).first;
- }
-
-#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
- template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
- std::pair<iterator_base, bool> emplace( \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ) \
- { \
- return emplace_impl(extractor::extract(arg0, arg1), \
- BOOST_UNORDERED_CALL_PARAMS(z, n)); \
- } \
- \
- template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
- iterator_base emplace_hint(iterator_base const& it, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ) \
- { \
- return emplace_impl(extractor::extract(arg0, arg1), \
- BOOST_UNORDERED_CALL_PARAMS(z, n)).first; \
- } \
- BOOST_UNORDERED_INSERT_IMPL2(z, n, _)
-
-#define BOOST_UNORDERED_INSERT_IMPL2(z, n, _) \
- template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
- std::pair<iterator_base, bool> emplace_impl(key_type const& k, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ) \
- { \
- std::size_t hash_value = this->hash_function()(k); \
- bucket_ptr bucket \
- = this->bucket_ptr_from_hash(hash_value); \
- node_ptr pos = find_iterator(bucket, k); \
- \
- if (BOOST_UNORDERED_BORLAND_BOOL(pos)) { \
- return std::pair<iterator_base, bool>( \
- iterator_base(bucket, pos), false); \
- } else { \
- node_constructor a(*this); \
- a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
- \
- if(reserve_for_insert(this->size_ + 1)) \
- bucket = this->bucket_ptr_from_hash(hash_value); \
- \
- return std::pair<iterator_base, bool>(iterator_base(bucket, \
- add_node(a, bucket)), true); \
- } \
- } \
- \
- template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
- std::pair<iterator_base, bool> 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); \
- }
-
- BOOST_UNORDERED_INSERT_IMPL2(1, 1, _)
-
- BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_INSERT_IMPL, _)
-
-#undef BOOST_UNORDERED_INSERT_IMPL
-
-#endif
-
- // if hash function throws, or inserting > 1 element, basic exception safety
- // strong otherwise
- template <class InputIterator>
- void insert_range(InputIterator i, InputIterator j)
- {
- if(i != j)
- return insert_range_impl(extractor::extract(*i), i, j);
- }
-
- template <class InputIterator>
- void insert_range_impl(key_type const&, InputIterator i, InputIterator j)
- {
- node_constructor a(*this);
-
- for (; i != j; ++i) {
- // No side effects in this initial code
- std::size_t hash_value = this->hash_function()(extractor::extract(*i));
- bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
- node_ptr pos = find_iterator(bucket, extractor::extract(*i));
-
- 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_) {
- reserve_for_insert(this->size_ + insert_size(i, j));
- bucket = this->bucket_ptr_from_hash(hash_value);
- }
-
- // Nothing after this point can throw.
- add_node(a, bucket);
- }
- }
- }
-
- template <class InputIterator>
- void insert_range_impl(no_key, InputIterator i, InputIterator j)
- {
- node_constructor a(*this);
-
- for (; i != j; ++i) {
- // No side effects in this initial code
- a.construct(*i);
- emplace_impl_with_node(a);
- }
- }
- };
-
- template <class H, class P, class A, class K>
- class hash_equivalent_table :
- public hash_table<H, P, A, boost::unordered_detail::grouped, K>
-
- {
- public:
- typedef H hasher;
- typedef P key_equal;
- typedef A value_allocator;
- typedef K key_extractor;
-
- typedef hash_table<H, P, A, boost::unordered_detail::grouped, K> table;
- typedef hash_node_constructor<A, boost::unordered_detail::grouped> node_constructor;
-
- typedef BOOST_DEDUCED_TYPENAME table::key_type key_type;
- typedef BOOST_DEDUCED_TYPENAME table::value_type value_type;
- typedef BOOST_DEDUCED_TYPENAME table::node node;
- typedef BOOST_DEDUCED_TYPENAME table::node_ptr node_ptr;
- typedef BOOST_DEDUCED_TYPENAME table::bucket_ptr bucket_ptr;
- typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base;
- typedef BOOST_DEDUCED_TYPENAME table::extractor extractor;
-
- // Constructors
-
- hash_equivalent_table(std::size_t n, hasher const& hf, key_equal const& eq, value_allocator const& a)
- : table(n, hf, eq, a) {}
- hash_equivalent_table(hash_equivalent_table const& x)
- : table(x) {}
- hash_equivalent_table(hash_equivalent_table const& x, value_allocator const& a)
- : table(x, a) {}
- hash_equivalent_table(hash_equivalent_table& x, move_tag m)
- : table(x, m) {}
- hash_equivalent_table(hash_equivalent_table& x, value_allocator const& a, move_tag m)
- : table(x, a, m) {}
- ~hash_equivalent_table() {}
-
- // Insert methods
-
- iterator_base emplace_impl(node_constructor& a);
- iterator_base emplace_hint_impl(iterator_base const& it, node_constructor& a);
- void emplace_impl_no_rehash(node_constructor& a);
-
- // equals
-
- bool equals(hash_equivalent_table const&) const;
- static bool group_equals(node_ptr it1, node_ptr it2, set_extractor*);
- static bool group_equals(node_ptr it1, node_ptr it2, map_extractor*);
-
- inline node_ptr add_node(node_constructor& a, bucket_ptr bucket, node_ptr pos)
- {
- node_ptr n = a.release();
- if(BOOST_UNORDERED_BORLAND_BOOL(pos)) {
- node::add_after_node(n, pos);
- }
- else {
- node::add_to_bucket(n, *bucket);
- if(bucket < this->cached_begin_bucket_) this->cached_begin_bucket_ = bucket;
- }
- ++this->size_;
- return n;
- }
-
- public:
-
- // Insert functions
- //
- // basic exception safety, if hash function throws
- // strong otherwise.
-
-#if defined(BOOST_UNORDERED_STD_FORWARD)
-
- // Emplace (equivalent key containers)
- // (I'm using an overloaded emplace for both 'insert' and 'emplace')
-
- // if hash function throws, basic exception safety
- // strong otherwise
- template <class... Args>
- iterator_base 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);
- }
-
- // Emplace (equivalent key containers)
- // (I'm using an overloaded emplace for both 'insert' and 'emplace')
-
- // if hash function throws, basic exception safety
- // strong otherwise
- template <class... Args>
- iterator_base emplace_hint(iterator_base const& it, 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_hint_impl(it, a);
- }
-
-#else
-
-#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
- template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
- iterator_base emplace( \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ) \
- { \
- node_constructor a(*this); \
- a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
- return emplace_impl(a); \
- } \
- \
- template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
- iterator_base emplace_hint(iterator_base const& it, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ) \
- { \
- node_constructor a(*this); \
- a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
- return emplace_hint_impl(it, a); \
- }
-
- BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_INSERT_IMPL, _)
-
-#undef BOOST_UNORDERED_INSERT_IMPL
-#endif
-
- // Insert from iterator range (equivalent key containers)
-
- private:
-
- // 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)
- {
- std::size_t distance = unordered_detail::distance(i, j);
- if(distance == 1) {
- emplace(*i);
- }
- else {
- // Only require basic exception safety here
- reserve_for_insert(this->size_ + distance);
- node_constructor a(*this);
-
- for (; i != j; ++i) {
- a.construct(*i);
- emplace_impl_no_rehash(a);
- }
- }
- }
-
- // if hash function throws, or inserting > 1 element, basic exception safety
- // strong otherwise
- template <class I>
- void insert_for_range(I i, I j,
- boost::incrementable_traversal_tag)
- {
- node_constructor a(*this);
- for (; i != j; ++i) {
- a.construct(*i);
- emplace_impl(a);
- }
- }
-
- public:
-
- // 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);
- }
- };
-
- ////////////////////////////////////////////////////////////////////////////
- // Unique insert methods
-
- template <class H, class P, class A, class K>
- std::pair<
- BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::iterator_base,
- bool>
- hash_unique_table<H, P, A, K>
- ::emplace_impl_with_node(node_constructor& a)
- {
- // No side effects in this initial code
- key_type const& k = extractor::extract(a.get()->value());
- std::size_t hash_value = this->hash_function()(k);
- bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
- node_ptr pos = find_iterator(bucket, k);
-
- if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
- // Found an existing key, return it (no throw).
- return std::pair<iterator_base, bool>(
- iterator_base(bucket, pos), false);
- } else {
- // reserve has basic exception safety if the hash function
- // throws, strong otherwise.
- if(reserve_for_insert(this->size_ + 1))
- bucket = this->bucket_ptr_from_hash(hash_value);
-
- // Nothing after this point can throw.
-
- return std::pair<iterator_base, bool>(iterator_base(bucket,
- add_node(a, bucket)), true);
- }
- }
-
- // if hash function throws, basic exception safety
- // strong otherwise
- template <class H, class P, class A, class K>
- BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::value_type&
- hash_unique_table<H, P, A, K>
- ::operator[](key_type const& k)
- {
- typedef BOOST_DEDUCED_TYPENAME value_type::second_type mapped_type;
-
- std::size_t hash_value = this->hash_function()(k);
- bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
- node_ptr pos = find_iterator(bucket, k);
-
- if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
- return node::get_value(pos);
- }
- else {
- // Side effects only in this block.
-
- // 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);
-
- // reserve has basic exception safety if the hash function
- // throws, strong otherwise.
- if(reserve_for_insert(this->size_ + 1))
- bucket = this->bucket_ptr_from_hash(hash_value);
-
- // Nothing after this point can throw.
-
- return node::get_value(add_node(a, bucket));
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Insert methods
-
- template <class H, class P, class A, class K>
- BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::iterator_base
- hash_equivalent_table<H, P, A, K>
- ::emplace_impl(node_constructor& a)
- {
- key_type const& k = extractor::extract(a.get()->value());
- std::size_t hash_value = this->hash_function()(k);
- bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
- node_ptr position = find_iterator(bucket, k);
-
- // reserve has basic exception safety if the hash function
- // throws, strong otherwise.
- if(reserve_for_insert(this->size_ + 1))
- bucket = this->bucket_ptr_from_hash(hash_value);
-
- // I'm relying on node_ptr not being invalidated by
- // the rehash here.
- return iterator_base(bucket, add_node(a, bucket, position));
- }
-
- template <class H, class P, class A, class K>
- BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::iterator_base
- hash_equivalent_table<H, P, A, K>
- ::emplace_hint_impl(iterator_base const& it, node_constructor& a)
- {
- // equal can throw, but with no effects
- if (it.is_end() ||
- !equal(extractor::extract(a.get()->value()), node::get_value(it.get()))) {
- // Use the standard emplace if the iterator doesn't point
- // to a matching key.
- return emplace_impl(a);
- }
- else {
- // Find the first node in the group - so that the node
- // will be added at the end of the group.
-
- node_ptr start(it.node_);
- while(node::next_group(start) == start)
- start = node::group_prev(start);
-
- // reserve has basic exception safety if the hash function
- // throws, strong otherwise.
- bucket_ptr bucket = reserve_for_insert(this->size_ + 1) ?
- get_bucket(this->bucket_index(
- extractor::extract(a.get()->value()))) : it.bucket_;
-
- // Nothing after this point can throw
-
- return iterator_base(bucket, add_node(a, bucket, start));
- }
- }
-
- template <class H, class P, class A, class K>
- void hash_equivalent_table<H, P, A, K>
- ::emplace_impl_no_rehash(node_constructor& a)
- {
- key_type const& k = extractor::extract(a.get()->value());
- bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
- add_node(a, bucket, find_iterator(bucket, k));
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Equalilty check
-
- template <class H, class P, class A, class K>
- inline bool hash_equivalent_table<H, P, A, K>
- ::group_equals(node_ptr it1, node_ptr it2, set_extractor*)
- {
- return node::group_count(it1) == node::group_count(it2);
- }
-
- template <class H, class P, class A, class K>
- inline bool hash_equivalent_table<H, P, A, K>
- ::group_equals(node_ptr it1, node_ptr it2, map_extractor*)
- {
- node_ptr end1 = node::next_group(it1);
- node_ptr end2 = node::next_group(it2);
-
- do {
- if(node::get_value(it1).second != node::get_value(it2).second) return false;
- it1 = next_node(it1);
- it2 = next_node(it2);
- } while(it1 != end1 && it2 != end2);
- return it1 == end1 && it2 == end2;
- }
-
- template <class H, class P, class A, class K>
- bool hash_equivalent_table<H, P, A, K>
- ::equals(hash_equivalent_table<H, P, A, K> const& other) const
- {
- if(this->size_ != other.size_) return false;
-
- for(bucket_ptr i = this->cached_begin_bucket_, j = this->buckets_end(); i != j; ++i)
- {
- for(node_ptr it(i->next_); BOOST_UNORDERED_BORLAND_BOOL(it); it = node::next_group(it))
- {
- node_ptr other_pos = other.find_iterator(extractor::extract(node::get_value(it)));
- if(!BOOST_UNORDERED_BORLAND_BOOL(other_pos) ||
- !group_equals(it, other_pos, (K*)0))
- return false;
- }
- }
-
- return true;
- }
-
- template <class H, class P, class A, class K>
- inline bool hash_unique_table<H, P, A, K>
- ::group_equals(node_ptr, node_ptr, set_extractor*)
- {
- return true;
- }
-
- template <class H, class P, class A, class K>
- inline bool hash_unique_table<H, P, A, K>
- ::group_equals(node_ptr it1, node_ptr it2, map_extractor*)
- {
- return node::get_value(it1).second == node::get_value(it2).second;
- }
-
- template <class H, class P, class A, class K>
- bool hash_unique_table<H, P, A, K>
- ::equals(hash_unique_table<H, P, A, K> const& other) const
- {
- if(this->size_ != other.size_) return false;
-
- for(bucket_ptr i = this->cached_begin_bucket_, j = this->buckets_end(); i != j; ++i)
- {
- for(node_ptr it(i->next_); BOOST_UNORDERED_BORLAND_BOOL(it); it = node::next_group(it))
- {
- node_ptr other_pos = other.find_iterator(extractor::extract(node::get_value(it)));
- if(!BOOST_UNORDERED_BORLAND_BOOL(other_pos) ||
- !group_equals(it, other_pos, (K*)0))
- return false;
- }
- }
-
- return true;
- }
-
-}}
-
-#endif

Modified: trunk/boost/unordered/detail/move.hpp
==============================================================================
--- trunk/boost/unordered/detail/move.hpp (original)
+++ trunk/boost/unordered/detail/move.hpp 2009-09-20 17:55:15 EDT (Sun, 20 Sep 2009)
@@ -109,6 +109,8 @@
 {
     explicit move_from(T& x) : source(x) { }
     T& source;
+private:
+ move_from& operator=(move_from const&);
 };
 
 /*************************************************************************************************/

Modified: trunk/boost/unordered/detail/node.hpp
==============================================================================
--- trunk/boost/unordered/detail/node.hpp (original)
+++ trunk/boost/unordered/detail/node.hpp 2009-09-20 17:55:15 EDT (Sun, 20 Sep 2009)
@@ -24,23 +24,6 @@
 
 namespace boost { namespace unordered_detail {
 
- template <class BucketPtr>
- inline BucketPtr& next_node(BucketPtr ptr)
- {
- return ptr->next_;
- }
-
- template <class BucketPtr>
- inline std::size_t node_count(BucketPtr ptr, BucketPtr end)
- {
- std::size_t count = 0;
- while(ptr != end) {
- ++count;
- ptr = next_node(ptr);
- }
- return count;
- }
-
     ////////////////////////////////////////////////////////////////////////////
     // ungrouped node implementation
     
@@ -48,7 +31,7 @@
     inline BOOST_DEDUCED_TYPENAME ungrouped_node_base<A>::node_ptr&
         ungrouped_node_base<A>::next_group(node_ptr ptr)
     {
- return next_node(ptr);
+ return ptr->next_;
     }
 
     template <class A>
@@ -60,35 +43,24 @@
     template <class A>
     inline void ungrouped_node_base<A>::add_to_bucket(node_ptr n, bucket& b)
     {
- next_node(n) = b.next_;
+ n->next_ = b.next_;
         b.next_ = n;
     }
 
     template <class A>
- inline void ungrouped_node_base<A>::add_group_to_bucket(node_ptr n, bucket& b)
+ inline void ungrouped_node_base<A>::add_after_node(node_ptr n,
+ node_ptr position)
     {
- next_node(n) = b.next_;
- b.next_ = n;
- }
-
- template <class A>
- inline void ungrouped_node_base<A>::add_after_node(node_ptr n, node_ptr position)
- {
- next_node(n) = next_node(position);
- next_node(position) = position;
+ n->next_ = position->next_;
+ position->next_ = position;
     }
     
     template <class A>
- inline void ungrouped_node_base<A>::unlink_node(bucket& b, node_ptr node)
- {
- unlink_nodes(b, node, next_node(node));
- }
-
- template <class A>
- inline void ungrouped_node_base<A>::unlink_nodes(bucket& b, node_ptr begin, node_ptr end)
+ inline void ungrouped_node_base<A>::unlink_nodes(bucket& b,
+ node_ptr begin, node_ptr end)
     {
         node_ptr* pos = &b.next_;
- while(*pos != begin) pos = &next_node(*pos);
+ while(*pos != begin) pos = &(*pos)->next_;
         *pos = end;
     }
 
@@ -99,26 +71,30 @@
     }
 
     template <class A>
- inline void ungrouped_node_base<A>::unlink_group(node_ptr* b)
+ inline void ungrouped_node_base<A>::unlink_node(bucket& b, node_ptr node)
     {
- *b = next_node(*b);
+ unlink_nodes(b, node, node->next_);
     }
 
     ////////////////////////////////////////////////////////////////////////////
     // grouped node implementation
     
+ // If ptr is the first element in a group, return pointer to next group.
+ // Otherwise returns a pointer to ptr.
     template <class A>
     inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr&
- grouped_node_base<A>::group_prev(node_ptr ptr)
+ grouped_node_base<A>::next_group(node_ptr ptr)
     {
- return get(ptr).group_prev_;
+ return get(ptr).group_prev_->next_;
     }
 
     template <class A>
- inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr&
- grouped_node_base<A>::next_group(node_ptr ptr)
+ inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr
+ grouped_node_base<A>::first_in_group(node_ptr ptr)
     {
- return next_node(group_prev(ptr));
+ while(next_group(ptr) == ptr)
+ ptr = get(ptr).group_prev_;
+ return ptr;
     }
 
     template <class A>
@@ -128,7 +104,7 @@
         std::size_t size = 0;
         do {
             ++size;
- ptr = group_prev(ptr);
+ ptr = get(ptr).group_prev_;
         } while(ptr != start);
         return size;
     }
@@ -136,25 +112,18 @@
     template <class A>
     inline void grouped_node_base<A>::add_to_bucket(node_ptr n, bucket& b)
     {
- next_node(n) = b.next_;
- group_prev(n) = n;
+ n->next_ = b.next_;
+ get(n).group_prev_ = n;
         b.next_ = n;
     }
 
     template <class A>
- inline void grouped_node_base<A>::add_group_to_bucket(node_ptr n, bucket& b)
+ inline void grouped_node_base<A>::add_after_node(node_ptr n, node_ptr pos)
     {
- next_group(n) = b.next_;
- b.next_ = n;
- }
-
- template <class A>
- inline void grouped_node_base<A>::add_after_node(node_ptr n, node_ptr position)
- {
- next_node(n) = next_group(position);
- group_prev(n) = group_prev(position);
- next_group(position) = n;
- group_prev(position) = n;
+ n->next_ = next_group(pos);
+ get(n).group_prev_ = get(pos).group_prev_;
+ next_group(pos) = n;
+ get(pos).group_prev_ = n;
     }
 
     // Break a ciruclar list into two, with split as the beginning
@@ -164,29 +133,21 @@
     inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr
         grouped_node_base<A>::split_group(node_ptr split)
     {
- // If split is at the beginning of the group then there's
- // nothing to split.
- if(next_node(group_prev(split)) != split)
- return split;
-
- // Find the start of the group.
- node_ptr start = split;
- do {
- start = group_prev(start);
- } while(next_node(group_prev(start)) == start);
+ node_ptr first = first_in_group(split);
+ if(first == split) return split;
 
- node_ptr last = group_prev(start);
- group_prev(start) = group_prev(split);
- group_prev(split) = last;
+ node_ptr last = get(first).group_prev_;
+ get(first).group_prev_ = get(split).group_prev_;
+ get(split).group_prev_ = last;
 
- return start;
+ return first;
     }
 
     template <class A>
     void grouped_node_base<A>::unlink_node(bucket& b, node_ptr node)
     {
- node_ptr next = next_node(node);
- node_ptr* pos = &next_node(group_prev(node));
+ node_ptr next = node->next_;
+ node_ptr* pos = &next_group(node);
 
         if(*pos != node) {
             // The node is at the beginning of a group.
@@ -196,31 +157,37 @@
             while(*pos != node) pos = &next_group(*pos);
 
             // Remove from group
- if(BOOST_UNORDERED_BORLAND_BOOL(next) && group_prev(next) == node)
- group_prev(next) = group_prev(node);
+ if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
+ get(next).group_prev_ == node)
+ {
+ get(next).group_prev_ = get(node).group_prev_;
+ }
         }
- else if(BOOST_UNORDERED_BORLAND_BOOL(next) && group_prev(next) == node) {
+ else if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
+ get(next).group_prev_ == node)
+ {
             // The deleted node is not at the end of the group, so
             // change the link from the next node.
- group_prev(next) = group_prev(node);
+ get(next).group_prev_ = get(node).group_prev_;
         }
         else {
             // The deleted node is at the end of the group, so the
             // first node in the group is pointing to it.
             // Find that to change its pointer.
- node_ptr x = group_prev(node);
- while(group_prev(x) != node) {
- x = group_prev(x);
+ node_ptr x = get(node).group_prev_;
+ while(get(x).group_prev_ != node) {
+ x = get(x).group_prev_;
             }
- group_prev(x) = group_prev(node);
+ get(x).group_prev_ = get(node).group_prev_;
         }
         *pos = next;
     }
 
     template <class A>
- void grouped_node_base<A>::unlink_nodes(bucket& b, node_ptr begin, node_ptr end)
+ void grouped_node_base<A>::unlink_nodes(bucket& b,
+ node_ptr begin, node_ptr end)
     {
- node_ptr* pos = &next_node(group_prev(begin));
+ node_ptr* pos = &next_group(begin);
 
         if(*pos != begin) {
             // The node is at the beginning of a group.
@@ -238,10 +205,10 @@
                 node_ptr group2 = split_group(end);
 
                 if(begin == group2) {
- node_ptr end1 = group_prev(group1);
- node_ptr end2 = group_prev(group2);
- group_prev(group1) = end2;
- group_prev(group2) = end1;
+ node_ptr end1 = get(group1).group_prev_;
+ node_ptr end2 = get(group2).group_prev_;
+ get(group1).group_prev_ = end2;
+ get(group2).group_prev_ = end1;
                 }
             }
         }
@@ -254,12 +221,6 @@
         split_group(end);
         b.next_ = end;
     }
-
- template <class A>
- inline void grouped_node_base<A>::unlink_group(node_ptr* b)
- {
- *b = next_group(*b);
- }
 }}
 
 #endif

Modified: trunk/boost/unordered/detail/table.hpp
==============================================================================
--- trunk/boost/unordered/detail/table.hpp (original)
+++ trunk/boost/unordered/detail/table.hpp 2009-09-20 17:55:15 EDT (Sun, 20 Sep 2009)
@@ -23,20 +23,22 @@
 
     // strong exception safety, no side effects
     template <class H, class P, class A, class G, class K>
- inline bool hash_table<H, P, A, G, K>
- ::equal(key_type const& k, value_type const& v) const
+ inline bool hash_table<H, P, A, G, K>::equal(
+ key_type const& k, value_type const& v) const
     {
- return this->key_eq()(k, extractor::extract(v));
+ return this->key_eq()(k, get_key(v));
     }
 
     // strong exception safety, no side effects
     template <class H, class P, class A, class G, class K>
     inline BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::node_ptr
- hash_table<H, P, A, G, K>
- ::find_iterator(bucket_ptr bucket, key_type const& k) const
+ hash_table<H, P, A, G, K>::find_iterator(
+ bucket_ptr bucket, key_type const& k) const
     {
         node_ptr it = bucket->next_;
- while (BOOST_UNORDERED_BORLAND_BOOL(it) && !equal(k, node::get_value(it))) {
+ while (BOOST_UNORDERED_BORLAND_BOOL(it) &&
+ !equal(k, node::get_value(it)))
+ {
             it = node::next_group(it);
         }
 
@@ -44,23 +46,26 @@
     }
 
     // strong exception safety, no side effects
+ // pre: this->buckets_
     template <class H, class P, class A, class G, class K>
     inline BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::node_ptr
- hash_table<H, P, A, G, K>
- ::find_iterator(key_type const& k) const
+ hash_table<H, P, A, G, K>::find_iterator(key_type const& k) const
     {
         return find_iterator(this->get_bucket(this->bucket_index(k)), k);
     }
 
     // strong exception safety, no side effects
     template <class H, class P, class A, class G, class K>
- BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::node_ptr*
- hash_table<H, P, A, G, K>
- ::find_for_erase(bucket_ptr bucket, key_type const& k) const
+ inline BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::node_ptr*
+ hash_table<H, P, A, G, K>::find_for_erase(
+ bucket_ptr bucket, key_type const& k) const
     {
         node_ptr* it = &bucket->next_;
- while(BOOST_UNORDERED_BORLAND_BOOL(*it) && !equal(k, node::get_value(*it)))
+ while(BOOST_UNORDERED_BORLAND_BOOL(*it) &&
+ !equal(k, node::get_value(*it)))
+ {
             it = &node::next_group(*it);
+ }
 
         return it;
     }
@@ -70,8 +75,7 @@
 
     // no throw
     template <class H, class P, class A, class G, class K>
- std::size_t hash_table<H, P, A, G, K>
- ::max_size() const
+ std::size_t hash_table<H, P, A, G, K>::max_size() const
     {
         using namespace std;
 
@@ -82,27 +86,37 @@
 
     // strong safety
     template <class H, class P, class A, class G, class K>
- std::size_t hash_table<H, P, A, G, K>
- ::bucket_index(key_type const& k) const
+ inline std::size_t hash_table<H, P, A, G, K>::bucket_index(
+ key_type const& k) const
     {
         // hash_function can throw:
- return this->bucket_from_hash(this->hash_function()(k));
+ return this->hash_function()(k) % this->bucket_count_;
     }
 
 
+ // no throw
     template <class H, class P, class A, class G, class K>
- void hash_table<H, P, A, G, K>
- ::max_load_factor(float z)
+ inline std::size_t hash_table<H, P, A, G, K>::calculate_max_load()
+ {
+ using namespace std;
+
+ // From 6.3.1/13:
+ // Only resize when size >= mlf_ * count
+ return double_to_size_t(ceil((double) mlf_ * this->bucket_count_));
+ }
+
+ template <class H, class P, class A, class G, class K>
+ void hash_table<H, P, A, G, K>::max_load_factor(float z)
     {
         BOOST_ASSERT(z > 0);
         mlf_ = (std::max)(z, minimum_max_load_factor);
- this->calculate_max_load();
+ this->max_load_ = this->calculate_max_load();
     }
 
     // no throw
     template <class H, class P, class A, class G, class K>
- std::size_t hash_table<H, P, A, G, K>
- ::min_buckets_for_size(std::size_t n) const
+ inline std::size_t hash_table<H, P, A, G, K>::min_buckets_for_size(
+ std::size_t n) const
     {
         BOOST_ASSERT(this->mlf_ != 0);
 
@@ -114,130 +128,146 @@
         //
         // Or from rehash post-condition:
         // count > size / mlf_
- return double_to_size_t(floor(n / (double) mlf_)) + 1;
+ return next_prime(double_to_size_t(floor(n / (double) mlf_)) + 1);
     }
 
- // no throw
+ ////////////////////////////////////////////////////////////////////////////
+ // recompute_begin_bucket
+
+ // init_buckets
+
     template <class H, class P, class A, class G, class K>
- void hash_table<H, P, A, G, K>
- ::calculate_max_load()
+ inline void hash_table<H, P, A, G, K>::init_buckets()
     {
- using namespace std;
-
- // From 6.3.1/13:
- // Only resize when size >= mlf_ * count
- max_load_ = double_to_size_t(ceil((double) mlf_ * this->bucket_count()));
+ if (this->size_) {
+ this->cached_begin_bucket_ = this->buckets_;
+ while (!this->cached_begin_bucket_->next_)
+ ++this->cached_begin_bucket_;
+ } else {
+ this->cached_begin_bucket_ = this->get_bucket(this->bucket_count_);
+ }
+ this->max_load_ = calculate_max_load();
     }
 
- ////////////////////////////////////////////////////////////////////////////
- // Constructors
+ // After an erase cached_begin_bucket_ might be left pointing to
+ // an empty bucket, so this is called to update it
+ //
+ // no throw
 
     template <class H, class P, class A, class G, class K>
- hash_table<H, P, A, G, K>
- ::hash_table(std::size_t n, hasher const& hf, key_equal const& eq, value_allocator const& a) :
- buckets(a, next_prime(n)), func_(false), cached_begin_bucket_(), size_(), mlf_(1.0f), max_load_(0)
- {
- std::uninitialized_fill((functions*)this->funcs_, (functions*)this->funcs_+2,
- functions(hf, eq));
- this->cached_begin_bucket_ = this->buckets_end();
- this->calculate_max_load();
- }
+ inline void hash_table<H, P, A, G, K>::recompute_begin_bucket(bucket_ptr b)
+ {
+ BOOST_ASSERT(!(b < this->cached_begin_bucket_));
 
- template <class H, class P, class A, class G, class K>
- hash_table<H, P, A, G, K>
- ::hash_table(hash_table const& x) :
- buckets(x.node_alloc(), next_prime(x.min_buckets_for_size(x.size_))), func_(false), cached_begin_bucket_(), size_(), mlf_(x.mlf_), max_load_(0)
- {
- std::uninitialized_fill((functions*)this->funcs_, (functions*)this->funcs_+2,
- x.current());
- this->calculate_max_load();
- x.copy_buckets_to(*this);
- this->size_ = x.size_;
- this->recompute_begin_bucket();
+ if(b == this->cached_begin_bucket_)
+ {
+ if (this->size_ != 0) {
+ while (!this->cached_begin_bucket_->next_)
+ ++this->cached_begin_bucket_;
+ } else {
+ this->cached_begin_bucket_ =
+ this->get_bucket(this->bucket_count_);
+ }
+ }
     }
 
- // Copy Construct with allocator
+ // This is called when a range has been erased
+ //
+ // no throw
 
     template <class H, class P, class A, class G, class K>
- hash_table<H, P, A, G, K>
- ::hash_table(hash_table const& x, value_allocator const& a) :
- buckets(a, next_prime(x.min_buckets_for_size(x.size_))), func_(false), cached_begin_bucket_(), size_(), mlf_(x.mlf_), max_load_(0)
- {
- std::uninitialized_fill((functions*)this->funcs_, (functions*)this->funcs_+2,
- x.current());
- this->cached_begin_bucket_ = this->buckets_end();
- this->calculate_max_load();
- x.copy_buckets_to(*this);
- this->size_ = x.size_;
- this->recompute_begin_bucket();
- }
+ inline void hash_table<H, P, A, G, K>::recompute_begin_bucket(
+ bucket_ptr b1, bucket_ptr b2)
+ {
+ BOOST_ASSERT(!(b1 < this->cached_begin_bucket_) && !(b2 < b1));
+ BOOST_ASSERT(BOOST_UNORDERED_BORLAND_BOOL(b2->next_));
 
- // Move Construct
+ if(b1 == this->cached_begin_bucket_ && !b1->next_)
+ this->cached_begin_bucket_ = b2;
+ }
 
+ // no throw
     template <class H, class P, class A, class G, class K>
- hash_table<H, P, A, G, K>
- ::hash_table(hash_table& x, move_tag m) :
- buckets(x, m), func_(false), cached_begin_bucket_(), size_(), mlf_(x.mlf_), max_load_(0)
+ inline float hash_table<H, P, A, G, K>::load_factor() const
     {
- this->cached_begin_bucket_ = x.cached_begin_bucket_;
- this->size_ = x.size_;
- x.cached_begin_bucket_ = bucket_ptr();
- x.size_ = 0;
+ BOOST_ASSERT(this->bucket_count_ != 0);
+ return static_cast<float>(this->size_)
+ / static_cast<float>(this->bucket_count_);
+ }
 
- // TODO: Shouldn't I move the functions if poss.
- std::uninitialized_fill((functions*)this->funcs_, (functions*)this->funcs_+2,
- x.current());
- }
+ ////////////////////////////////////////////////////////////////////////////
+ // Constructors
 
     template <class H, class P, class A, class G, class K>
- hash_table<H, P, A, G, K>
- ::hash_table(hash_table& x, value_allocator const& a, move_tag m) :
- buckets(x, a, m), func_(false), cached_begin_bucket_(), size_(), mlf_(x.mlf_), max_load_(0)
+ hash_table<H, P, A, G, K>::hash_table(std::size_t n,
+ hasher const& hf, key_equal const& eq, node_allocator const& a)
+ : buckets(a, next_prime(n)),
+ base(hf, eq),
+ size_(),
+ mlf_(1.0f),
+ cached_begin_bucket_(),
+ max_load_(0)
     {
- std::uninitialized_fill((functions*)this->funcs_, (functions*)this->funcs_+2,
- x.current());
+ }
 
- this->calculate_max_load(); // no throw
+ // Copy Construct with allocator
 
- if(!this->buckets_) {
- buckets new_buckets(this->node_alloc(), x.min_buckets_for_size(x.size_));
- x.copy_buckets_to(new_buckets);
- new_buckets.swap(*this);
- this->size_ = x.size_;
- this->recompute_begin_bucket();
- }
- else {
- this->cached_begin_bucket_ = x.cached_begin_bucket_;
- this->size_ = x.size_;
- x.cached_begin_bucket_ = bucket_ptr();
- x.size_ = 0;
+ template <class H, class P, class A, class G, class K>
+ hash_table<H, P, A, G, K>::hash_table(hash_table const& x,
+ node_allocator const& a)
+ : buckets(a, x.min_buckets_for_size(x.size_)),
+ base(x),
+ size_(x.size_),
+ mlf_(x.mlf_),
+ cached_begin_bucket_(),
+ max_load_(0)
+ {
+ if(x.size_) {
+ x.copy_buckets_to(*this);
+ this->init_buckets();
         }
     }
 
+ // Move Construct
+
     template <class H, class P, class A, class G, class K>
- hash_table<H, P, A, G, K>::~hash_table()
- {
- BOOST_UNORDERED_DESTRUCT(this->get_functions(false), functions);
- BOOST_UNORDERED_DESTRUCT(this->get_functions(true), functions);
+ hash_table<H, P, A, G, K>::hash_table(hash_table& x, move_tag)
+ : buckets(x.node_alloc(), x.bucket_count_),
+ base(x),
+ size_(0),
+ mlf_(1.0f),
+ cached_begin_bucket_(),
+ max_load_(0)
+ {
+ this->partial_swap(x);
     }
 
- // TODO: Reuse current nodes amd buckets?
     template <class H, class P, class A, class G, class K>
- hash_table<H, P, A, G, K>& hash_table<H, P, A, G, K>::operator=(hash_table const& x)
+ hash_table<H, P, A, G, K>::hash_table(hash_table& x,
+ node_allocator const& a, move_tag)
+ : buckets(a, x.bucket_count_),
+ base(x),
+ size_(0),
+ mlf_(x.mlf_),
+ cached_begin_bucket_(),
+ max_load_(0)
     {
- if(this != &x) {
- this->clear(); // no throw
- this->set_functions(
- this->buffer_functions(x)); // throws, strong
- this->mlf_ = x.mlf_; // no throw
- buckets new_buckets(this->node_alloc(), x.min_buckets_for_size(x.size_));
- x.copy_buckets_to(new_buckets);
- new_buckets.swap(*this);
- this->calculate_max_load(); // no throw
+ if(a == x.node_alloc()) {
+ this->partial_swap(x);
+ }
+ else if(x.size_) {
+ x.copy_buckets_to(*this);
             this->size_ = x.size_;
- this->recompute_begin_bucket();
+ this->init_buckets();
         }
+ }
 
+ template <class H, class P, class A, class G, class K>
+ hash_table<H, P, A, G, K>& hash_table<H, P, A, G, K>::operator=(
+ hash_table const& x)
+ {
+ hash_table tmp(x, this->node_alloc());
+ this->fast_swap(tmp);
         return *this;
     }
 
@@ -252,58 +282,81 @@
     // or if allocators are unequal.
 
     template <class H, class P, class A, class G, class K>
- void hash_table<H, P, A, G, K>
- ::swap(hash_table& x)
+ inline void hash_table<H, P, A, G, K>::partial_swap(hash_table& x)
     {
- // The swap code can work when swapping a container with itself
- // but it triggers an assertion in buffered_functions.
- // At the moment, I'd rather leave that assertion in and add a
- // check here, rather than remove the assertion. I might change
- // this at a later date.
- if(this == &x) return;
+ this->buckets::swap(x); // No throw
+ std::swap(this->size_, x.size_);
+ std::swap(this->mlf_, x.mlf_);
+ std::swap(this->cached_begin_bucket_, x.cached_begin_bucket_);
+ std::swap(this->max_load_, x.max_load_);
+ }
 
+ template <class H, class P, class A, class G, class K>
+ inline void hash_table<H, P, A, G, K>::fast_swap(hash_table& x)
+ {
         // These can throw, but they only affect the function objects
         // that aren't in use so it is strongly exception safe, via.
         // double buffering.
- functions_ptr new_func_this = this->buffer_functions(x);
- functions_ptr new_func_that = x.buffer_functions(*this);
-
- if(this->node_alloc() == x.node_alloc()) {
- this->buckets::swap(x); // No throw
- std::swap(this->cached_begin_bucket_, x.cached_begin_bucket_);
- std::swap(this->size_, x.size_);
+ {
+ set_hash_functions<H, P> op1(*this, x);
+ set_hash_functions<H, P> op2(x, *this);
+ op1.commit();
+ op2.commit();
         }
- else {
+ this->buckets::swap(x); // No throw
+ std::swap(this->size_, x.size_);
+ std::swap(this->mlf_, x.mlf_);
+ std::swap(this->cached_begin_bucket_, x.cached_begin_bucket_);
+ std::swap(this->max_load_, x.max_load_);
+ }
+
+ template <class H, class P, class A, class G, class K>
+ inline void hash_table<H, P, A, G, K>::slow_swap(hash_table& x)
+ {
+ if(this == &x) return;
+
+ {
+ // These can throw, but they only affect the function objects
+ // that aren't in use so it is strongly exception safe, via.
+ // double buffering.
+ set_hash_functions<H, P> op1(*this, x);
+ set_hash_functions<H, P> op2(x, *this);
+
             // Create new buckets in separate hash_buckets objects
             // which will clean up if anything throws an exception.
             // (all can throw, but with no effect as these are new objects).
-
- buckets new_this(this->node_alloc(), x.min_buckets_for_size(x.size_));
- x.copy_buckets_to(new_this);
-
- buckets new_that(x.node_alloc(), this->min_buckets_for_size(this->size_));
- copy_buckets_to(new_that);
-
+
+ buckets b1(this->node_alloc(), x.min_buckets_for_size(x.size_));
+ if(x.size_) x.copy_buckets_to(b1);
+
+ buckets b2(x.node_alloc(), this->min_buckets_for_size(this->size_));
+ if(this->size_) copy_buckets_to(b2);
+
             // Modifying the data, so no throw from now on.
-
- this->buckets::swap(new_this);
- x.buckets::swap(new_that);
- std::swap(this->size_, x.size_);
- this->recompute_begin_bucket();
- x.recompute_begin_bucket();
+
+ b1.swap(*this);
+ b2.swap(x);
+ op1.commit();
+ op2.commit();
         }
+
+ std::swap(this->size_, x.size_);
 
- // The rest is no throw.
-
- std::swap(this->mlf_, x.mlf_);
-
- this->set_functions(new_func_this);
- x.set_functions(new_func_that);
+ if(this->buckets_) this->init_buckets();
+ if(x.buckets_) x.init_buckets();
+ }
 
- //TODO: Test that this works:
- this->calculate_max_load();
- x.calculate_max_load();
+ template <class H, class P, class A, class G, class K>
+ void hash_table<H, P, A, G, K>::swap(hash_table& x)
+ {
+ if(this->node_alloc() == x.node_alloc()) {
+ if(this != &x) this->fast_swap(x);
+ }
+ else {
+ this->slow_swap(x);
+ }
     }
+
     
     // Move
     //
@@ -313,40 +366,37 @@
     // or if allocators are unequal.
 
     template <class H, class P, class A, class G, class K>
- void hash_table<H, P, A, G, K>
- ::move(hash_table& x)
+ void hash_table<H, P, A, G, K>::move(hash_table& x)
     {
         // This can throw, but it only affects the function objects
         // that aren't in use so it is strongly exception safe, via.
         // double buffering.
- functions_ptr new_func_this = this->buffer_functions(x);
+ set_hash_functions<H, P> new_func_this(*this, x);
 
         if(this->node_alloc() == x.node_alloc()) {
             this->buckets::move(x); // no throw
             this->size_ = x.size_;
             this->cached_begin_bucket_ = x.cached_begin_bucket_;
+ this->max_load_ = x.max_load_;
             x.size_ = 0;
- x.cached_begin_bucket_ = bucket_ptr();
         }
         else {
             // Create new buckets in separate HASH_TABLE_DATA objects
             // which will clean up if anything throws an exception.
             // (all can throw, but with no effect as these are new objects).
             
- buckets new_this(this->node_alloc(), next_prime(x.min_buckets_for_size(x.size_)));
- x.copy_buckets_to(new_this);
+ buckets b(this->node_alloc(), x.min_buckets_for_size(x.size_));
+ if(x.size_) x.copy_buckets_to(b);
 
             // Start updating the data here, no throw from now on.
- this->buckets::move(new_this);
             this->size_ = x.size_;
- this->recompute_begin_bucket();
+ b.swap(*this);
+ this->init_buckets();
         }
 
         // We've made it, the rest is no throw.
         this->mlf_ = x.mlf_;
- this->set_functions(new_func_this);
-
- this->calculate_max_load();
+ new_func_this.commit();
     }
     
     ////////////////////////////////////////////////////////////////////////////
@@ -354,96 +404,100 @@
 
     // basic exception safety
     template <class H, class P, class A, class G, class K>
- inline bool hash_table<H, P, A, G, K>
- ::reserve(std::size_t n)
+ inline void hash_table<H, P, A, G, K>::create_for_insert(std::size_t n)
     {
- bool need_to_reserve = n >= this->max_load_;
- // throws - basic:
- if (need_to_reserve) rehash_impl(this->min_buckets_for_size(n));
- BOOST_ASSERT(n < this->max_load_ || n > max_size());
- return need_to_reserve;
+ if(n > this->bucket_count_)
+ this->bucket_count_ = this->min_buckets_for_size(n);
+ this->create_buckets();
+ this->init_buckets();
     }
 
     // basic exception safety
     template <class H, class P, class A, class G, class K>
- inline bool hash_table<H, P, A, G, K>
- ::reserve_for_insert(std::size_t n)
+ inline bool hash_table<H, P, A, G, K>::reserve_for_insert(std::size_t n)
     {
- bool need_to_reserve = n >= this->max_load_;
- // throws - basic:
- if (need_to_reserve) {
+ if(n >= max_load_) {
             std::size_t s = this->size_;
             s = s + (s >> 1);
- s = s > n ? s : n;
- rehash_impl(this->min_buckets_for_size(s));
+ n = this->min_buckets_for_size(s > n ? s : n);
+ if(n != this->bucket_count_) {
+ rehash_impl(n);
+ return true;
+ }
         }
- BOOST_ASSERT(n < this->max_load_ || n > max_size());
- return need_to_reserve;
+
+ return false;
     }
 
     // if hash function throws, basic exception safety
     // strong otherwise.
+ // TODO: Should this always create buckets?
     template <class H, class P, class A, class G, class K>
- void hash_table<H, P, A, G, K>
+ inline void hash_table<H, P, A, G, K>
         ::rehash(std::size_t n)
     {
         using namespace std;
 
- // no throw:
- std::size_t min_size = this->min_buckets_for_size(this->size_);
- // basic/strong:
- rehash_impl(min_size > n ? min_size : n);
+ if(!this->buckets_) {
+ this->bucket_count_ = next_prime(n);
+ this->create_buckets();
+ this->init_buckets();
+ }
+ else if(n != this->bucket_count_) {
+ // no throw:
+ // TODO: Needlessly calling next_prime twice.
+ std::size_t min_size = this->min_buckets_for_size(this->size_);
+ n = next_prime(n);
+ n = min_size > n ? min_size : n;
 
- BOOST_ASSERT((float) this->bucket_count() > (float) this->size_ / this->mlf_
- && this->bucket_count() >= n);
+ rehash_impl(n);
+ }
     }
 
     // if hash function throws, basic exception safety
     // strong otherwise
 
+ // TODO: Rewrite so that it doesn't need to keep updating size_.
+
     template <class H, class P, class A, class G, class K>
     void hash_table<H, P, A, G, K>
         ::rehash_impl(std::size_t n)
- {
- n = next_prime(n); // no throw
-
- if (n == this->bucket_count()) // no throw
- return;
-
- // Save the size to restore it if successful
+ {
+ hasher const& hf = this->hash_function();
         std::size_t size = this->size_;
+ bucket_ptr end = this->get_bucket(this->bucket_count_);
 
- // Create another buckets to move the nodes into.
- buckets dst(this->node_alloc(), n);// throws, separate
+ buckets dst(this->node_alloc(), n);
+ dst.create_buckets();
 
- // Move the nodes to dst.
- hasher const& hf = this->hash_function();
- bucket_ptr end = this->buckets_end();
+ buckets src(this->node_alloc(), this->bucket_count_);
+ src.swap(*this);
+ this->size_ = 0;
 
- for(; this->cached_begin_bucket_ != end; ++this->cached_begin_bucket_) {
- bucket_ptr src_bucket = this->cached_begin_bucket_;
- while(src_bucket->next_) {
- // Move the first group of equivalent nodes in
- // src_bucket to dst.
+ for(bucket_ptr bucket = this->cached_begin_bucket_;
+ bucket != end; ++bucket)
+ {
+ node_ptr group = bucket->next_;
+ while(group) {
+ // Move the first group of equivalent nodes in bucket to dst.
 
                 // This next line throws iff the hash function throws.
                 bucket_ptr dst_bucket = dst.bucket_ptr_from_hash(
- hf(extractor::extract(node::get_value(src_bucket->next_))));
+ hf(get_key_from_ptr(group)));
 
-
- node_ptr n = src_bucket->next_;
- this->size_ -= node::group_count(n);
- node::unlink_group(&src_bucket->next_);
- node::add_group_to_bucket(n, *dst_bucket);
+ node_ptr& next_group = node::next_group(group);
+ bucket->next_ = next_group;
+ next_group = dst_bucket->next_;
+ dst_bucket->next_ = group;
+ group = bucket->next_;
             }
         }
 
         // Swap the new nodes back into the container and setup the local
         // variables.
- dst.swap(*this); // no throw
         this->size_ = size;
- this->recompute_begin_bucket(); // no throw
- this->calculate_max_load(); // no throw
+ dst.swap(*this); // no throw
+ this->init_buckets();
     }
 
     ////////////////////////////////////////////////////////////////////////////
@@ -458,12 +512,13 @@
     void hash_table<H, P, A, G, K>
         ::copy_buckets_to(buckets& dst) const
     {
- BOOST_ASSERT(this->buckets_ && dst.buckets_);
+ BOOST_ASSERT(this->buckets_ && !dst.buckets_);
 
         hasher const& hf = this->hash_function();
- bucket_ptr end = this->buckets_end();
+ bucket_ptr end = this->get_bucket(this->bucket_count_);
 
         hash_node_constructor<A, G> a(dst);
+ dst.create_buckets();
 
         // no throw:
         for(bucket_ptr i = this->cached_begin_bucket_; i != end; ++i) {
@@ -471,7 +526,7 @@
             for(node_ptr it = i->next_; it;) {
                 // hash function can throw.
                 bucket_ptr dst_bucket = dst.bucket_ptr_from_hash(
- hf(extractor::extract(node::get_value(it))));
+ hf(get_key_from_ptr(it)));
                 // throws, strong
 
                 node_ptr group_end = node::next_group(it);
@@ -480,7 +535,7 @@
                 node_ptr n = a.release();
                 node::add_to_bucket(n, *dst_bucket);
         
- for(it = next_node(it); it != group_end; it = next_node(it)) {
+ for(it = it->next_; it != group_end; it = it->next_) {
                     a.construct(node::get_value(it));
                     node::add_after_node(a.release(), n);
                 }
@@ -498,8 +553,7 @@
     // strong exception safety, no side effects
 
     template <class H, class P, class A, class G, class K>
- std::size_t hash_table<H, P, A, G, K>
- ::count(key_type const& k) const
+ std::size_t hash_table<H, P, A, G, K>::count(key_type const& k) const
     {
         if(!this->size_) return 0;
         node_ptr it = find_iterator(k); // throws, strong
@@ -511,8 +565,7 @@
     // strong exception safety, no side effects
     template <class H, class P, class A, class G, class K>
     BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::iterator_base
- hash_table<H, P, A, G, K>
- ::find(key_type const& k) const
+ hash_table<H, P, A, G, K>::find(key_type const& k) const
     {
         if(!this->size_) return this->end();
 
@@ -527,8 +580,7 @@
 
     template <class H, class P, class A, class G, class K>
     BOOST_DEDUCED_TYPENAME A::value_type&
- hash_table<H, P, A, G, K>
- ::at(key_type const& k) const
+ hash_table<H, P, A, G, K>::at(key_type const& k) const
     {
         if(!this->size_)
             throw std::out_of_range("Unable to find key in unordered_map.");
@@ -546,26 +598,22 @@
     //
     // strong exception safety, no side effects
     template <class H, class P, class A, class G, class K>
- std::pair<
- BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::iterator_base,
- BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::iterator_base
- >
- hash_table<H, P, A, G, K>
- ::equal_range(key_type const& k) const
+ BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::iterator_pair
+ hash_table<H, P, A, G, K>::equal_range(key_type const& k) const
     {
         if(!this->size_)
- return std::pair<iterator_base, iterator_base>(this->end(), this->end());
+ return iterator_pair(this->end(), this->end());
 
         bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
         node_ptr it = find_iterator(bucket, k);
         if (BOOST_UNORDERED_BORLAND_BOOL(it)) {
             iterator_base first(iterator_base(bucket, it));
             iterator_base second(first);
- second.increment(node::next_group(second.node_));
- return std::pair<iterator_base, iterator_base>(first, second);
+ second.increment_bucket(node::next_group(second.node_));
+ return iterator_pair(first, second);
         }
         else {
- return std::pair<iterator_base, iterator_base>(this->end(), this->end());
+ return iterator_pair(this->end(), this->end());
         }
     }
     
@@ -575,18 +623,37 @@
     template <class H, class P, class A, class G, class K>
     void hash_table<H, P, A, G, K>::clear()
     {
- for(bucket_ptr begin = this->buckets_begin(), end = this->buckets_end(); begin != end; ++begin) {
+ // TODO: Is this check needed when called internally?
+ if(!this->size_) return;
+
+ bucket_ptr end = this->get_bucket(this->bucket_count_);
+ for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
             this->clear_bucket(begin);
         }
 
- this->cached_begin_bucket_ = this->buckets_end();
         this->size_ = 0;
+ this->cached_begin_bucket_ = end;
     }
 
     template <class H, class P, class A, class G, class K>
+ inline std::size_t hash_table<H, P, A, G, K>::erase_group(
+ node_ptr* it, bucket_ptr bucket)
+ {
+ node_ptr pos = *it;
+ node_ptr end = node::next_group(pos);
+ *it = end;
+ std::size_t count = this->delete_nodes(pos, end);
+ this->size_ -= count;
+ this->recompute_begin_bucket(bucket);
+ return count;
+ }
+
+ template <class H, class P, class A, class G, class K>
     std::size_t hash_table<H, P, A, G, K>
         ::erase_key(key_type const& k)
     {
+ if(!this->size_) return 0;
+
         // No side effects in initial section
         bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
         node_ptr* it = this->find_for_erase(bucket, k);
@@ -600,135 +667,78 @@
     BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::iterator_base
         hash_table<H, P, A, G, K>::erase(iterator_base r)
     {
- BOOST_ASSERT(!r.is_end());
+ BOOST_ASSERT(r.node_);
         iterator_base next = r;
         next.increment();
         --this->size_;
         node::unlink_node(*r.bucket_, r.node_);
- this->destruct_node(r.node_);
+ this->delete_node(r.node_);
         // r has been invalidated but its bucket is still valid
         this->recompute_begin_bucket(r.bucket_, next.bucket_);
         return next;
     }
 
     template <class H, class P, class A, class G, class K>
- inline std::size_t hash_table<H, P, A, G, K>::erase_group(node_ptr* it, bucket_ptr bucket)
- {
- node_ptr pos = *it;
- std::size_t count = node::group_count(*it);
- this->size_ -= count;
- node::unlink_group(it);
- this->delete_group(pos);
- this->recompute_begin_bucket(bucket);
- return count;
- }
-
- template <class H, class P, class A, class G, class K>
     BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::iterator_base
- hash_table<H, P, A, G, K>::erase_range(iterator_base r1, iterator_base r2)
+ hash_table<H, P, A, G, K>::erase_range(
+ iterator_base r1, iterator_base r2)
     {
         if(r1 != r2)
         {
- BOOST_ASSERT(!r1.is_end());
-
+ BOOST_ASSERT(r1.node_);
             if (r1.bucket_ == r2.bucket_) {
- this->size_ -= node_count(r1.node_, r2.node_);
                 node::unlink_nodes(*r1.bucket_, r1.node_, r2.node_);
- this->delete_nodes(r1.node_, r2.node_);
+ this->size_ -= this->delete_nodes(r1.node_, r2.node_);
 
                 // No need to call recompute_begin_bucket because
                 // the nodes are only deleted from one bucket, which
                 // still contains r2 after the erase.
- BOOST_ASSERT(r1.bucket_->next_);
+ BOOST_ASSERT(r1.bucket_->next_);
             }
             else {
- BOOST_ASSERT(r1.bucket_ < r2.bucket_);
-
- this->size_ -= node_count(r1.node_, node_ptr());
+ bucket_ptr end_bucket = r2.node_ ?
+ r2.bucket_ : this->get_bucket(this->bucket_count_);
+ BOOST_ASSERT(r1.bucket_ < end_bucket);
                 node::unlink_nodes(*r1.bucket_, r1.node_, node_ptr());
- this->delete_to_bucket_end(r1.node_);
+ this->size_ -= this->delete_nodes(r1.node_, node_ptr());
 
                 bucket_ptr i = r1.bucket_;
- for(++i; i != r2.bucket_; ++i) {
- this->size_ -= node_count(i->next_, node_ptr());
- this->clear_bucket(i);
+ for(++i; i != end_bucket; ++i) {
+ this->size_ -= this->delete_nodes(i->next_, node_ptr());
+ i->next_ = node_ptr();
                 }
 
- if(!r2.is_end()) {
+ if(r2.node_) {
                     node_ptr first = r2.bucket_->next_;
- this->size_ -= node_count(r2.bucket_->next_, r2.node_);
                     node::unlink_nodes(*r2.bucket_, r2.node_);
- this->delete_nodes(first, r2.node_);
+ this->size_ -= this->delete_nodes(first, r2.node_);
                 }
 
                 // r1 has been invalidated but its bucket is still
                 // valid.
- this->recompute_begin_bucket(r1.bucket_, r2.bucket_);
+ this->recompute_begin_bucket(r1.bucket_, end_bucket);
             }
         }
 
         return r2;
     }
 
-
- template <class H, class P, class A, class G, class K>
- inline void hash_table<H, P, A, G, K>::recompute_begin_bucket()
- {
- if (this->size_ != 0) {
- this->cached_begin_bucket_ = this->buckets_begin();
- while (!this->cached_begin_bucket_->next_)
- ++this->cached_begin_bucket_;
- } else {
- this->cached_begin_bucket_ = this->buckets_end();
- }
- }
-
- // recompute_begin_bucket
- //
- // After an erase cached_begin_bucket_ might be left pointing to
- // an empty bucket, so this is called to update it
- //
- // no throw
-
- template <class H, class P, class A, class G, class K>
- inline void hash_table<H, P, A, G, K>::recompute_begin_bucket(bucket_ptr b)
- {
- BOOST_ASSERT(!(b < this->cached_begin_bucket_));
-
- if(b == this->cached_begin_bucket_)
- {
- if (this->size_ != 0) {
- while (!this->cached_begin_bucket_->next_)
- ++this->cached_begin_bucket_;
- } else {
- this->cached_begin_bucket_ = this->buckets_end();
- }
- }
- }
-
- // This is called when a range has been erased
- //
- // no throw
-
     template <class H, class P, class A, class G, class K>
- inline void hash_table<H, P, A, G, K>::recompute_begin_bucket(bucket_ptr b1, bucket_ptr b2)
+ BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::iterator_base
+ hash_table<H, P, A, G, K>::emplace_empty_impl_with_node(
+ node_constructor& a, std::size_t n)
     {
- BOOST_ASSERT(!(b1 < this->cached_begin_bucket_) && !(b2 < b1));
- BOOST_ASSERT(BOOST_UNORDERED_BORLAND_BOOL(b2->next_));
-
- if(b1 == this->cached_begin_bucket_ && !b1->next_)
- this->cached_begin_bucket_ = b2;
+ key_type const& k = get_key(a.value());
+ std::size_t hash_value = this->hash_function()(k);
+ if(this->buckets_) this->reserve_for_insert(n);
+ else this->create_for_insert(n);
+ bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
+ node_ptr node = a.release();
+ node::add_to_bucket(node, *bucket);
+ ++this->size_;
+ this->cached_begin_bucket_ = bucket;
+ return iterator_base(bucket, node);
     }
-
- // no throw
- template <class H, class P, class A, class G, class K>
- inline float hash_table<H, P, A, G, K>::load_factor() const
- {
- BOOST_ASSERT(this->bucket_count_ != 0);
- return static_cast<float>(this->size_)
- / static_cast<float>(this->bucket_count_);
- }
-
 }}
 
 #endif

Added: trunk/boost/unordered/detail/unique.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/unordered/detail/unique.hpp 2009-09-20 17:55:15 EDT (Sun, 20 Sep 2009)
@@ -0,0 +1,431 @@
+
+// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
+// Copyright (C) 2005-2009 Daniel James
+// 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/table.hpp>
+#include <boost/unordered/detail/extract_key.hpp>
+
+namespace boost { namespace unordered_detail {
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Equality
+
+ template <class H, class P, class A, class K>
+ bool hash_unique_table<H, P, A, K>
+ ::equals(hash_unique_table<H, P, A, K> const& other) const
+ {
+ if(this->size_ != other.size_) return false;
+ if(!this->size_) return true;
+
+ bucket_ptr end = this->get_bucket(this->bucket_count_);
+ for(bucket_ptr i = this->cached_begin_bucket_; i != end; ++i)
+ {
+ node_ptr it1 = i->next_;
+ while(BOOST_UNORDERED_BORLAND_BOOL(it1))
+ {
+ node_ptr it2 = other.find_iterator(get_key_from_ptr(it1));
+ if(!BOOST_UNORDERED_BORLAND_BOOL(it2)) return false;
+ if(!extractor::compare_mapped(
+ node::get_value(it1), node::get_value(it2)))
+ return false;
+ it1 = it1->next_;
+ }
+ }
+
+ return true;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // A convenience method for adding nodes.
+
+ template <class H, class P, class A, class K>
+ inline BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::node_ptr
+ hash_unique_table<H, P, A, K>::add_node(node_constructor& a,
+ bucket_ptr bucket)
+ {
+ node_ptr n = a.release();
+ node::add_to_bucket(n, *bucket);
+ ++this->size_;
+ if(bucket < this->cached_begin_bucket_)
+ this->cached_begin_bucket_ = bucket;
+ return n;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Insert methods
+
+ // if hash function throws, basic exception safety
+ // strong otherwise
+ template <class H, class P, class A, class K>
+ BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::value_type&
+ hash_unique_table<H, P, A, K>::operator[](key_type const& k)
+ {
+ typedef BOOST_DEDUCED_TYPENAME value_type::second_type mapped_type;
+
+ std::size_t hash_value = this->hash_function()(k);
+ bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
+
+ if(!this->buckets_) {
+ node_constructor a(*this);
+ a.construct_pair(k, (mapped_type*) 0);
+ return *this->emplace_empty_impl_with_node(a, 1);
+ }
+
+ node_ptr pos = find_iterator(bucket, k);
+
+ if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
+ return node::get_value(pos);
+ }
+ else {
+ // Side effects only in this block.
+
+ // 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);
+
+ // reserve has basic exception safety if the hash function
+ // throws, strong otherwise.
+ if(this->reserve_for_insert(this->size_ + 1))
+ bucket = this->bucket_ptr_from_hash(hash_value);
+
+ // Nothing after this point can throw.
+
+ return node::get_value(add_node(a, bucket));
+ }
+ }
+
+ template <class H, class P, class A, class K>
+ inline BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
+ hash_unique_table<H, P, A, K>
+ ::emplace_impl_with_node(node_constructor& a)
+ {
+ // No side effects in this initial code
+ key_type const& k = get_key(a.value());
+ std::size_t hash_value = this->hash_function()(k);
+ bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
+ node_ptr pos = find_iterator(bucket, k);
+
+ if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
+ // Found an existing key, return it (no throw).
+ return emplace_return(iterator_base(bucket, pos), false);
+ } else {
+ // reserve has basic exception safety if the hash function
+ // throws, strong otherwise.
+ if(this->reserve_for_insert(this->size_ + 1))
+ bucket = this->bucket_ptr_from_hash(hash_value);
+
+ // Nothing after this point can throw.
+
+ return emplace_return(
+ iterator_base(bucket, add_node(a, bucket)),
+ true);
+ }
+ }
+
+#if defined(BOOST_UNORDERED_STD_FORWARD)
+
+ template <class H, class P, class A, class K>
+ template<class... Args>
+ inline BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
+ hash_unique_table<H, P, A, K>::emplace_impl(key_type const& k,
+ Args&&... args)
+ {
+ // No side effects in this initial code
+ std::size_t hash_value = this->hash_function()(k);
+ bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
+ node_ptr pos = find_iterator(bucket, k);
+
+ if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
+ // Found an existing key, return it (no throw).
+ return emplace_return(iterator_base(bucket, pos), false);
+
+ } else {
+ // 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).
+ node_constructor a(*this);
+ a.construct(std::forward<Args>(args)...);
+
+ // reserve has basic exception safety if the hash function
+ // throws, strong otherwise.
+ if(this->reserve_for_insert(this->size_ + 1))
+ bucket = this->bucket_ptr_from_hash(hash_value);
+
+ // Nothing after this point can throw.
+
+ return emplace_return(
+ iterator_base(bucket, add_node(a, bucket)),
+ true);
+ }
+ }
+
+ template <class H, class P, class A, class K>
+ template<class... Args>
+ inline BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
+ hash_unique_table<H, P, A, K>::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);
+ }
+
+ template <class H, class P, class A, class K>
+ template<class... Args>
+ inline BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
+ hash_unique_table<H, P, A, K>::emplace_empty_impl(Args&&... args)
+ {
+ node_constructor a(*this);
+ a.construct(std::forward<Args>(args)...);
+ return emplace_return(this->emplace_empty_impl_with_node(a, 1), true);
+ }
+
+#else
+
+#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
+ template <class H, class P, class A, class K> \
+ template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
+ inline BOOST_DEDUCED_TYPENAME \
+ hash_unique_table<H, P, A, K>::emplace_return \
+ hash_unique_table<H, P, A, K>::emplace_impl( \
+ key_type const& k, \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
+ { \
+ std::size_t hash_value = this->hash_function()(k); \
+ bucket_ptr bucket \
+ = this->bucket_ptr_from_hash(hash_value); \
+ node_ptr pos = find_iterator(bucket, k); \
+ \
+ if (BOOST_UNORDERED_BORLAND_BOOL(pos)) { \
+ return emplace_return(iterator_base(bucket, pos), false); \
+ } else { \
+ node_constructor a(*this); \
+ a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
+ \
+ if(this->reserve_for_insert(this->size_ + 1)) \
+ bucket = this->bucket_ptr_from_hash(hash_value); \
+ \
+ return emplace_return(iterator_base(bucket, \
+ add_node(a, bucket)), true); \
+ } \
+ } \
+ \
+ template <class H, class P, class A, class K> \
+ template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
+ inline BOOST_DEDUCED_TYPENAME \
+ hash_unique_table<H, P, A, K>::emplace_return \
+ hash_unique_table<H, P, A, K>:: \
+ 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); \
+ } \
+ \
+ template <class H, class P, class A, class K> \
+ template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
+ inline BOOST_DEDUCED_TYPENAME \
+ hash_unique_table<H, P, A, K>::emplace_return \
+ hash_unique_table<H, P, A, K>:: \
+ emplace_empty_impl(BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
+ { \
+ node_constructor a(*this); \
+ a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
+ return emplace_return(this->emplace_empty_impl_with_node(a, 1), true); \
+ }
+
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
+ BOOST_UNORDERED_INSERT_IMPL, _)
+
+#undef BOOST_UNORDERED_INSERT_IMPL
+
+#endif
+
+#if defined(BOOST_UNORDERED_STD_FORWARD)
+
+ // Emplace (unique keys)
+ // (I'm using an overloaded emplace for both 'insert' and 'emplace')
+
+ // if hash function throws, basic exception safety
+ // strong otherwise
+
+ template <class H, class P, class A, class K>
+ template<class... Args>
+ BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
+ hash_unique_table<H, P, A, K>::emplace(Args&&... args)
+ {
+ return this->size_ ?
+ emplace_impl(
+ extractor::extract(std::forward<Args>(args)...),
+ std::forward<Args>(args)...) :
+ emplace_empty_impl(std::forward<Args>(args)...);
+ }
+
+ // Insert (unique keys)
+ // (I'm using an overloaded emplace for both 'insert' and 'emplace')
+ // I'm just ignoring hints here for now.
+
+ // if hash function throws, basic exception safety
+ // strong otherwise
+ template <class H, class P, class A, class K>
+ template<class... Args>
+ BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::iterator_base
+ hash_unique_table<H, P, A, K>::emplace_hint(iterator_base const&,
+ Args&&... args)
+ {
+ return this->size_ ?
+ emplace_impl(
+ extractor::extract(std::forward<Args>(args)...),
+ std::forward<Args>(args)...).first :
+ emplace_empty_impl(std::forward<Args>(args)...).first;
+ }
+
+#else
+
+ template <class H, class P, class A, class K>
+ template <class Arg0>
+ BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
+ hash_unique_table<H, P, A, K>::emplace(Arg0 const& arg0)
+ {
+ return this->size_ ?
+ emplace_impl(extractor::extract(arg0), arg0) :
+ emplace_empty_impl(arg0);
+ }
+
+ template <class H, class P, class A, class K>
+ template <class Arg0>
+ BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::iterator_base
+ hash_unique_table<H, P, A, K>::emplace_hint(iterator_base const&,
+ Arg0 const& arg0)
+ {
+ return this->size_ ?
+ emplace_impl(extractor::extract(arg0), arg0).first :
+ emplace_empty_impl(arg0).first;
+ }
+
+#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
+ template <class H, class P, class A, class K> \
+ template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
+ BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return \
+ hash_unique_table<H, P, A, K>::emplace( \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
+ { \
+ return this->size_ ? \
+ emplace_impl(extractor::extract(arg0, arg1), \
+ BOOST_UNORDERED_CALL_PARAMS(z, n)) : \
+ emplace_empty_impl( \
+ BOOST_UNORDERED_CALL_PARAMS(z, n)); \
+ } \
+ \
+ template <class H, class P, class A, class K> \
+ template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
+ BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::iterator_base \
+ hash_unique_table<H, P, A, K>:: \
+ emplace_hint(iterator_base const& it, \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
+ { \
+ return this->size_ ? \
+ emplace_impl(extractor::extract(arg0, arg1), \
+ BOOST_UNORDERED_CALL_PARAMS(z, n)) : \
+ emplace_empty_impl( \
+ BOOST_UNORDERED_CALL_PARAMS(z, n)); \
+ } \
+
+ BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT,
+ BOOST_UNORDERED_INSERT_IMPL, _)
+
+#undef BOOST_UNORDERED_INSERT_IMPL
+
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Insert range methods
+
+ template <class H, class P, class A, class K>
+ template <class InputIt>
+ inline void hash_unique_table<H, P, A, K>::insert_range_impl(
+ key_type const&, InputIt i, InputIt j)
+ {
+ node_constructor a(*this);
+
+ if(!this->size_) {
+ a.construct(*i);
+ this->emplace_empty_impl_with_node(a, 1);
+ ++i;
+ if(i == j) return;
+ }
+
+ do {
+ // No side effects in this initial code
+ // Note: can't use get_key as '*i' might not be value_type.
+ // TODO: Check if std::pair has an appropriate constructor. If not
+ // that might not be true.
+ // TODO: Test this line better.
+ key_type const& k = extractor::extract(*i);
+ std::size_t hash_value = this->hash_function()(k);
+ bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
+ node_ptr pos = find_iterator(bucket, 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 = this->bucket_ptr_from_hash(hash_value);
+ }
+
+ // Nothing after this point can throw.
+ add_node(a, bucket);
+ }
+ } while(++i != j);
+ }
+
+ template <class H, class P, class A, class K>
+ template <class InputIt>
+ inline void hash_unique_table<H, P, A, K>::insert_range_impl(
+ no_key, InputIt i, InputIt j)
+ {
+ node_constructor a(*this);
+
+ if(!this->size_) {
+ a.construct(*i);
+ this->emplace_empty_impl_with_node(a, 1);
+ ++i;
+ if(i == j) return;
+ }
+
+ do {
+ // No side effects in this initial code
+ a.construct(*i);
+ emplace_impl_with_node(a);
+ } while(++i != j);
+ }
+
+ // if hash function throws, or inserting > 1 element, basic exception safety
+ // strong otherwise
+ template <class H, class P, class A, class K>
+ template <class InputIt>
+ void hash_unique_table<H, P, A, K>::insert_range(InputIt i, InputIt j)
+ {
+ if(i != j)
+ return insert_range_impl(extractor::extract(*i), i, j);
+ }
+}}
+
+#endif

Modified: trunk/boost/unordered/detail/util.hpp
==============================================================================
--- trunk/boost/unordered/detail/util.hpp (original)
+++ trunk/boost/unordered/detail/util.hpp 2009-09-20 17:55:15 EDT (Sun, 20 Sep 2009)
@@ -14,22 +14,7 @@
 #include <boost/iterator/iterator_categories.hpp>
 #include <boost/preprocessor/seq/size.hpp>
 #include <boost/preprocessor/seq/enum.hpp>
-#include <boost/unordered/detail/buckets.hpp>
-
-#if !defined(BOOST_UNORDERED_STD_FORWARD)
-
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/repetition/enum_binary_params.hpp>
-#include <boost/preprocessor/repetition/repeat_from_to.hpp>
-
-#define BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- BOOST_PP_ENUM_PARAMS_Z(z, n, class Arg)
-#define BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, const& arg)
-#define BOOST_UNORDERED_CALL_PARAMS(z, n) \
- BOOST_PP_ENUM_PARAMS_Z(z, n, arg)
-
-#endif
+#include <boost/unordered/detail/fwd.hpp>
 
 namespace boost { namespace unordered_detail {
 
@@ -38,7 +23,8 @@
 
     inline std::size_t double_to_size_t(double f)
     {
- return f >= static_cast<double>((std::numeric_limits<std::size_t>::max)()) ?
+ return f >= static_cast<double>(
+ (std::numeric_limits<std::size_t>::max)()) ?
             (std::numeric_limits<std::size_t>::max)() :
             static_cast<std::size_t>(f);
     }
@@ -143,7 +129,7 @@
     
     template <class I>
     inline std::size_t initial_size(I i, I j,
- std::size_t n = boost::unordered_detail::default_initial_bucket_count)
+ std::size_t n = boost::unordered_detail::default_bucket_count)
     {
         return (std::max)(static_cast<std::size_t>(insert_size(i, j)) + 1, n);
     }
@@ -172,29 +158,29 @@
 
 #else
 
-#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, n, _) \
- template < \
- class T, \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- inline void construct_impl( \
- T*, void* address, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ) \
- { \
- new(address) T( \
- BOOST_UNORDERED_CALL_PARAMS(z, n)); \
- } \
- \
- template <class First, class Second, class Key, \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- inline void construct_impl( \
- std::pair<First, Second>*, void* address, \
- Key const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
- { \
- new(address) std::pair<First, Second>(k, \
- Second(BOOST_UNORDERED_CALL_PARAMS(z, n))); \
+#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, n, _) \
+ template < \
+ class T, \
+ BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
+ > \
+ inline void construct_impl( \
+ T*, void* address, \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
+ ) \
+ { \
+ new(address) T( \
+ BOOST_UNORDERED_CALL_PARAMS(z, n)); \
+ } \
+ \
+ template <class First, class Second, class Key, \
+ BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
+ > \
+ inline void construct_impl( \
+ std::pair<First, Second>*, void* address, \
+ Key const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
+ { \
+ new(address) std::pair<First, Second>(k, \
+ Second(BOOST_UNORDERED_CALL_PARAMS(z, n))); \
     }
 
     BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
@@ -244,20 +230,20 @@
         }
 #else
 
-#define BOOST_UNORDERED_CONSTRUCT(z, n, _) \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- void construct( \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ) \
- { \
- construct_preamble(); \
- construct_impl( \
- (value_type*) 0, node_->address(), \
- BOOST_UNORDERED_CALL_PARAMS(z, n) \
- ); \
- value_constructed_ = true; \
+#define BOOST_UNORDERED_CONSTRUCT(z, n, _) \
+ template < \
+ BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
+ > \
+ void construct( \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
+ ) \
+ { \
+ construct_preamble(); \
+ construct_impl( \
+ (value_type*) 0, node_->address(), \
+ BOOST_UNORDERED_CALL_PARAMS(z, n) \
+ ); \
+ value_constructed_ = true; \
         }
 
         BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
@@ -274,10 +260,10 @@
             value_constructed_ = true;
         }
 
- real_node_ptr get() const
+ value_type& value() const
         {
             BOOST_ASSERT(node_);
- return node_;
+ return node_->value();
         }
 
         // no throw
@@ -297,11 +283,11 @@
     // hash_node_constructor
 
     template <class Alloc, class Grouped>
- hash_node_constructor<Alloc, Grouped>::~hash_node_constructor()
+ inline hash_node_constructor<Alloc, Grouped>::~hash_node_constructor()
     {
         if (node_) {
             if (value_constructed_) {
- BOOST_UNORDERED_DESTRUCT(&node_->value(), value_type);
+ boost::unordered_detail::destroy(&node_->value());
             }
 
             if (node_constructed_)
@@ -312,7 +298,7 @@
     }
 
     template <class Alloc, class Grouped>
- void hash_node_constructor<Alloc, Grouped>::construct_preamble()
+ inline void hash_node_constructor<Alloc, Grouped>::construct_preamble()
     {
         if(!node_) {
             node_constructed_ = false;
@@ -324,7 +310,7 @@
         }
         else {
             BOOST_ASSERT(node_constructed_ && value_constructed_);
- BOOST_UNORDERED_DESTRUCT(&node_->value(), value_type);
+ boost::unordered_detail::destroy(&node_->value());
             value_constructed_ = false;
         }
     }

Modified: trunk/boost/unordered/unordered_map.hpp
==============================================================================
--- trunk/boost/unordered/unordered_map.hpp (original)
+++ trunk/boost/unordered/unordered_map.hpp 2009-09-20 17:55:15 EDT (Sun, 20 Sep 2009)
@@ -16,7 +16,8 @@
 #include <boost/unordered/unordered_map_fwd.hpp>
 #include <boost/functional/hash.hpp>
 #include <boost/unordered/detail/allocator_helpers.hpp>
-#include <boost/unordered/detail/insert.hpp>
+#include <boost/unordered/detail/equivalent.hpp>
+#include <boost/unordered/detail/unique.hpp>
 
 #if !defined(BOOST_HAS_RVALUE_REFS)
 #include <boost/unordered/detail/move.hpp>
@@ -53,32 +54,41 @@
 #endif
 
         typedef BOOST_DEDUCED_TYPENAME
- boost::unordered_detail::rebind_wrap<allocator_type, value_type>::type
+ boost::unordered_detail::rebind_wrap<
+ allocator_type, value_type>::type
             value_allocator;
 
- typedef boost::unordered_detail::hash_unique_table<Hash, Pred, value_allocator,
- boost::unordered_detail::map_extractor> table;
+ typedef boost::unordered_detail::hash_unique_table<Hash, Pred,
+ value_allocator, boost::unordered_detail::map_extractor> table;
 
         typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base;
 
     public:
 
- typedef BOOST_DEDUCED_TYPENAME value_allocator::pointer pointer;
- typedef BOOST_DEDUCED_TYPENAME value_allocator::const_pointer const_pointer;
- typedef BOOST_DEDUCED_TYPENAME value_allocator::reference reference;
- typedef BOOST_DEDUCED_TYPENAME value_allocator::const_reference const_reference;
+ typedef BOOST_DEDUCED_TYPENAME
+ value_allocator::pointer pointer;
+ typedef BOOST_DEDUCED_TYPENAME
+ value_allocator::const_pointer const_pointer;
+ typedef BOOST_DEDUCED_TYPENAME
+ value_allocator::reference reference;
+ typedef BOOST_DEDUCED_TYPENAME
+ value_allocator::const_reference const_reference;
 
         typedef std::size_t size_type;
         typedef std::ptrdiff_t difference_type;
 
         typedef boost::unordered_detail::hash_const_local_iterator<
- value_allocator, boost::unordered_detail::ungrouped> const_local_iterator;
+ value_allocator, boost::unordered_detail::ungrouped>
+ const_local_iterator;
         typedef boost::unordered_detail::hash_local_iterator<
- value_allocator, boost::unordered_detail::ungrouped> local_iterator;
+ value_allocator, boost::unordered_detail::ungrouped>
+ local_iterator;
         typedef boost::unordered_detail::hash_const_iterator<
- value_allocator, boost::unordered_detail::ungrouped> const_iterator;
+ value_allocator, boost::unordered_detail::ungrouped>
+ const_iterator;
         typedef boost::unordered_detail::hash_iterator<
- value_allocator, boost::unordered_detail::ungrouped> iterator;
+ value_allocator, boost::unordered_detail::ungrouped>
+ iterator;
 
 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
     private:
@@ -97,49 +107,51 @@
         // construct/destroy/copy
 
         explicit unordered_map(
- size_type n = boost::unordered_detail::default_initial_bucket_count,
+ size_type n = boost::unordered_detail::default_bucket_count,
                 const hasher &hf = hasher(),
                 const key_equal &eql = key_equal(),
                 const allocator_type &a = allocator_type())
- : table_(n, hf, eql, a)
+ : table_(n, hf, eql, a)
         {
         }
 
         explicit unordered_map(allocator_type const& a)
- : table_(boost::unordered_detail::default_initial_bucket_count,
+ : table_(boost::unordered_detail::default_bucket_count,
                 hasher(), key_equal(), a)
         {
         }
 
         unordered_map(unordered_map const& other, allocator_type const& a)
- : table_(other.table_, a)
+ : table_(other.table_, a)
         {
         }
 
- template <class InputIterator>
- unordered_map(InputIterator f, InputIterator l)
- : table_(boost::unordered_detail::initial_size(f, l), hasher(), key_equal(), allocator_type())
+ template <class InputIt>
+ unordered_map(InputIt f, InputIt l)
+ : table_(boost::unordered_detail::initial_size(f, l),
+ hasher(), key_equal(), allocator_type())
         {
             table_.insert_range(f, l);
         }
 
- template <class InputIterator>
- unordered_map(InputIterator f, InputIterator l,
+ template <class InputIt>
+ unordered_map(InputIt f, InputIt l,
                 size_type n,
                 const hasher &hf = hasher(),
                 const key_equal &eql = key_equal())
- : table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, allocator_type())
+ : table_(boost::unordered_detail::initial_size(f, l, n),
+ hf, eql, allocator_type())
         {
             table_.insert_range(f, l);
         }
 
- template <class InputIterator>
- unordered_map(InputIterator f, InputIterator l,
+ template <class InputIt>
+ unordered_map(InputIt f, InputIt l,
                 size_type n,
                 const hasher &hf,
                 const key_equal &eql,
                 const allocator_type &a)
- : table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, a)
+ : table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, a)
         {
             table_.insert_range(f, l);
         }
@@ -148,12 +160,12 @@
 
 #if defined(BOOST_HAS_RVALUE_REFS)
         unordered_map(unordered_map&& other)
- : table_(other.table_, boost::unordered_detail::move_tag())
+ : table_(other.table_, boost::unordered_detail::move_tag())
         {
         }
 
         unordered_map(unordered_map&& other, allocator_type const& a)
- : table_(other.table_, a, boost::unordered_detail::move_tag())
+ : table_(other.table_, a, boost::unordered_detail::move_tag())
         {
         }
 
@@ -163,8 +175,10 @@
             return *this;
         }
 #else
- unordered_map(boost::unordered_detail::move_from<unordered_map<Key, T, Hash, Pred, Alloc> > other)
- : table_(other.source.table_, boost::unordered_detail::move_tag())
+ unordered_map(boost::unordered_detail::move_from<
+ unordered_map<Key, T, Hash, Pred, Alloc>
+ > other)
+ : table_(other.source.table_, boost::unordered_detail::move_tag())
         {
         }
 
@@ -179,11 +193,13 @@
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
         unordered_map(std::initializer_list<value_type> list,
- size_type n = boost::unordered_detail::default_initial_bucket_count,
+ size_type n = boost::unordered_detail::default_bucket_count,
                 const hasher &hf = hasher(),
                 const key_equal &eql = key_equal(),
                 const allocator_type &a = allocator_type())
- : table_(boost::unordered_detail::initial_size(list.begin(), list.end(), n), hf, eql, allocator_type())
+ : table_(boost::unordered_detail::initial_size(
+ list.begin(), list.end(), n),
+ hf, eql, allocator_type())
         {
             table_.insert_range(list.begin(), list.end());
         }
@@ -263,7 +279,8 @@
         template <class... Args>
         iterator emplace_hint(const_iterator hint, Args&&... args)
         {
- return iterator(table_.emplace_hint(get(hint), std::forward<Args>(args)...));
+ return iterator(
+ table_.emplace_hint(get(hint), std::forward<Args>(args)...));
         }
 #else
 
@@ -273,35 +290,36 @@
                 table_.emplace(v));
         }
 
- iterator emplace_hint(const_iterator hint, value_type const& v = value_type())
+ iterator emplace_hint(const_iterator hint,
+ value_type const& v = value_type())
         {
             return iterator(table_.emplace_hint(get(hint), v));
         }
 
-#define BOOST_UNORDERED_EMPLACE(z, n, _) \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- std::pair<iterator, bool> emplace( \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ) \
- { \
- return boost::unordered_detail::pair_cast<iterator, bool>( \
- table_.emplace( \
- BOOST_UNORDERED_CALL_PARAMS(z, n) \
- )); \
- } \
- \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- iterator emplace_hint(const_iterator hint, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ) \
- { \
- return iterator(table_.emplace_hint(get(hint), \
- BOOST_UNORDERED_CALL_PARAMS(z, n) \
- )); \
+#define BOOST_UNORDERED_EMPLACE(z, n, _) \
+ template < \
+ BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
+ > \
+ std::pair<iterator, bool> emplace( \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
+ ) \
+ { \
+ return boost::unordered_detail::pair_cast<iterator, bool>( \
+ table_.emplace( \
+ BOOST_UNORDERED_CALL_PARAMS(z, n) \
+ )); \
+ } \
+ \
+ template < \
+ BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
+ > \
+ iterator emplace_hint(const_iterator hint, \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
+ ) \
+ { \
+ return iterator(table_.emplace_hint(get(hint), \
+ BOOST_UNORDERED_CALL_PARAMS(z, n) \
+ )); \
             }
 
         BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
@@ -322,8 +340,8 @@
             return iterator(table_.emplace_hint(get(hint), obj));
         }
 
- template <class InputIterator>
- void insert(InputIterator first, InputIterator last)
+ template <class InputIt>
+ void insert(InputIt first, InputIt last)
         {
             table_.insert_range(first, last);
         }
@@ -400,14 +418,16 @@
         std::pair<iterator, iterator>
             equal_range(const key_type& k)
         {
- return boost::unordered_detail::pair_cast<iterator, iterator>(
+ return boost::unordered_detail::pair_cast<
+ iterator, iterator>(
                     table_.equal_range(k));
         }
 
         std::pair<const_iterator, const_iterator>
             equal_range(const key_type& k) const
         {
- return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
+ return boost::unordered_detail::pair_cast<
+ const_iterator, const_iterator>(
                     table_.equal_range(k));
         }
 
@@ -415,7 +435,7 @@
 
         size_type bucket_count() const
         {
- return table_.bucket_count();
+ return table_.bucket_count_;
         }
 
         size_type max_bucket_count() const
@@ -443,14 +463,14 @@
             return const_local_iterator(table_.bucket_begin(n));
         }
 
- local_iterator end(size_type n)
+ local_iterator end(size_type)
         {
- return local_iterator(table_.bucket_end(n));
+ return local_iterator();
         }
 
- const_local_iterator end(size_type n) const
+ const_local_iterator end(size_type) const
         {
- return const_local_iterator(table_.bucket_end(n));
+ return const_local_iterator();
         }
 
         const_local_iterator cbegin(size_type n) const
@@ -458,9 +478,9 @@
             return const_local_iterator(table_.bucket_begin(n));
         }
 
- const_local_iterator cend(size_type n) const
+ const_local_iterator cend(size_type) const
         {
- return const_local_iterator(table_.bucket_end(n));
+ return const_local_iterator();
         }
 
         // hash policy
@@ -486,8 +506,10 @@
         }
         
 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
- friend bool operator==<Key, T, Hash, Pred, Alloc>(unordered_map const&, unordered_map const&);
- friend bool operator!=<Key, T, Hash, Pred, Alloc>(unordered_map const&, unordered_map const&);
+ friend bool operator==<Key, T, Hash, Pred, Alloc>(
+ unordered_map const&, unordered_map const&);
+ friend bool operator!=<Key, T, Hash, Pred, Alloc>(
+ unordered_map const&, unordered_map const&);
 #endif
     }; // class template unordered_map
 
@@ -528,31 +550,40 @@
     private:
 #endif
         typedef BOOST_DEDUCED_TYPENAME
- boost::unordered_detail::rebind_wrap<allocator_type, value_type>::type
+ boost::unordered_detail::rebind_wrap<
+ allocator_type, value_type>::type
             value_allocator;
 
- typedef boost::unordered_detail::hash_equivalent_table<Hash, Pred, value_allocator,
- boost::unordered_detail::map_extractor> table;
+ typedef boost::unordered_detail::hash_equivalent_table<Hash, Pred,
+ value_allocator, boost::unordered_detail::map_extractor> table;
         typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base;
 
     public:
 
- typedef BOOST_DEDUCED_TYPENAME value_allocator::pointer pointer;
- typedef BOOST_DEDUCED_TYPENAME value_allocator::const_pointer const_pointer;
- typedef BOOST_DEDUCED_TYPENAME value_allocator::reference reference;
- typedef BOOST_DEDUCED_TYPENAME value_allocator::const_reference const_reference;
+ typedef BOOST_DEDUCED_TYPENAME
+ value_allocator::pointer pointer;
+ typedef BOOST_DEDUCED_TYPENAME
+ value_allocator::const_pointer const_pointer;
+ typedef BOOST_DEDUCED_TYPENAME
+ value_allocator::reference reference;
+ typedef BOOST_DEDUCED_TYPENAME
+ value_allocator::const_reference const_reference;
 
         typedef std::size_t size_type;
         typedef std::ptrdiff_t difference_type;
 
         typedef boost::unordered_detail::hash_const_local_iterator<
- value_allocator, boost::unordered_detail::grouped> const_local_iterator;
+ value_allocator, boost::unordered_detail::grouped>
+ const_local_iterator;
         typedef boost::unordered_detail::hash_local_iterator<
- value_allocator, boost::unordered_detail::grouped> local_iterator;
+ value_allocator, boost::unordered_detail::grouped>
+ local_iterator;
         typedef boost::unordered_detail::hash_const_iterator<
- value_allocator, boost::unordered_detail::grouped> const_iterator;
+ value_allocator, boost::unordered_detail::grouped>
+ const_iterator;
         typedef boost::unordered_detail::hash_iterator<
- value_allocator, boost::unordered_detail::grouped> iterator;
+ value_allocator, boost::unordered_detail::grouped>
+ iterator;
 
 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
     private:
@@ -571,7 +602,7 @@
         // construct/destroy/copy
 
         explicit unordered_multimap(
- size_type n = boost::unordered_detail::default_initial_bucket_count,
+ size_type n = boost::unordered_detail::default_bucket_count,
                 const hasher &hf = hasher(),
                 const key_equal &eql = key_equal(),
                 const allocator_type &a = allocator_type())
@@ -580,35 +611,38 @@
         }
 
         explicit unordered_multimap(allocator_type const& a)
- : table_(boost::unordered_detail::default_initial_bucket_count,
+ : table_(boost::unordered_detail::default_bucket_count,
                 hasher(), key_equal(), a)
         {
         }
 
- unordered_multimap(unordered_multimap const& other, allocator_type const& a)
- : table_(other.table_, a)
+ unordered_multimap(unordered_multimap const& other,
+ allocator_type const& a)
+ : table_(other.table_, a)
         {
         }
 
- template <class InputIterator>
- unordered_multimap(InputIterator f, InputIterator l)
- : table_(boost::unordered_detail::initial_size(f, l), hasher(), key_equal(), allocator_type())
+ template <class InputIt>
+ unordered_multimap(InputIt f, InputIt l)
+ : table_(boost::unordered_detail::initial_size(f, l),
+ hasher(), key_equal(), allocator_type())
         {
             table_.insert_range(f, l);
         }
 
- template <class InputIterator>
- unordered_multimap(InputIterator f, InputIterator l,
+ template <class InputIt>
+ unordered_multimap(InputIt f, InputIt l,
                 size_type n,
                 const hasher &hf = hasher(),
                 const key_equal &eql = key_equal())
- : table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, allocator_type())
+ : table_(boost::unordered_detail::initial_size(f, l, n),
+ hf, eql, allocator_type())
         {
             table_.insert_range(f, l);
         }
 
- template <class InputIterator>
- unordered_multimap(InputIterator f, InputIterator l,
+ template <class InputIt>
+ unordered_multimap(InputIt f, InputIt l,
                 size_type n,
                 const hasher &hf,
                 const key_equal &eql,
@@ -622,12 +656,12 @@
 
 #if defined(BOOST_HAS_RVALUE_REFS)
         unordered_multimap(unordered_multimap&& other)
- : table_(other.table_, boost::unordered_detail::move_tag())
+ : table_(other.table_, boost::unordered_detail::move_tag())
         {
         }
 
         unordered_multimap(unordered_multimap&& other, allocator_type const& a)
- : table_(other.table_, a, boost::unordered_detail::move_tag())
+ : table_(other.table_, a, boost::unordered_detail::move_tag())
         {
         }
 
@@ -637,8 +671,10 @@
             return *this;
         }
 #else
- unordered_multimap(boost::unordered_detail::move_from<unordered_multimap<Key, T, Hash, Pred, Alloc> > other)
- : table_(other.source.table_, boost::unordered_detail::move_tag())
+ unordered_multimap(boost::unordered_detail::move_from<
+ unordered_multimap<Key, T, Hash, Pred, Alloc>
+ > other)
+ : table_(other.source.table_, boost::unordered_detail::move_tag())
         {
         }
 
@@ -653,11 +689,13 @@
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
         unordered_multimap(std::initializer_list<value_type> list,
- size_type n = boost::unordered_detail::default_initial_bucket_count,
+ size_type n = boost::unordered_detail::default_bucket_count,
                 const hasher &hf = hasher(),
                 const key_equal &eql = key_equal(),
                 const allocator_type &a = allocator_type())
- : table_(boost::unordered_detail::initial_size(list.begin(), list.end(), n), hf, eql, allocator_type())
+ : table_(boost::unordered_detail::initial_size(
+ list.begin(), list.end(), n),
+ hf, eql, allocator_type())
         {
             table_.insert_range(list.begin(), list.end());
         }
@@ -736,7 +774,8 @@
         template <class... Args>
         iterator emplace_hint(const_iterator hint, Args&&... args)
         {
- return iterator(table_.emplace_hint(get(hint), std::forward<Args>(args)...));
+ return iterator(table_.emplace_hint(get(hint),
+ std::forward<Args>(args)...));
         }
 #else
 
@@ -745,36 +784,37 @@
             return iterator(table_.emplace(v));
         }
         
- iterator emplace_hint(const_iterator hint, value_type const& v = value_type())
+ iterator emplace_hint(const_iterator hint,
+ value_type const& v = value_type())
         {
             return iterator(table_.emplace_hint(get(hint), v));
         }
 
 
-#define BOOST_UNORDERED_EMPLACE(z, n, _) \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- iterator emplace( \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ) \
- { \
- return iterator( \
- table_.emplace( \
- BOOST_UNORDERED_CALL_PARAMS(z, n) \
- )); \
- } \
- \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- iterator emplace_hint(const_iterator hint, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ) \
- { \
- return iterator(table_.emplace_hint(get(hint), \
- BOOST_UNORDERED_CALL_PARAMS(z, n) \
- )); \
+#define BOOST_UNORDERED_EMPLACE(z, n, _) \
+ template < \
+ BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
+ > \
+ iterator emplace( \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
+ ) \
+ { \
+ return iterator( \
+ table_.emplace( \
+ BOOST_UNORDERED_CALL_PARAMS(z, n) \
+ )); \
+ } \
+ \
+ template < \
+ BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
+ > \
+ iterator emplace_hint(const_iterator hint, \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
+ ) \
+ { \
+ return iterator(table_.emplace_hint(get(hint), \
+ BOOST_UNORDERED_CALL_PARAMS(z, n) \
+ )); \
             }
 
         BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
@@ -794,8 +834,8 @@
             return iterator(table_.emplace_hint(get(hint), obj));
         }
 
- template <class InputIterator>
- void insert(InputIterator first, InputIterator last)
+ template <class InputIt>
+ void insert(InputIt first, InputIt last)
         {
             table_.insert_range(first, last);
         }
@@ -857,14 +897,16 @@
         std::pair<iterator, iterator>
             equal_range(const key_type& k)
         {
- return boost::unordered_detail::pair_cast<iterator, iterator>(
+ return boost::unordered_detail::pair_cast<
+ iterator, iterator>(
                     table_.equal_range(k));
         }
 
         std::pair<const_iterator, const_iterator>
             equal_range(const key_type& k) const
         {
- return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
+ return boost::unordered_detail::pair_cast<
+ const_iterator, const_iterator>(
                     table_.equal_range(k));
         }
 
@@ -872,7 +914,7 @@
 
         size_type bucket_count() const
         {
- return table_.bucket_count();
+ return table_.bucket_count_;
         }
 
         size_type max_bucket_count() const
@@ -900,14 +942,14 @@
             return const_local_iterator(table_.bucket_begin(n));
         }
 
- local_iterator end(size_type n)
+ local_iterator end(size_type)
         {
- return local_iterator(table_.bucket_end(n));
+ return local_iterator();
         }
 
- const_local_iterator end(size_type n) const
+ const_local_iterator end(size_type) const
         {
- return const_local_iterator(table_.bucket_end(n));
+ return const_local_iterator();
         }
 
         const_local_iterator cbegin(size_type n) const
@@ -915,9 +957,9 @@
             return const_local_iterator(table_.bucket_begin(n));
         }
 
- const_local_iterator cend(size_type n) const
+ const_local_iterator cend(size_type) const
         {
- return const_local_iterator(table_.bucket_end(n));
+ return const_local_iterator();
         }
 
         // hash policy
@@ -943,8 +985,10 @@
         }
 
 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
- friend bool operator==<Key, T, Hash, Pred, Alloc>(unordered_multimap const&, unordered_multimap const&);
- friend bool operator!=<Key, T, Hash, Pred, Alloc>(unordered_multimap const&, unordered_multimap const&);
+ friend bool operator==<Key, T, Hash, Pred, Alloc>(
+ unordered_multimap const&, unordered_multimap const&);
+ friend bool operator!=<Key, T, Hash, Pred, Alloc>(
+ unordered_multimap const&, unordered_multimap const&);
 #endif
     }; // class template unordered_multimap
 

Modified: trunk/boost/unordered/unordered_set.hpp
==============================================================================
--- trunk/boost/unordered/unordered_set.hpp (original)
+++ trunk/boost/unordered/unordered_set.hpp 2009-09-20 17:55:15 EDT (Sun, 20 Sep 2009)
@@ -16,7 +16,8 @@
 #include <boost/unordered/unordered_set_fwd.hpp>
 #include <boost/functional/hash.hpp>
 #include <boost/unordered/detail/allocator_helpers.hpp>
-#include <boost/unordered/detail/insert.hpp>
+#include <boost/unordered/detail/equivalent.hpp>
+#include <boost/unordered/detail/unique.hpp>
 
 #if !defined(BOOST_HAS_RVALUE_REFS)
 #include <boost/unordered/detail/move.hpp>
@@ -53,27 +54,34 @@
 #endif
 
         typedef BOOST_DEDUCED_TYPENAME
- boost::unordered_detail::rebind_wrap<allocator_type, value_type>::type
+ boost::unordered_detail::rebind_wrap<
+ allocator_type, value_type>::type
             value_allocator;
 
- typedef boost::unordered_detail::hash_unique_table<Hash, Pred, value_allocator,
- boost::unordered_detail::set_extractor> table;
+ typedef boost::unordered_detail::hash_unique_table<Hash, Pred,
+ value_allocator, boost::unordered_detail::set_extractor> table;
         typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base;
 
     public:
 
- typedef BOOST_DEDUCED_TYPENAME value_allocator::pointer pointer;
- typedef BOOST_DEDUCED_TYPENAME value_allocator::const_pointer const_pointer;
- typedef BOOST_DEDUCED_TYPENAME value_allocator::reference reference;
- typedef BOOST_DEDUCED_TYPENAME value_allocator::const_reference const_reference;
+ typedef BOOST_DEDUCED_TYPENAME
+ value_allocator::pointer pointer;
+ typedef BOOST_DEDUCED_TYPENAME
+ value_allocator::const_pointer const_pointer;
+ typedef BOOST_DEDUCED_TYPENAME
+ value_allocator::reference reference;
+ typedef BOOST_DEDUCED_TYPENAME
+ value_allocator::const_reference const_reference;
 
         typedef std::size_t size_type;
         typedef std::ptrdiff_t difference_type;
 
         typedef boost::unordered_detail::hash_const_local_iterator<
- value_allocator, boost::unordered_detail::ungrouped> const_local_iterator;
+ value_allocator, boost::unordered_detail::ungrouped>
+ const_local_iterator;
         typedef boost::unordered_detail::hash_const_iterator<
- value_allocator, boost::unordered_detail::ungrouped> const_iterator;
+ value_allocator, boost::unordered_detail::ungrouped>
+ const_iterator;
         typedef const_local_iterator local_iterator;
         typedef const_iterator iterator;
 
@@ -94,47 +102,49 @@
         // construct/destroy/copy
 
         explicit unordered_set(
- size_type n = boost::unordered_detail::default_initial_bucket_count,
+ size_type n = boost::unordered_detail::default_bucket_count,
                 const hasher &hf = hasher(),
                 const key_equal &eql = key_equal(),
                 const allocator_type &a = allocator_type())
- : table_(n, hf, eql, a)
+ : table_(n, hf, eql, a)
         {
         }
 
         explicit unordered_set(allocator_type const& a)
- : table_(boost::unordered_detail::default_initial_bucket_count,
+ : table_(boost::unordered_detail::default_bucket_count,
                 hasher(), key_equal(), a)
         {
         }
 
         unordered_set(unordered_set const& other, allocator_type const& a)
- : table_(other.table_, a)
+ : table_(other.table_, a)
         {
         }
 
- template <class InputIterator>
- unordered_set(InputIterator f, InputIterator l)
- : table_(boost::unordered_detail::initial_size(f, l), hasher(), key_equal(), allocator_type())
+ template <class InputIt>
+ unordered_set(InputIt f, InputIt l)
+ : table_(boost::unordered_detail::initial_size(f, l),
+ hasher(), key_equal(), allocator_type())
         {
             table_.insert_range(f, l);
         }
 
- template <class InputIterator>
- unordered_set(InputIterator f, InputIterator l, size_type n,
+ template <class InputIt>
+ unordered_set(InputIt f, InputIt l, size_type n,
                 const hasher &hf = hasher(),
                 const key_equal &eql = key_equal())
- : table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, allocator_type())
+ : table_(boost::unordered_detail::initial_size(f, l, n),
+ hf, eql, allocator_type())
         {
             table_.insert_range(f, l);
         }
         
- template <class InputIterator>
- unordered_set(InputIterator f, InputIterator l, size_type n,
+ template <class InputIt>
+ unordered_set(InputIt f, InputIt l, size_type n,
                 const hasher &hf,
                 const key_equal &eql,
                 const allocator_type &a)
- : table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, a)
+ : table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, a)
         {
             table_.insert_range(f, l);
         }
@@ -143,12 +153,12 @@
 
 #if defined(BOOST_HAS_RVALUE_REFS)
         unordered_set(unordered_set&& other)
- : table_(other.table_, boost::unordered_detail::move_tag())
+ : table_(other.table_, boost::unordered_detail::move_tag())
         {
         }
 
         unordered_set(unordered_set&& other, allocator_type const& a)
- : table_(other.table_, a, boost::unordered_detail::move_tag())
+ : table_(other.table_, a, boost::unordered_detail::move_tag())
         {
         }
 
@@ -158,8 +168,10 @@
             return *this;
         }
 #else
- unordered_set(boost::unordered_detail::move_from<unordered_set<Value, Hash, Pred, Alloc> > other)
- : table_(other.source.table_, boost::unordered_detail::move_tag())
+ unordered_set(boost::unordered_detail::move_from<
+ unordered_set<Value, Hash, Pred, Alloc>
+ > other)
+ : table_(other.source.table_, boost::unordered_detail::move_tag())
         {
         }
 
@@ -174,11 +186,13 @@
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
         unordered_set(std::initializer_list<value_type> list,
- size_type n = boost::unordered_detail::default_initial_bucket_count,
+ size_type n = boost::unordered_detail::default_bucket_count,
                 const hasher &hf = hasher(),
                 const key_equal &eql = key_equal(),
                 const allocator_type &a = allocator_type())
- : table_(boost::unordered_detail::initial_size(list.begin(), list.end(), n), hf, eql, allocator_type())
+ : table_(boost::unordered_detail::initial_size(
+ list.begin(), list.end(), n),
+ hf, eql, allocator_type())
         {
             table_.insert_range(list.begin(), list.end());
         }
@@ -269,35 +283,36 @@
                 table_.emplace(v));
         }
 
- iterator emplace_hint(const_iterator hint, value_type const& v = value_type())
+ iterator emplace_hint(const_iterator hint,
+ value_type const& v = value_type())
         {
             return iterator(table_.emplace_hint(get(hint), v));
         }
 
-#define BOOST_UNORDERED_EMPLACE(z, n, _) \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- std::pair<iterator, bool> emplace( \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ) \
- { \
- return boost::unordered_detail::pair_cast<iterator, bool>( \
- table_.emplace( \
- BOOST_UNORDERED_CALL_PARAMS(z, n) \
- )); \
- } \
- \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- iterator emplace_hint(const_iterator hint, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ) \
- { \
- return iterator(table_.emplace_hint(get(hint), \
- BOOST_UNORDERED_CALL_PARAMS(z, n) \
- )); \
+#define BOOST_UNORDERED_EMPLACE(z, n, _) \
+ template < \
+ BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
+ > \
+ std::pair<iterator, bool> emplace( \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
+ ) \
+ { \
+ return boost::unordered_detail::pair_cast<iterator, bool>( \
+ table_.emplace( \
+ BOOST_UNORDERED_CALL_PARAMS(z, n) \
+ )); \
+ } \
+ \
+ template < \
+ BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
+ > \
+ iterator emplace_hint(const_iterator hint, \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
+ ) \
+ { \
+ return iterator(table_.emplace_hint(get(hint), \
+ BOOST_UNORDERED_CALL_PARAMS(z, n) \
+ )); \
             }
 
         BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
@@ -318,8 +333,8 @@
             return iterator(table_.emplace_hint(get(hint), obj));
         }
 
- template <class InputIterator>
- void insert(InputIterator first, InputIterator last)
+ template <class InputIt>
+ void insert(InputIt first, InputIt last)
         {
             table_.insert_range(first, last);
         }
@@ -376,7 +391,8 @@
         std::pair<const_iterator, const_iterator>
             equal_range(const key_type& k) const
         {
- return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
+ return boost::unordered_detail::pair_cast<
+ const_iterator, const_iterator>(
                     table_.equal_range(k));
         }
 
@@ -384,7 +400,7 @@
 
         size_type bucket_count() const
         {
- return table_.bucket_count();
+ return table_.bucket_count_;
         }
 
         size_type max_bucket_count() const
@@ -412,14 +428,14 @@
             return const_local_iterator(table_.bucket_begin(n));
         }
 
- local_iterator end(size_type n)
+ local_iterator end(size_type)
         {
- return local_iterator(table_.bucket_end(n));
+ return local_iterator();
         }
 
- const_local_iterator end(size_type n) const
+ const_local_iterator end(size_type) const
         {
- return const_local_iterator(table_.bucket_end(n));
+ return const_local_iterator();
         }
 
         const_local_iterator cbegin(size_type n) const
@@ -427,9 +443,9 @@
             return const_local_iterator(table_.bucket_begin(n));
         }
 
- const_local_iterator cend(size_type n) const
+ const_local_iterator cend(size_type) const
         {
- return const_local_iterator(table_.bucket_end(n));
+ return const_local_iterator();
         }
 
         // hash policy
@@ -455,8 +471,10 @@
         }
 
 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
- friend bool operator==<Value, Hash, Pred, Alloc>(unordered_set const&, unordered_set const&);
- friend bool operator!=<Value, Hash, Pred, Alloc>(unordered_set const&, unordered_set const&);
+ friend bool operator==<Value, Hash, Pred, Alloc>(
+ unordered_set const&, unordered_set const&);
+ friend bool operator!=<Value, Hash, Pred, Alloc>(
+ unordered_set const&, unordered_set const&);
 #endif
     }; // class template unordered_set
 
@@ -496,27 +514,34 @@
     private:
 #endif
         typedef BOOST_DEDUCED_TYPENAME
- boost::unordered_detail::rebind_wrap<allocator_type, value_type>::type
+ boost::unordered_detail::rebind_wrap<
+ allocator_type, value_type>::type
             value_allocator;
 
- typedef boost::unordered_detail::hash_equivalent_table<Hash, Pred, value_allocator,
- boost::unordered_detail::set_extractor> table;
+ typedef boost::unordered_detail::hash_equivalent_table<Hash, Pred,
+ value_allocator, boost::unordered_detail::set_extractor> table;
         typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base;
 
     public:
 
- typedef BOOST_DEDUCED_TYPENAME value_allocator::pointer pointer;
- typedef BOOST_DEDUCED_TYPENAME value_allocator::const_pointer const_pointer;
- typedef BOOST_DEDUCED_TYPENAME value_allocator::reference reference;
- typedef BOOST_DEDUCED_TYPENAME value_allocator::const_reference const_reference;
+ typedef BOOST_DEDUCED_TYPENAME
+ value_allocator::pointer pointer;
+ typedef BOOST_DEDUCED_TYPENAME
+ value_allocator::const_pointer const_pointer;
+ typedef BOOST_DEDUCED_TYPENAME
+ value_allocator::reference reference;
+ typedef BOOST_DEDUCED_TYPENAME
+ value_allocator::const_reference const_reference;
 
         typedef std::size_t size_type;
         typedef std::ptrdiff_t difference_type;
 
         typedef boost::unordered_detail::hash_const_local_iterator<
- value_allocator, boost::unordered_detail::grouped> const_local_iterator;
+ value_allocator, boost::unordered_detail::grouped>
+ const_local_iterator;
         typedef boost::unordered_detail::hash_const_iterator<
- value_allocator, boost::unordered_detail::grouped> const_iterator;
+ value_allocator, boost::unordered_detail::grouped>
+ const_iterator;
         typedef const_local_iterator local_iterator;
         typedef const_iterator iterator;
 
@@ -537,7 +562,7 @@
         // construct/destroy/copy
 
         explicit unordered_multiset(
- size_type n = boost::unordered_detail::default_initial_bucket_count,
+ size_type n = boost::unordered_detail::default_bucket_count,
                 const hasher &hf = hasher(),
                 const key_equal &eql = key_equal(),
                 const allocator_type &a = allocator_type())
@@ -546,34 +571,37 @@
         }
 
         explicit unordered_multiset(allocator_type const& a)
- : table_(boost::unordered_detail::default_initial_bucket_count,
+ : table_(boost::unordered_detail::default_bucket_count,
                 hasher(), key_equal(), a)
         {
         }
 
- unordered_multiset(unordered_multiset const& other, allocator_type const& a)
- : table_(other.table_, a)
+ unordered_multiset(unordered_multiset const& other,
+ allocator_type const& a)
+ : table_(other.table_, a)
         {
         }
 
- template <class InputIterator>
- unordered_multiset(InputIterator f, InputIterator l)
- : table_(boost::unordered_detail::initial_size(f, l), hasher(), key_equal(), allocator_type())
+ template <class InputIt>
+ unordered_multiset(InputIt f, InputIt l)
+ : table_(boost::unordered_detail::initial_size(f, l),
+ hasher(), key_equal(), allocator_type())
         {
             table_.insert_range(f, l);
         }
 
- template <class InputIterator>
- unordered_multiset(InputIterator f, InputIterator l, size_type n,
+ template <class InputIt>
+ unordered_multiset(InputIt f, InputIt l, size_type n,
                 const hasher &hf = hasher(),
                 const key_equal &eql = key_equal())
- : table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, allocator_type())
+ : table_(boost::unordered_detail::initial_size(f, l, n),
+ hf, eql, allocator_type())
         {
             table_.insert_range(f, l);
         }
 
- template <class InputIterator>
- unordered_multiset(InputIterator f, InputIterator l, size_type n,
+ template <class InputIt>
+ unordered_multiset(InputIt f, InputIt l, size_type n,
                 const hasher &hf,
                 const key_equal &eql,
                 const allocator_type &a)
@@ -586,12 +614,12 @@
 
 #if defined(BOOST_HAS_RVALUE_REFS)
         unordered_multiset(unordered_multiset&& other)
- : table_(other.table_, boost::unordered_detail::move_tag())
+ : table_(other.table_, boost::unordered_detail::move_tag())
         {
         }
 
         unordered_multiset(unordered_multiset&& other, allocator_type const& a)
- : table_(other.table_, a, boost::unordered_detail::move_tag())
+ : table_(other.table_, a, boost::unordered_detail::move_tag())
         {
         }
 
@@ -601,8 +629,10 @@
             return *this;
         }
 #else
- unordered_multiset(boost::unordered_detail::move_from<unordered_multiset<Value, Hash, Pred, Alloc> > other)
- : table_(other.source.table_, boost::unordered_detail::move_tag())
+ unordered_multiset(boost::unordered_detail::move_from<
+ unordered_multiset<Value, Hash, Pred, Alloc>
+ > other)
+ : table_(other.source.table_, boost::unordered_detail::move_tag())
         {
         }
 
@@ -617,11 +647,13 @@
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
         unordered_multiset(std::initializer_list<value_type> list,
- size_type n = boost::unordered_detail::default_initial_bucket_count,
+ size_type n = boost::unordered_detail::default_bucket_count,
                 const hasher &hf = hasher(),
                 const key_equal &eql = key_equal(),
                 const allocator_type &a = allocator_type())
- : table_(boost::unordered_detail::initial_size(list.begin(), list.end(), n), hf, eql, allocator_type())
+ : table_(boost::unordered_detail::initial_size(
+ list.begin(), list.end(), n),
+ hf, eql, allocator_type())
         {
             table_.insert_range(list.begin(), list.end());
         }
@@ -700,7 +732,8 @@
         template <class... Args>
         iterator emplace_hint(const_iterator hint, Args&&... args)
         {
- return iterator(table_.emplace_hint(get(hint), std::forward<Args>(args)...));
+ return iterator(table_.emplace_hint(get(hint),
+ std::forward<Args>(args)...));
         }
 #else
 
@@ -709,33 +742,34 @@
             return iterator(table_.emplace(v));
         }
 
- iterator emplace_hint(const_iterator hint, value_type const& v = value_type())
+ iterator emplace_hint(const_iterator hint,
+ value_type const& v = value_type())
         {
             return iterator(table_.emplace_hint(get(hint), v));
         }
 
-#define BOOST_UNORDERED_EMPLACE(z, n, _) \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- iterator emplace( \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ) \
- { \
- return iterator( \
- table_.emplace(BOOST_UNORDERED_CALL_PARAMS(z, n))); \
- } \
- \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- iterator emplace_hint(const_iterator hint, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ) \
- { \
- return iterator(table_.emplace_hint(get(hint), \
- BOOST_UNORDERED_CALL_PARAMS(z, n) \
- )); \
+#define BOOST_UNORDERED_EMPLACE(z, n, _) \
+ template < \
+ BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
+ > \
+ iterator emplace( \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
+ ) \
+ { \
+ return iterator( \
+ table_.emplace(BOOST_UNORDERED_CALL_PARAMS(z, n))); \
+ } \
+ \
+ template < \
+ BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
+ > \
+ iterator emplace_hint(const_iterator hint, \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
+ ) \
+ { \
+ return iterator(table_.emplace_hint(get(hint), \
+ BOOST_UNORDERED_CALL_PARAMS(z, n) \
+ )); \
             }
 
         BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
@@ -755,8 +789,8 @@
             return iterator(table_.emplace_hint(get(hint), obj));
         }
 
- template <class InputIterator>
- void insert(InputIterator first, InputIterator last)
+ template <class InputIt>
+ void insert(InputIt first, InputIt last)
         {
             table_.insert_range(first, last);
         }
@@ -813,7 +847,8 @@
         std::pair<const_iterator, const_iterator>
             equal_range(const key_type& k) const
         {
- return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
+ return boost::unordered_detail::pair_cast<
+ const_iterator, const_iterator>(
                     table_.equal_range(k));
         }
 
@@ -821,7 +856,7 @@
 
         size_type bucket_count() const
         {
- return table_.bucket_count();
+ return table_.bucket_count_;
         }
 
         size_type max_bucket_count() const
@@ -849,14 +884,14 @@
             return const_local_iterator(table_.bucket_begin(n));
         }
 
- local_iterator end(size_type n)
+ local_iterator end(size_type)
         {
- return local_iterator(table_.bucket_end(n));
+ return local_iterator();
         }
 
- const_local_iterator end(size_type n) const
+ const_local_iterator end(size_type) const
         {
- return const_local_iterator(table_.bucket_end(n));
+ return const_local_iterator();
         }
 
         const_local_iterator cbegin(size_type n) const
@@ -864,9 +899,9 @@
             return const_local_iterator(table_.bucket_begin(n));
         }
 
- const_local_iterator cend(size_type n) const
+ const_local_iterator cend(size_type) const
         {
- return const_local_iterator(table_.bucket_end(n));
+ return const_local_iterator();
         }
 
         // hash policy
@@ -892,8 +927,10 @@
         }
 
 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
- friend bool operator==<Value, Hash, Pred, Alloc>(unordered_multiset const&, unordered_multiset const&);
- friend bool operator!=<Value, Hash, Pred, Alloc>(unordered_multiset const&, unordered_multiset const&);
+ friend bool operator==<Value, Hash, Pred, Alloc>(
+ unordered_multiset const&, unordered_multiset const&);
+ friend bool operator!=<Value, Hash, Pred, Alloc>(
+ unordered_multiset const&, unordered_multiset const&);
 #endif
     }; // class template unordered_multiset
 

Modified: trunk/libs/unordered/test/helpers/list.hpp
==============================================================================
--- trunk/libs/unordered/test/helpers/list.hpp (original)
+++ trunk/libs/unordered/test/helpers/list.hpp 2009-09-20 17:55:15 EDT (Sun, 20 Sep 2009)
@@ -21,14 +21,17 @@
 
     namespace test_detail
     {
- template <typename T> struct list_node;
+ template <typename T> class list_node;
         template <typename T> class list_data;
         template <typename T> class list_iterator;
         template <typename T> class list_const_iterator;
 
         template <typename T>
- struct list_node
+ class list_node
         {
+ list_node(list_node const&);
+ list_node& operator=(list_node const&);
+ public:
             T value_;
             list_node* next_;
                     
@@ -243,8 +246,8 @@
         node** merge_adjacent_ranges(node** first, node** second,
                 node** third, Less less)
         {
- while(true) {
- while(true) {
+ for(;;) {
+ for(;;) {
                     if(first == second) return third;
                     if(less((*second)->value_, (*first)->value_)) break;
                     first = &(*first)->next_;
@@ -256,7 +259,7 @@
                 // Since the two ranges we just swapped, the order is now:
                 // first...third...second
                 
- while(true) {
+ for(;;) {
                     if(first == third) return second;
                     if(!less((*first)->value_, (*third)->value_)) break;
                     first = &(*first)->next_;

Modified: trunk/libs/unordered/test/unordered/erase_equiv_tests.cpp
==============================================================================
--- trunk/libs/unordered/test/unordered/erase_equiv_tests.cpp (original)
+++ trunk/libs/unordered/test/unordered/erase_equiv_tests.cpp 2009-09-20 17:55:15 EDT (Sun, 20 Sep 2009)
@@ -116,7 +116,7 @@
 }
 
 template <class Container>
-bool general_erase_range_test(Container& x, int start, int end)
+bool general_erase_range_test(Container& x, std::size_t start, std::size_t end)
 {
     collide_list l(x.begin(), x.end());
     l.erase(boost::next(l.begin(), start), boost::next(l.begin(), end));

Modified: trunk/libs/unordered/test/unordered/out_of_line.cpp
==============================================================================
--- trunk/libs/unordered/test/unordered/out_of_line.cpp (original)
+++ trunk/libs/unordered/test/unordered/out_of_line.cpp 2009-09-20 17:55:15 EDT (Sun, 20 Sep 2009)
@@ -10,7 +10,7 @@
 
 template <class T>
 template <class U>
-bool foo<T>::bar(U x) { return x; }
+bool foo<T>::bar(U x) { return x ? true : false; }
 
 int main() {
     foo<int> x;


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk