$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r73987 - in branches/release: boost/unordered boost/unordered/detail libs/unordered libs/unordered/doc libs/unordered/test/exception libs/unordered/test/helpers libs/unordered/test/objects libs/unordered/test/unordered
From: dnljms_at_[hidden]
Date: 2011-08-21 15:19:16
Author: danieljames
Date: 2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
New Revision: 73987
URL: http://svn.boost.org/trac/boost/changeset/73987
Log:
Unordered: Merge to release.
Using Boost.Move and better C++11 support.
Added:
   branches/release/boost/unordered/detail/fwd.hpp
      - copied, changed from r72401, /trunk/boost/unordered/detail/fwd.hpp
   branches/release/libs/unordered/doc/compliance.qbk
      - copied unchanged from r73985, /trunk/libs/unordered/doc/compliance.qbk
   branches/release/libs/unordered/doc/ref.php
      - copied, changed from r73582, /trunk/libs/unordered/doc/ref.php
   branches/release/libs/unordered/test/objects/cxx11_allocator.hpp
      - copied unchanged from r73985, /trunk/libs/unordered/test/objects/cxx11_allocator.hpp
Removed:
   branches/release/boost/unordered/detail/move.hpp
Properties modified: 
   branches/release/boost/unordered/   (props changed)
   branches/release/libs/unordered/   (props changed)
Text files modified: 
   branches/release/boost/unordered/detail/allocator_helpers.hpp             |   273 +++++                                   
   branches/release/boost/unordered/detail/buckets.hpp                       |   877 +++++++++++++++++--                     
   branches/release/boost/unordered/detail/equivalent.hpp                    |   463 +++++-----                              
   branches/release/boost/unordered/detail/extract_key.hpp                   |    31                                         
   branches/release/boost/unordered/detail/fwd.hpp                           |    37                                         
   branches/release/boost/unordered/detail/node.hpp                          |   470 +++++++---                              
   branches/release/boost/unordered/detail/table.hpp                         |  1282 ++++++++++++++---------------           
   branches/release/boost/unordered/detail/unique.hpp                        |   728 +++++++---------                        
   branches/release/boost/unordered/detail/util.hpp                          |   358 ++++---                                 
   branches/release/boost/unordered/unordered_map.hpp                        |  1730 +++++++++++++++++++++++++-------------- 
   branches/release/boost/unordered/unordered_map_fwd.hpp                    |    66                                         
   branches/release/boost/unordered/unordered_set.hpp                        |  1523 ++++++++++++++++++++++------------      
   branches/release/boost/unordered/unordered_set_fwd.hpp                    |    64                                         
   branches/release/libs/unordered/doc/changes.qbk                           |    17                                         
   branches/release/libs/unordered/doc/rationale.qbk                         |     2                                         
   branches/release/libs/unordered/doc/ref.php                               |     1                                         
   branches/release/libs/unordered/doc/ref.xml                               |   128 +-                                      
   branches/release/libs/unordered/doc/unordered.qbk                         |     1                                         
   branches/release/libs/unordered/test/exception/swap_exception_tests.cpp   |    14                                         
   branches/release/libs/unordered/test/helpers/count.hpp                    |     7                                         
   branches/release/libs/unordered/test/helpers/invariants.hpp               |    49                                         
   branches/release/libs/unordered/test/helpers/memory.hpp                   |    37                                         
   branches/release/libs/unordered/test/objects/exception.hpp                |    22                                         
   branches/release/libs/unordered/test/objects/minimal.hpp                  |   144 ++                                      
   branches/release/libs/unordered/test/objects/test.hpp                     |    31                                         
   branches/release/libs/unordered/test/unordered/Jamfile.v2                 |     2                                         
   branches/release/libs/unordered/test/unordered/assign_tests.cpp           |    87 +                                       
   branches/release/libs/unordered/test/unordered/bucket_tests.cpp           |     2                                         
   branches/release/libs/unordered/test/unordered/compile_map.cpp            |   100 +                                       
   branches/release/libs/unordered/test/unordered/compile_set.cpp            |   192 +++                                     
   branches/release/libs/unordered/test/unordered/compile_tests.hpp          |   203 +++                                     
   branches/release/libs/unordered/test/unordered/constructor_tests.cpp      |    43                                         
   branches/release/libs/unordered/test/unordered/copy_tests.cpp             |    81 +                                       
   branches/release/libs/unordered/test/unordered/equality_tests.cpp         |     8                                         
   branches/release/libs/unordered/test/unordered/erase_tests.cpp            |    14                                         
   branches/release/libs/unordered/test/unordered/find_tests.cpp             |     4                                         
   branches/release/libs/unordered/test/unordered/insert_tests.cpp           |    23                                         
   branches/release/libs/unordered/test/unordered/move_tests.cpp             |   139 +++                                     
   branches/release/libs/unordered/test/unordered/swap_tests.cpp             |   137 ++                                      
   branches/release/libs/unordered/test/unordered/unnecessary_copy_tests.cpp |   139 ++                                      
   40 files changed, 6142 insertions(+), 3387 deletions(-)
Modified: branches/release/boost/unordered/detail/allocator_helpers.hpp
==============================================================================
--- branches/release/boost/unordered/detail/allocator_helpers.hpp	(original)
+++ branches/release/boost/unordered/detail/allocator_helpers.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -1,9 +1,12 @@
 
-// Copyright 2005-2009 Daniel James.
+// Copyright 2005-2011 Daniel James.
+// Copyright 2009 Pablo Halpern.
+//
 // 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)
-
-// A couple of templates to make using allocators easier.
+//
+// Written by Daniel James using some code from Pablo Halpern's
+// allocator traits implementation.
 
 #ifndef BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
 #define BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
@@ -13,6 +16,8 @@
 #endif
 
 #include <boost/config.hpp>
+#include <boost/detail/select_type.hpp>
+#include <boost/utility/enable_if.hpp>
 
 #if (defined(BOOST_NO_STD_ALLOCATOR) || defined(BOOST_DINKUMWARE_STDLIB)) \
     && !defined(__BORLANDC__)
@@ -23,24 +28,257 @@
 #  include <boost/detail/allocator_utilities.hpp>
 #endif
 
-namespace boost { namespace unordered_detail {
+#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
+#  include <memory>
+#endif
+
+#if !defined(BOOST_NO_0X_HDR_TYPE_TRAITS)
+#include <type_traits>
+namespace boost { namespace unordered { namespace detail {
+    using std::integral_constant;
+    using std::true_type;
+    using std::false_type;
+}}}
+#else
+namespace boost { namespace unordered { namespace detail {
+    template <typename T, T Value>
+    struct integral_constant { enum { value = Value }; };
+    typedef integral_constant<bool, true> true_type;
+    typedef integral_constant<bool, false> false_type;
+}}}
+#endif
+
+// TODO: Use std::addressof if available?
+#include <boost/utility/addressof.hpp>
 
+namespace boost { namespace unordered { namespace detail {
+
+#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
+    template <typename Alloc>
+    struct allocator_traits : std::allocator_traits<Alloc> {};
+    
+    template <typename Alloc, typename T>
+    struct rebind_wrap
+    {
+        typedef typename allocator_traits<Alloc>::rebind_alloc<T> type;
+    };
+#else
     // rebind_wrap
     //
     // Rebind allocators. For some problematic libraries, use rebind_to
     // from <boost/detail/allocator_utilities.hpp>.
 
-#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
-    template <class Alloc, class T>
+#   if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
+    template <typename Alloc, typename T>
     struct rebind_wrap : ::boost::detail::allocator::rebind_to<Alloc, T> {};
-#else
-    template <class Alloc, class T>
+#   else
+    template <typename Alloc, typename T>
     struct rebind_wrap
     {
         typedef BOOST_DEDUCED_TYPENAME
             Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
             type;
     };
+#   endif
+
+    struct convertible_from_anything
+    {
+        template<typename T> convertible_from_anything(T const&);
+    };
+
+    typedef char (&no_type)[1];
+    typedef char (&yes_type)[2];
+
+    template <typename T> struct sfinae {
+        typedef yes_type type;
+    };
+
+    // Infrastructure for providing a default type for Tp::tname if absent.
+    #define BOOST_DEFAULT_TYPE_TMPLT(tname)                                 \
+        template <typename Tp, typename Default>                            \
+        struct default_type_ ## tname {                                     \
+            template <typename T>                                           \
+            static BOOST_DEDUCED_TYPENAME sfinae<                           \
+                BOOST_DEDUCED_TYPENAME T::tname>::type test(int);           \
+            template <typename T>                                           \
+            static no_type test(long);                                      \
+                                                                            \
+            enum { value = sizeof(test<Tp>(0)) == sizeof(yes_type) };       \
+                                                                            \
+            struct DefaultWrap { typedef Default tname; };                  \
+                                                                            \
+            typedef BOOST_DEDUCED_TYPENAME                                  \
+                boost::detail::if_true<value>::                             \
+                BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap>                 \
+                ::type::tname type;                                         \
+        }
+    
+    #define BOOST_DEFAULT_TYPE(T,tname, arg)                                \
+        BOOST_DEDUCED_TYPENAME default_type_ ## tname<T, arg>::type
+
+    BOOST_DEFAULT_TYPE_TMPLT(pointer);
+    BOOST_DEFAULT_TYPE_TMPLT(const_pointer);
+    BOOST_DEFAULT_TYPE_TMPLT(void_pointer);
+    BOOST_DEFAULT_TYPE_TMPLT(const_void_pointer);
+    BOOST_DEFAULT_TYPE_TMPLT(difference_type);
+    BOOST_DEFAULT_TYPE_TMPLT(size_type);
+    BOOST_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment);
+    BOOST_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
+    BOOST_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
+
+#if !defined(BOOST_NO_SFINAE_EXPR) || BOOST_WORKAROUND(BOOST_MSVC, >= 1500)
+    // Specialization is only needed for Visual C++. Without it SFINAE doesn't
+    // kick in.
+    template <unsigned int>
+    struct expr_sfinae;
+    
+    template <>
+    struct expr_sfinae<sizeof(yes_type)> {
+        typedef yes_type type;
+    };
+    
+    template <typename T>
+    struct has_select_on_container_copy_construction
+    {
+        // This needs to be a template for Visual C++.
+        template <typename T2>
+        static yes_type to_yes_type(const T2&);
+
+        template <typename T2>
+        static typename expr_sfinae<sizeof(to_yes_type(
+            ((T2 const*)0)->select_on_container_copy_construction()
+        ))>::type check(T2*);
+
+        static no_type check(void*);
+        
+        enum { value = sizeof(check((T*) 0)) == sizeof(yes_type) };
+    };
+#else
+    template <typename T>
+    struct has_select_on_container_copy_construction
+    {
+        typedef T (T::*SelectFunc)() const;
+
+        template <SelectFunc e> struct sfinae { typedef yes_type type; };
+
+        template <class U>  
+        static typename sfinae<&U::select_on_container_copy_construction>::type
+            test(int);  
+        template <class U>  
+        static no_type test(...);  
+ 
+        enum { value = sizeof(test<T>(1)) == sizeof(yes_type) };
+    };
+
+#endif
+
+    template <typename Alloc>
+    inline BOOST_DEDUCED_TYPENAME boost::enable_if<
+            has_select_on_container_copy_construction<Alloc>, Alloc
+        >::type call_select_on_container_copy_construction(const Alloc& rhs)
+    {
+        return rhs.select_on_container_copy_construction();
+    }
+
+    template <typename Alloc>
+    inline BOOST_DEDUCED_TYPENAME boost::disable_if<
+            has_select_on_container_copy_construction<Alloc>, Alloc
+        >::type call_select_on_container_copy_construction(const Alloc& rhs)
+    {
+        return rhs;
+    }
+
+    template <typename Alloc>
+    struct allocator_traits
+    {
+        typedef Alloc allocator_type;
+        typedef typename Alloc::value_type value_type;
+
+        typedef BOOST_DEFAULT_TYPE(Alloc, pointer, value_type*)
+            pointer;
+
+        // For now always use the allocator's const_pointer.
+
+        //typedef BOOST_DEFAULT_TYPE(Alloc, const_pointer,
+        //    BOOST_DEDUCED_TYPENAME pointer_traits<pointer>::
+        //    BOOST_NESTED_TEMPLATE rebind<const value_type>::other)
+        //    const_pointer;
+
+        typedef BOOST_DEFAULT_TYPE(Alloc, const_pointer, value_type const*)
+            const_pointer;
+
+        // I'm not using void pointers for now.
+
+        //typedef BOOST_DEFAULT_TYPE(Alloc, void_pointer,
+        //    BOOST_NESTED_TEMPLATE pointer_traits<pointer>::
+        //    BOOST_NESTED_TEMPLATE rebind<void>::other)
+        //    void_pointer;
+
+        //typedef BOOST_DEFAULT_TYPE(Alloc, const_void_pointer,
+        //    BOOST_DEDUCED_TYPENAME pointer_traits<pointer>::
+        //    BOOST_NESTED_TEMPLATE rebind<const void>::other)
+        //    const_void_pointer;
+
+        typedef BOOST_DEFAULT_TYPE(Alloc, difference_type, std::ptrdiff_t)
+            difference_type;
+
+        typedef BOOST_DEFAULT_TYPE(Alloc, size_type, std::size_t)
+            size_type;
+
+        // TODO: rebind_alloc and rebind_traits
+
+       static pointer allocate(Alloc& a, size_type n)
+            { return a.allocate(n); }
+
+        // I never use this, so I'll just comment it out for now.
+        //
+        //static pointer allocate(Alloc& a, size_type n, const_void_pointer hint)
+        //    { return DEFAULT_FUNC(allocate, pointer)(a, n, hint); }
+    
+        static void deallocate(Alloc& a, pointer p, size_type n)
+            { a.deallocate(p, n); }
+
+        // Only support the basic copy constructor
+
+        // template <typename T, typename... Args>
+        // static void construct(Alloc& a, T* p, Args&&... args) {
+        //     DEFAULT_FUNC(construct,void)(a, p, std::forward<Args>(args)...);
+        // }
+
+        template <typename T>
+        static void construct(Alloc& a, T* p, T const& x) {
+            a.construct(p, x);
+        }
+
+        template <typename T>
+        static void destroy(Alloc& a, T* p) {
+            // DEFAULT_FUNC(destroy,void)(a, p);
+            a.destroy(p);
+        }
+
+        static size_type max_size(const Alloc& a)
+            { return a.max_size(); }
+
+        // Allocator propagation on construction
+        
+        static Alloc select_on_container_copy_construction(Alloc const& rhs)
+        {
+            return boost::unordered::detail::
+                call_select_on_container_copy_construction(rhs);
+        }
+    
+        // Allocator propagation on assignment and swap.
+        // Return true if lhs is modified.
+        typedef BOOST_DEFAULT_TYPE(
+            Alloc, propagate_on_container_copy_assignment, false_type)
+            propagate_on_container_copy_assignment;
+        typedef BOOST_DEFAULT_TYPE(
+            Alloc,propagate_on_container_move_assignment, false_type)
+            propagate_on_container_move_assignment;
+        typedef BOOST_DEFAULT_TYPE(
+            Alloc,propagate_on_container_swap,false_type)
+            propagate_on_container_swap;
+    };
 #endif
 
     // allocator_array_constructor
@@ -49,10 +287,11 @@
     // clean up if an exception is thrown before the container takes charge
     // of it.
 
-    template <class Allocator>
+    template <typename Allocator>
     struct allocator_array_constructor
     {
-        typedef BOOST_DEDUCED_TYPENAME Allocator::pointer pointer;
+        typedef BOOST_DEDUCED_TYPENAME allocator_traits<Allocator>::pointer
+            pointer;
 
         Allocator& alloc_;
         pointer ptr_;
@@ -69,21 +308,23 @@
         ~allocator_array_constructor() {
             if (ptr_) {
                 for(pointer p = ptr_; p != constructed_; ++p)
-                    alloc_.destroy(p);
+                    allocator_traits<Allocator>::destroy(alloc_,
+                        boost::addressof(*p));
 
-                alloc_.deallocate(ptr_, length_);
+                allocator_traits<Allocator>::deallocate(alloc_, ptr_, length_);
             }
         }
 
-        template <class V>
+        template <typename V>
         void construct(V const& v, std::size_t l)
         {
             BOOST_ASSERT(!ptr_);
             length_ = l;
-            ptr_ = alloc_.allocate(length_);
+            ptr_ = allocator_traits<Allocator>::allocate(alloc_, length_);
             pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
             for(constructed_ = ptr_; constructed_ != end; ++constructed_)
-                alloc_.construct(constructed_, v);
+                allocator_traits<Allocator>::construct(alloc_,
+                    boost::addressof(*constructed_), v);
         }
 
         pointer get() const
@@ -102,7 +343,7 @@
         allocator_array_constructor& operator=(
             allocator_array_constructor const&);
     };
-}}
+}}}
 
 #if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
 #  undef BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES
Modified: branches/release/boost/unordered/detail/buckets.hpp
==============================================================================
--- branches/release/boost/unordered/detail/buckets.hpp	(original)
+++ branches/release/boost/unordered/detail/buckets.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -1,183 +1,808 @@
 
 // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
-// Copyright (C) 2005-2009 Daniel James
+// Copyright (C) 2005-2011 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_MANAGER_HPP_INCLUDED
 #define BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
 
-#include <boost/config.hpp>
-#include <boost/assert.hpp>
 #include <boost/unordered/detail/node.hpp>
-#include <boost/unordered/detail/util.hpp>
 
-namespace boost { namespace unordered_detail {
+namespace boost { namespace unordered { namespace detail {
     
     ////////////////////////////////////////////////////////////////////////////
-    // Buckets
+    //
+    // Now the main data structure:
+    //
+    // buckets<A, Unique>           functions<H, P>
+    //       |                              |
+    //       +---------------+--------------+
+    //                       |
+    //                   table<T>
+    //
+    // T is a class which contains typedefs for all the types we need.
     
-    template <class A, class G>
-    inline std::size_t hash_buckets<A, G>::max_bucket_count() const {
-        // -1 to account for the sentinel.
-        return prev_prime(this->bucket_alloc().max_size() - 1);
-    }
+    // buckets
+    //
+    // This is responsible for allocating and deallocating buckets and nodes.
+    //
+    // Notes:
+    // 1. For the sake exception safety the consturctors 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, bool Unique>
+    class buckets
+    {
+        buckets(buckets const&);
+        buckets& operator=(buckets const&);
+    public:
+        // Types
+
+        typedef BOOST_DEDUCED_TYPENAME ::boost::detail::if_true<Unique>::
+            BOOST_NESTED_TEMPLATE then<
+                ::boost::unordered::detail::ungrouped_node<A>,
+                ::boost::unordered::detail::grouped_node<A>
+            >::type node;
+
+        typedef A value_allocator;
+        typedef ::boost::unordered::detail::bucket<A> bucket;
+        typedef BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type value_type;
+
+        typedef BOOST_DEDUCED_TYPENAME bucket::bucket_allocator
+            bucket_allocator;
+        typedef BOOST_DEDUCED_TYPENAME allocator_traits<bucket_allocator>::pointer bucket_ptr;
+        typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
+
+        typedef BOOST_DEDUCED_TYPENAME rebind_wrap<value_allocator, node>::type
+            node_allocator;
+        typedef BOOST_DEDUCED_TYPENAME allocator_traits<node_allocator>::pointer real_node_ptr;
+
+        // Members
+
+        bucket_ptr buckets_;
+        std::size_t bucket_count_;
+        std::size_t size_;
+        compressed_pair<bucket_allocator, node_allocator> allocators_;
+        
+        // Data access
+
+        bucket_allocator const& bucket_alloc() const
+        {
+            return allocators_.first();
+        }
 
-    template <class A, class G>
-    inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
-        hash_buckets<A, G>::get_bucket(std::size_t num) const
-    {
-        return buckets_ + static_cast<std::ptrdiff_t>(num);
-    }
+        node_allocator const& node_alloc() const
+        {
+            return allocators_.second();
+        }
 
-    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 get_bucket(hashed % bucket_count_);
-    }
+        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 start bucket.
+            return prev_prime(allocator_traits<bucket_allocator>::max_size(bucket_alloc()) - 1);
+        }
+
+        ////////////////////////////////////////////////////////////////////////
+        // Constructors and Destructors
+
+        buckets(node_allocator const& a, std::size_t bucket_count)
+          : buckets_(),
+            bucket_count_(bucket_count),
+            size_(),
+            allocators_(a,a)
+        {
+        }
+
+        buckets(buckets& b, move_tag m)
+          : buckets_(),
+            bucket_count_(b.bucket_count_),
+            size_(),
+            allocators_(b.allocators_, m)
+        {
+            swap(b);
+        }
+
+        template <typename T>
+        buckets(table<T>& x, move_tag m)
+          : buckets_(),
+            bucket_count_(x.bucket_count_),
+            allocators_(x.allocators_, m)
+        {
+            swap(x);
+            x.size_ = 0;
+        }
+        
+        inline ~buckets()
+        {
+            if(this->buckets_) { this->delete_buckets(); }
+        }
+
+        void create_buckets()
+        {
+            // The array constructor will clean up in the event of an
+            // exception.
+            allocator_array_constructor<bucket_allocator>
+                constructor(bucket_alloc());
     
-    template <class A, class G>
-    std::size_t hash_buckets<A, G>::bucket_size(std::size_t index) const
-    {
-        if(!buckets_) return 0;
-        bucket_ptr ptr = get_bucket(index)->next_;
-        std::size_t count = 0;
-        while(ptr) {
-            ++count;
+            // Creates an extra bucket to act as the start node.
+            constructor.construct(bucket(), this->bucket_count_ + 1);
+    
+            // Only release the buckets once everything is successfully
+            // done.
+            this->buckets_ = constructor.release();
+        }
+        
+        void swap(buckets& other, false_type = false_type())
+        {
+            BOOST_ASSERT(node_alloc() == other.node_alloc());
+            std::swap(buckets_, other.buckets_);
+            std::swap(bucket_count_, other.bucket_count_);
+            std::swap(size_, other.size_);
+        }
+
+        void swap(buckets& other, true_type)
+        {
+            allocators_.swap(other.allocators_);
+            std::swap(buckets_, other.buckets_);
+            std::swap(bucket_count_, other.bucket_count_);
+            std::swap(size_, other.size_);
+        }
+
+        void move_buckets_from(buckets& other)
+        {
+            BOOST_ASSERT(node_alloc() == other.node_alloc());
+            BOOST_ASSERT(!this->buckets_);
+            this->buckets_ = other.buckets_;
+            this->bucket_count_ = other.bucket_count_;
+            this->size_ = other.size_;
+            other.buckets_ = bucket_ptr();
+            other.bucket_count_ = 0;
+            other.size_ = 0;
+        }
+
+        std::size_t bucket_size(std::size_t index) const
+        {
+            if (!this->size_) return 0;
+            node_ptr ptr = this->buckets_[index].next_;
+            if (!ptr) return 0;
             ptr = ptr->next_;
+    
+            std::size_t count = 0;
+            while(BOOST_UNORDERED_BORLAND_BOOL(ptr) &&
+                node::get_hash(ptr) % this->bucket_count_ == index)
+            {
+                ++count;
+                ptr = ptr->next_;
+            }
+    
+            return count;
         }
-        return count;
-    }
 
-    template <class A, class G>
-    inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::node_ptr
-        hash_buckets<A, G>::bucket_begin(std::size_t num) const
-    {
-        return buckets_ ? get_bucket(num)->next_ : node_ptr();
-    }
+        node_ptr bucket_begin(std::size_t bucket_index) const
+        {
+            if (!this->size_) return node_ptr();
+            bucket& b = this->buckets_[bucket_index];
+            if (!b.next_) return node_ptr();
+            return b.next_->next_;
+        }
 
-    ////////////////////////////////////////////////////////////////////////////
-    // Delete
+        // For the remaining functions, buckets_ must not be null.
+        
+        bucket_ptr get_bucket(std::size_t bucket_index) const
+        {
+            return buckets_ + static_cast<std::ptrdiff_t>(bucket_index);
+        }
 
-    template <class A, class G>
-    inline void hash_buckets<A, G>::delete_node(node_ptr b)
-    {
-        node* raw_ptr = static_cast<node*>(&*b);
-        boost::unordered_detail::destroy(raw_ptr->value_ptr());
-        real_node_ptr n(node_alloc().address(*raw_ptr));
-        node_alloc().destroy(n);
-        node_alloc().deallocate(n, 1);
-    }
+        float load_factor() const
+        {
+            BOOST_ASSERT(this->bucket_count_ != 0);
+            return static_cast<float>(this->size_)
+                / static_cast<float>(this->bucket_count_);
+        }
 
-    template <class A, class G>
-    inline void hash_buckets<A, G>::clear_bucket(bucket_ptr b)
-    {
-        node_ptr node_it = b->next_;
-        b->next_ = node_ptr();
+        ////////////////////////////////////////////////////////////////////////
+        // Delete
+        
+        void delete_node(node_ptr n)
+        {
+            node* raw_ptr = static_cast<node*>(boost::addressof(*n));
+            real_node_ptr real_ptr(node_alloc().address(*raw_ptr));
+
+            ::boost::unordered::detail::destroy(raw_ptr->value_ptr());
+            allocator_traits<node_allocator>::destroy(node_alloc(), raw_ptr);
+            allocator_traits<node_allocator>::deallocate(node_alloc(), real_ptr, 1);
 
-        while(node_it) {
-            node_ptr node_to_delete = node_it;
-            node_it = node_it->next_;
-            delete_node(node_to_delete);
+            --this->size_;
+        }
+
+        void delete_buckets()
+        {
+            bucket_ptr end = this->get_bucket(this->bucket_count_);
+            node_ptr n = (end)->next_;
+            while(BOOST_UNORDERED_BORLAND_BOOL(n))
+            {
+                node_ptr node_to_delete = n;
+                n = n->next_;
+                delete_node(node_to_delete);
+            }
+    
+            ++end;
+            for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
+                allocator_traits<bucket_allocator>::destroy(bucket_alloc(),
+                    boost::addressof(*begin));
+            }
+    
+            allocator_traits<bucket_allocator>::deallocate(bucket_alloc(), this->buckets_, this->bucket_count_ + 1);
+    
+            this->buckets_ = bucket_ptr();
+            BOOST_ASSERT(this->size_ == 0);
         }
-    }
 
-    template <class A, class G>
-    inline void hash_buckets<A, G>::delete_buckets()
-    {      
-        bucket_ptr end = this->get_bucket(this->bucket_count_);
+        std::size_t delete_nodes(node_ptr begin, node_ptr end)
+        {
+            std::size_t count = 0;
+            while(begin != end) {
+                node_ptr n = begin;
+                begin = begin->next_;
+                delete_node(n);
+                ++count;
+            }
+            return count;
+        }
 
-        for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
-            clear_bucket(begin);
+        void clear()
+        {
+            if(!this->size_) return;
+    
+            bucket_ptr end = this->get_bucket(this->bucket_count_);
+    
+            node_ptr n = (end)->next_;
+            while(BOOST_UNORDERED_BORLAND_BOOL(n))
+            {
+                node_ptr node_to_delete = n;
+                n = n->next_;
+                this->delete_node(node_to_delete);
+            }
+    
+            ++end;
+            for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
+                begin->next_ = bucket_ptr();
+            }
+    
+            this->size_ = 0;
         }
 
-        // Destroy the buckets (including the sentinel bucket).
-        ++end;
-        for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
-            bucket_alloc().destroy(begin);
+        node_ptr erase(node_ptr r)
+        {
+            BOOST_ASSERT(r);
+            node_ptr next = r->next_;
+    
+            bucket_ptr bucket = this->get_bucket(
+                node::get_hash(r) % this->bucket_count_);
+            node_ptr prev = node::unlink_node(*bucket, r);
+    
+            this->fix_buckets(bucket, prev, next);
+    
+            this->delete_node(r);
+    
+            return next;
         }
 
-        bucket_alloc().deallocate(this->buckets_, this->bucket_count_ + 1);
+        node_ptr erase_range(node_ptr r1, node_ptr r2)
+        {
+            if (r1 == r2) return r2;
+    
+            std::size_t bucket_index = node::get_hash(r1) % this->bucket_count_;
+            node_ptr prev = node::unlink_nodes(
+                this->buckets_[bucket_index], r1, r2);
+            this->fix_buckets_range(bucket_index, prev, r1, r2);
+            this->delete_nodes(r1, r2);
+    
+            return r2;
+        }
 
-        this->buckets_ = bucket_ptr();
-    }
+        // This is called after erasing a node or group of nodes to fix up
+        // the bucket pointers.
+        void fix_buckets(bucket_ptr bucket, node_ptr prev, node_ptr next)
+        {
+            if (!next)
+            {
+                if (bucket->next_ == prev) bucket->next_ = node_ptr();
+            }
+            else
+            {
+                bucket_ptr next_bucket = this->get_bucket(
+                    node::get_hash(next) % this->bucket_count_);
+                if (next_bucket != bucket)
+                {
+                    next_bucket->next_ = prev;
+                    if (bucket->next_ == prev) bucket->next_ = node_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) {
+        // This is called after erasing a range of nodes to fix any bucket
+        // pointers into that range.
+        void fix_buckets_range(
+            std::size_t bucket_index, node_ptr prev, node_ptr begin, node_ptr end)
+        {
             node_ptr n = begin;
-            begin = begin->next_;
-            delete_node(n);
-            ++count;
+    
+            // If we're not at the start of the current bucket, then
+            // go to the start of the next bucket.
+            if (this->get_bucket(bucket_index)->next_ != prev)
+            {
+                for(;;) {
+                    n = n->next_;
+                    if (n == end) return;
+    
+                    std::size_t new_bucket_index =
+                        node::get_hash(n) % this->bucket_count_;
+                    if (bucket_index != new_bucket_index) {
+                        bucket_index = new_bucket_index;
+                        break;
+                    }
+                }
+            }
+    
+            // Iterate through the remaining nodes, clearing out the bucket
+            // pointers.
+            this->buckets_[bucket_index].next_ = bucket_ptr();
+            for(;;) {
+                n = n->next_;
+                if (n == end) break;
+    
+                std::size_t new_bucket_index =
+                    node::get_hash(n) % this->bucket_count_;
+                if (bucket_index != new_bucket_index) {
+                    bucket_index = new_bucket_index;
+                    this->buckets_[bucket_index].next_ = bucket_ptr();
+                }
+            };
+    
+            // Finally fix the bucket containing the trailing node.
+            if (BOOST_UNORDERED_BORLAND_BOOL(n)) {
+                this->buckets_[node::get_hash(n) % this->bucket_count_].next_
+                    = prev;
+            }
         }
-        return count;
-    }
+
+        // Iterate through the nodes placing them in the correct buckets.
+        // pre: prev->next_ is not null.
+        node_ptr place_in_bucket(node_ptr prev, node_ptr end) {
+            bucket_ptr b = this->get_bucket(node::get_hash(prev->next_) % this->bucket_count_);
+
+            if (!b->next_) {
+                b->next_ = prev;
+                return end;
+            }
+            else {
+                node_ptr next = end->next_;
+                end->next_ = b->next_->next_;
+                b->next_->next_ = prev->next_;
+                prev->next_ = next;
+                return prev;
+            }
+        }
+        
+        void copy_buckets_to(buckets&) const;
+        void move_buckets_to(buckets&) const;
+        void rehash_impl(std::size_t);
+    };
+
+    // Assigning and swapping the equality and hash function objects
+    // needs strong exception safety. To implement that normally we'd
+    // require one of them to be known to not throw and the other to
+    // guarantee strong exception safety. Unfortunately they both only
+    // have basic exception safety. So to acheive strong exception
+    // safety we have storage space for two copies, and assign the new
+    // copies to the unused space. Then switch to using that to use
+    // them. This is implemented in 'set_hash_functions' which
+    // atomically assigns the new function objects in a strongly
+    // exception safe manner.
+
+    template <class H, class P> class set_hash_functions;
+
+    template <class H, class P>
+    class functions
+    {
+        friend class set_hash_functions<H, P>;
+        functions& operator=(functions const&);
+
+        typedef 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:
+
+        functions(H const& hf, P const& eq)
+            : current_(false)
+        {
+            construct(current_, hf, eq);
+        }
+
+        functions(functions const& bf)
+            : current_(false)
+        {
+            construct(current_, bf.current());
+        }
+
+        ~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&);
+    
+        functions<H,P>& functions_;
+        bool tmp_functions_;
+
+    public:
+
+        set_hash_functions(functions<H,P>& f, H const& h, P const& p)
+          : functions_(f),
+            tmp_functions_(!f.current_)
+        {
+            f.construct(tmp_functions_, h, p);
+        }
+
+        set_hash_functions(functions<H,P>& f, functions<H,P> const& other)
+          : functions_(f),
+            tmp_functions_(!f.current_)
+        {
+            f.construct(tmp_functions_, other.current());
+        }
+
+        ~set_hash_functions()
+        {
+            functions_.destroy(tmp_functions_);
+        }
+
+        void commit()
+        {
+            functions_.current_ = tmp_functions_;
+            tmp_functions_ = !tmp_functions_;
+        }
+    };
 
     ////////////////////////////////////////////////////////////////////////////
-    // Constructors and Destructors
+    // Node Constructors
+
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
 
-    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 T, class... Args>
+    inline void construct_impl(T*, void* address, Args&&... args)
     {
+        new(address) T(std::forward<Args>(args)...);
     }
 
-    template <class A, class G>
-    inline hash_buckets<A, G>::~hash_buckets()
-    {
-        if(this->buckets_) { this->delete_buckets(); }
+#else
+
+#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _)                       \
+    template <                                                                 \
+        class T,                                                               \
+        BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)                           \
+    >                                                                          \
+    inline void construct_impl(                                                \
+        T*, void* address,                                                     \
+        BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)                         \
+    )                                                                          \
+    {                                                                          \
+        new(address) T(                                                        \
+            BOOST_UNORDERED_CALL_PARAMS(z, num_params));                       \
+    }                                                                          \
+                                                                               \
+    template <class First, class Second, class Key,                            \
+        BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)                           \
+    >                                                                          \
+    inline void construct_impl(                                                \
+        std::pair<First, Second>*, void* address,                              \
+        Key const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params))          \
+    {                                                                          \
+        new(address) std::pair<First, Second>(k,                               \
+            Second(BOOST_UNORDERED_CALL_PARAMS(z, num_params)));               \
     }
+
+    BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
+        BOOST_UNORDERED_CONSTRUCT_IMPL, _)
+
+#undef BOOST_UNORDERED_CONSTRUCT_IMPL
+#endif
+
+    ///////////////////////////////////////////////////////////////////
+    //
+    // Node construction
+
+    template <class Alloc, bool Unique>
+    class node_constructor
+    {
+        typedef ::boost::unordered::detail::buckets<Alloc, Unique> buckets;
+        typedef BOOST_DEDUCED_TYPENAME buckets::node node;
+        typedef BOOST_DEDUCED_TYPENAME buckets::real_node_ptr real_node_ptr;
+        typedef BOOST_DEDUCED_TYPENAME buckets::value_type value_type;
+        typedef BOOST_DEDUCED_TYPENAME buckets::node_allocator node_allocator;
+
+        buckets& buckets_;
+        real_node_ptr node_;
+        bool node_constructed_;
+        bool value_constructed_;
+
+    public:
+
+        node_constructor(buckets& m) :
+            buckets_(m),
+            node_(),
+            node_constructed_(false),
+            value_constructed_(false)
+        {
+        }
+
+        ~node_constructor();
+        void construct_preamble();
+
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+        template <class... Args>
+        void construct(Args&&... args)
+        {
+            construct_preamble();
+            construct_impl((value_type*) 0, node_->address(),
+                std::forward<Args>(args)...);
+            value_constructed_ = true;
+        }
+#else
+
+#define BOOST_UNORDERED_CONSTRUCT(z, num_params, _)                            \
+        template <                                                             \
+            BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)                       \
+        >                                                                      \
+        void construct(                                                        \
+            BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)                     \
+        )                                                                      \
+        {                                                                      \
+            construct_preamble();                                              \
+            construct_impl(                                                    \
+                (value_type*) 0, node_->address(),                             \
+                BOOST_UNORDERED_CALL_PARAMS(z, num_params)                     \
+            );                                                                 \
+            value_constructed_ = true;                                         \
+        }
+
+        BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
+            BOOST_UNORDERED_CONSTRUCT, _)
+
+#undef BOOST_UNORDERED_CONSTRUCT
+
+#endif
+        template <class K, class M>
+        void construct_pair(K const& k, M*)
+        {
+            construct_preamble();
+            new(node_->address()) value_type(k, M());                    
+            value_constructed_ = true;
+        }
+
+        value_type& value() const
+        {
+            BOOST_ASSERT(node_);
+            return node_->value();
+        }
+
+        // no throw
+        BOOST_DEDUCED_TYPENAME buckets::node_ptr release()
+        {
+            real_node_ptr p = node_;
+            node_ = real_node_ptr();
+            // node_ptr cast
+            return buckets_.bucket_alloc().address(*p);
+        }
+
+    private:
+        node_constructor(node_constructor const&);
+        node_constructor& operator=(node_constructor const&);
+    };
     
-    template <class A, class G>
-    inline void hash_buckets<A, G>::create_buckets()
+    // node_constructor
+
+    template <class Alloc, bool Unique>
+    inline node_constructor<Alloc, Unique>::~node_constructor()
     {
-        // The array constructor will clean up in the event of an
-        // exception.
-        allocator_array_constructor<bucket_allocator>
-            constructor(bucket_alloc());
+        if (node_) {
+            if (value_constructed_) {
+#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
+                struct dummy { node<Alloc, Grouped> x; };
+#endif
+                ::boost::unordered::detail::destroy(node_->value_ptr());
+            }
 
-        // Creates an extra bucket to act as a sentinel.
-        constructor.construct(bucket(), this->bucket_count_ + 1);
+            if (node_constructed_)
+                allocator_traits<node_allocator>::destroy(buckets_.node_alloc(),
+                    boost::addressof(*node_));
 
-        // Set up the sentinel (node_ptr cast)
-        bucket_ptr sentinel = constructor.get() +
-            static_cast<std::ptrdiff_t>(this->bucket_count_);
-        sentinel->next_ = sentinel;
+            allocator_traits<node_allocator>::deallocate(buckets_.node_alloc(), node_, 1);
+        }
+    }
+
+    template <class Alloc, bool Unique>
+    inline void node_constructor<Alloc, Unique>::construct_preamble()
+    {
+        if(!node_) {
+            node_constructed_ = false;
+            value_constructed_ = false;
+
+            node_ = allocator_traits<node_allocator>::allocate(buckets_.node_alloc(), 1);
+            allocator_traits<node_allocator>::construct(buckets_.node_alloc(),
+                boost::addressof(*node_), node());
+            node_->init(buckets_.bucket_alloc().address(*node_));
 
-        // Only release the buckets once everything is successfully
-        // done.
-        this->buckets_ = constructor.release();
+            node_constructed_ = true;
+        }
+        else {
+            BOOST_ASSERT(node_constructed_ && value_constructed_);
+            ::boost::unordered::detail::destroy(node_->value_ptr());
+            value_constructed_ = false;
+        }
     }
 
     ////////////////////////////////////////////////////////////////////////////
-    // Constructors and Destructors
+    // copy_buckets_to
+    //
+    // basic exception safety. If an exception is thrown this will
+    // leave dst partially filled and the buckets unset.
 
-    // no throw
-    template <class A, class G>
-    inline void hash_buckets<A, G>::move(hash_buckets& other)
+    template <class A, bool Unique>
+    void buckets<A, Unique>::copy_buckets_to(buckets& dst) const
     {
-        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;
+        BOOST_ASSERT(!dst.buckets_);
+
+        dst.create_buckets();
+        bucket_ptr dst_start = dst.get_bucket(dst.bucket_count_);
+
+        {        
+            node_constructor<A, Unique> a(dst);
+    
+            node_ptr n = this->buckets_[this->bucket_count_].next_;
+            node_ptr prev = dst_start;
+            
+            while(n) {
+                std::size_t hash = node::get_hash(n);
+                node_ptr group_end = node::next_group(n);
+    
+                a.construct(node::get_value(n));
+                node_ptr first_node = a.release();
+                node::set_hash(first_node, hash);
+                node_ptr end = prev->next_ = first_node;
+                ++dst.size_;
+    
+                for(n = n->next_; n != group_end; n = n->next_) {
+                    a.construct(node::get_value(n));
+                    end = a.release();
+                    node::set_hash(end, hash);
+                    node::add_after_node(end, first_node);
+                    ++dst.size_;
+                }
+                
+                prev = dst.place_in_bucket(prev, end);
+            }
+        }
     }
 
-    template <class A, class G>
-    inline void hash_buckets<A, G>::swap(hash_buckets<A, G>& other)
+    ////////////////////////////////////////////////////////////////////////////
+    // move_buckets_to
+    //
+    // Basic exception safety. The source nodes are left in an unusable state
+    // if an exception throws.
+
+    template <class A, bool Unique>
+    void buckets<A, Unique>::move_buckets_to(buckets& dst) const
     {
-        BOOST_ASSERT(node_alloc() == other.node_alloc());
-        std::swap(buckets_, other.buckets_);
-        std::swap(bucket_count_, other.bucket_count_);
+        BOOST_ASSERT(!dst.buckets_);
+
+        dst.create_buckets();
+        bucket_ptr dst_start = dst.get_bucket(dst.bucket_count_);
+
+        {        
+            node_constructor<A, Unique> a(dst);
+    
+            node_ptr n = this->buckets_[this->bucket_count_].next_;
+            node_ptr prev = dst_start;
+            
+            while(n) {
+                std::size_t hash = node::get_hash(n);
+                node_ptr group_end = node::next_group(n);
+    
+                a.construct(boost::move(node::get_value(n)));
+                node_ptr first_node = a.release();
+                node::set_hash(first_node, hash);
+                node_ptr end = prev->next_ = first_node;
+                ++dst.size_;
+    
+                for(n = n->next_; n != group_end; n = n->next_) {
+                    a.construct(boost::move(node::get_value(n)));
+                    end = a.release();
+                    node::set_hash(end, hash);
+                    node::add_after_node(end, first_node);
+                    ++dst.size_;
+                }
+                
+                prev = dst.place_in_bucket(prev, end);
+            }
+        }
+    }
+
+    // strong otherwise exception safety
+    template <class A, bool Unique>
+    void buckets<A, Unique>::rehash_impl(std::size_t num_buckets)
+    {
+        BOOST_ASSERT(this->size_);
+
+        buckets dst(this->node_alloc(), num_buckets);
+        dst.create_buckets();
+        
+        bucket_ptr src_start = this->get_bucket(this->bucket_count_);
+        bucket_ptr dst_start = dst.get_bucket(dst.bucket_count_);
+
+        dst_start->next_ = src_start->next_;
+        src_start->next_ = bucket_ptr();
+        dst.size_ = this->size_;
+        this->size_ = 0;
+
+        node_ptr prev = dst_start;
+        while (BOOST_UNORDERED_BORLAND_BOOL(prev->next_))
+            prev = dst.place_in_bucket(prev, node::next_group2(prev));
+
+        // Swap the new nodes back into the container and setup the
+        // variables.
+        dst.swap(*this); // no throw
     }
-}}
+}}}
 
 #endif
Modified: branches/release/boost/unordered/detail/equivalent.hpp
==============================================================================
--- branches/release/boost/unordered/detail/equivalent.hpp	(original)
+++ branches/release/boost/unordered/detail/equivalent.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -1,19 +1,18 @@
 
 // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
-// Copyright (C) 2005-2009 Daniel James
+// Copyright (C) 2005-2011 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 {
+namespace boost { namespace unordered { namespace detail {
 
     template <class T>
-    class hash_equivalent_table : public T::table
+    class equivalent_table : public T::table_base
     {
     public:
         typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
@@ -21,284 +20,288 @@
         typedef BOOST_DEDUCED_TYPENAME T::value_allocator value_allocator;
         typedef BOOST_DEDUCED_TYPENAME T::key_type key_type;
         typedef BOOST_DEDUCED_TYPENAME T::value_type value_type;
-        typedef BOOST_DEDUCED_TYPENAME T::table table;
+        typedef BOOST_DEDUCED_TYPENAME T::table_base table_base;
         typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor;
+        typedef BOOST_DEDUCED_TYPENAME T::node_allocator node_allocator;
 
         typedef BOOST_DEDUCED_TYPENAME T::node node;
         typedef BOOST_DEDUCED_TYPENAME T::node_ptr node_ptr;
         typedef BOOST_DEDUCED_TYPENAME T::bucket_ptr bucket_ptr;
-        typedef BOOST_DEDUCED_TYPENAME T::iterator_base iterator_base;
         typedef BOOST_DEDUCED_TYPENAME T::extractor extractor;
 
         // Constructors
 
-        hash_equivalent_table(std::size_t n,
+        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,
+          : table_base(n, hf, eq, a) {}
+        equivalent_table(equivalent_table const& x)
+          : table_base(x,
+                allocator_traits<node_allocator>::
+                select_on_container_copy_construction(x.node_alloc())) {}
+        equivalent_table(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,
+          : table_base(x, a) {}
+        equivalent_table(equivalent_table& x, move_tag m)
+          : table_base(x, m) {}
+        equivalent_table(equivalent_table& x,
             value_allocator const& a, move_tag m)
-          : table(x, a, m) {}
-        ~hash_equivalent_table() {}
+          : table_base(x, a, m) {}
+        ~equivalent_table() {}
 
-        // Insert methods
-
-        iterator_base emplace_impl(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);
+        // Equality
 
-#else
-
-#define BOOST_UNORDERED_INSERT_IMPL(z, n, _)                                   \
-        template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)>                         \
-        iterator_base emplace(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);
-    };
-
-    template <class H, class P, class A>
-    struct multiset : public types<
-        BOOST_DEDUCED_TYPENAME A::value_type,
-        BOOST_DEDUCED_TYPENAME A::value_type,
-        H, P, A,
-        set_extractor<BOOST_DEDUCED_TYPENAME A::value_type>,
-        grouped>
-    {
-        typedef hash_equivalent_table<multiset<H, P, A> > impl;
-        typedef hash_table<multiset<H, P, A> > table;
-    };
-
-    template <class K, class H, class P, class A>
-    struct multimap : public types<
-        K, BOOST_DEDUCED_TYPENAME A::value_type,
-        H, P, A,
-        map_extractor<K, BOOST_DEDUCED_TYPENAME A::value_type>,
-        grouped>
-    {
-        typedef hash_equivalent_table<multimap<K, H, P, A> > impl;
-        typedef hash_table<multimap<K, H, P, A> > table;
-    };
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Equality
-
-    template <class T>
-    bool hash_equivalent_table<T>
-        ::equals(hash_equivalent_table<T> 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)
+        bool equals(equivalent_table const& other) const
         {
-            node_ptr it1 = i->next_;
-            while(BOOST_UNORDERED_BORLAND_BOOL(it1))
+            if(this->size_ != other.size_) return false;
+            if(!this->size_) return true;
+    
+            for(node_ptr n1 = this->buckets_[this->bucket_count_].next_; n1;)
             {
-                node_ptr it2 = other.find_iterator(this->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;
+                node_ptr n2 = other.find_matching_node(n1);
+                if (!n2) return false;
+                node_ptr end1 = node::next_group(n1);
+                node_ptr end2 = node::next_group(n2);
+                if (!group_equals(n1, end1, n2, end2)) return false;
+                n1 = end1;    
             }
+    
+            return true;
         }
+        
+        static bool group_equals(node_ptr n1, node_ptr end1,
+                node_ptr n2, node_ptr end2)
+        {
+            for(;;)
+            {
+                if (node::get_value(n1) != node::get_value(n2))
+                    break;
 
-        return true;
-    }
+                n1 = n1->next_;
+                n2 = n2->next_;
+            
+                if (n1 == end1) return n2 == end2;
+                if (n2 == end2) return false;
+            }
+            
+            for(node_ptr n1a = n1, n2a = n2;;)
+            {
+                n1a = n1a->next_;
+                n2a = n2a->next_;
 
-    ////////////////////////////////////////////////////////////////////////////
-    // A convenience method for adding nodes.
+                if (n1a == end1)
+                {
+                    if (n2a == end2) break;
+                    else return false;
+                }
+                if (n2a == end2) return false;
+            }
 
-    template <class T>
-    inline BOOST_DEDUCED_TYPENAME hash_equivalent_table<T>::node_ptr
-        hash_equivalent_table<T>
-            ::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;
-    }
+            node_ptr start = n1;
+            for(;n1 != end2; n1 = n1->next_)
+            {
+                value_type const& v = node::get_value(n1);
+                if (find(start, n1, v)) continue;
+                std::size_t matches = count_equal(n2, end2, v);
+                if (!matches || matches != 1 + count_equal(n1->next_, end1, v))
+                    return false;
+            }
+            
+            return true;
+        }
+        
+        static bool find(node_ptr n, node_ptr end, value_type const& v)
+        {
+            for(;n != end; n = n->next_)
+                if (node::get_value(n) == v)
+                    return true;
+            return false;
+        }
+        
+        static std::size_t count_equal(node_ptr n, node_ptr end, value_type const& v)
+        {
+            std::size_t count = 0;
+            for(;n != end; n = n->next_)
+                if (node::get_value(n) == v) ++count;
+            return count;
+        }
 
-    ////////////////////////////////////////////////////////////////////////////
-    // Insert methods
+        ////////////////////////////////////////////////////////////////////////
+        // A convenience method for adding nodes.
 
-    template <class T>
-    inline BOOST_DEDUCED_TYPENAME
-        hash_equivalent_table<T>::iterator_base
-        hash_equivalent_table<T>::emplace_impl(node_constructor& a)
-    {
-        key_type const& k = this->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);
+        inline node_ptr add_node(
+                node_constructor& a,
+                std::size_t bucket_index,
+                std::size_t hash,
+                node_ptr pos)
+        {
+            node_ptr n = a.release();
+            node::set_hash(n, hash);
+    
+            if(BOOST_UNORDERED_BORLAND_BOOL(pos)) {
+                node::add_after_node(n, pos);
+                if (n->next_) {
+                    std::size_t next_bucket =
+                        node::get_hash(n->next_) % this->bucket_count_;
+                    if (next_bucket != bucket_index) {
+                        this->buckets_[next_bucket].next_ = n;
+                    }
+                }
+            }
+            else {
+                bucket_ptr b = this->get_bucket(bucket_index);
+    
+                if (!b->next_)
+                {
+                    bucket_ptr start_node =
+                        this->get_bucket(this->bucket_count_);
+                    
+                    if (BOOST_UNORDERED_BORLAND_BOOL(start_node->next_)) {
+                        this->buckets_[
+                            node::get_hash(start_node->next_) %
+                                this->bucket_count_].next_ = n;
+                    }
+    
+                    b->next_ = start_node;
+                    n->next_ = start_node->next_;
+                    start_node->next_ = n;
+                }
+                else
+                {
+                    n->next_ = b->next_->next_;
+                    b->next_->next_ = n;
+                }
+            }
+            ++this->size_;
+            return n;
         }
-        else {
-            bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
-            node_ptr position = this->find_iterator(bucket, k);
 
+        ////////////////////////////////////////////////////////////////////////
+        // Insert methods
+
+        node_ptr emplace_impl(node_constructor& a)
+        {
+            key_type const& k = this->get_key(a.value());
+            std::size_t hash = this->hash_function()(k);
+            std::size_t bucket_index = hash % this->bucket_count_;
+            node_ptr position = this->find_node(bucket_index, hash, k);
+    
             // 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));
-        }
-    }
+            if(this->reserve_for_insert(this->size_ + 1)) {
+                bucket_index = hash % this->bucket_count_;
+            }
     
-    template <class T>
-    inline void hash_equivalent_table<T>
-            ::emplace_impl_no_rehash(node_constructor& a)
-    {
-        key_type const& k = this->get_key(a.value());
-        bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
-        add_node(a, bucket, this->find_iterator(bucket, k));
-    }
-
-#if defined(BOOST_UNORDERED_STD_FORWARD)
+            return add_node(a, bucket_index, hash, position);
+        }
 
-    // Emplace (equivalent key containers)
-    // (I'm using an overloaded emplace for both 'insert' and 'emplace')
+        void emplace_impl_no_rehash(node_constructor& a)
+        {
+            key_type const& k = this->get_key(a.value());
+            std::size_t hash = this->hash_function()(k);
+            std::size_t bucket_index = hash % this->bucket_count_;
+            add_node(a, bucket_index, hash,
+                this->find_node(bucket_index, hash, k));
+        }
 
-    // if hash function throws, basic exception safety
-    // strong otherwise
-    template <class T>
-    template <class... Args>
-    BOOST_DEDUCED_TYPENAME hash_equivalent_table<T>::iterator_base
-        hash_equivalent_table<T>
-            ::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)...);
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
 
-        return emplace_impl(a);
-    }
+        template <class... Args>
+        node_ptr emplace(Args&&... args)
+        {
+            // Create the node before rehashing in case it throws an
+            // exception (need strong safety in such a case).
+            node_constructor a(*this);
+            a.construct(std::forward<Args>(args)...);
+    
+            return emplace_impl(a);
+        }
 
 #else
 
 #define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _)                       \
-    template <class T>                                                      \
-    template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)>                 \
-    BOOST_DEDUCED_TYPENAME hash_equivalent_table<T>::iterator_base          \
-        hash_equivalent_table<T>                                            \
-            ::emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params))       \
-    {                                                                       \
-        node_constructor a(*this);                                          \
-        a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params));            \
-        return emplace_impl(a);                                             \
-    }
+        template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)>             \
+        node_ptr emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params))    \
+        {                                                                   \
+            node_constructor a(*this);                                      \
+            a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params));        \
+            return emplace_impl(a);                                         \
+        }
 
-    BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
-        BOOST_UNORDERED_INSERT_IMPL, _)
+        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 T>
-    template <class I>
-    inline void hash_equivalent_table<T>
-        ::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);
+        ////////////////////////////////////////////////////////////////////////
+        // Insert range methods
 
-            // Only require basic exception safety here
-            if(this->size_) {
-                this->reserve_for_insert(this->size_ + distance);
+        // if hash function throws, or inserting > 1 element, basic exception
+        // safety. Strong otherwise
+        template <class I>
+        void insert_for_range(I i, I j, forward_traversal_tag)
+        {
+            if(i == j) return;
+            std::size_t distance = ::boost::unordered::detail::distance(i, j);
+            if(distance == 1) {
+                emplace(*i);
             }
             else {
-                a.construct(*i++);
-                this->emplace_empty_impl_with_node(a, distance);
+                // Only require basic exception safety here
+                this->reserve_for_insert(this->size_ + distance);
+
+                node_constructor a(*this);    
+                for (; i != j; ++i) {
+                    a.construct(*i);
+                    emplace_impl_no_rehash(a);
+                }
             }
+        }
 
+        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_no_rehash(a);
+                emplace_impl(a);
             }
         }
-    }
 
-    // if hash function throws, or inserting > 1 element, basic exception safety
-    // strong otherwise
-    template <class T>
-    template <class I>
-    inline void hash_equivalent_table<T>
-        ::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
+        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);
         }
-    }
 
-    // if hash function throws, or inserting > 1 element, basic exception safety
-    // strong otherwise
-    template <class T>
-    template <class I>
-    void hash_equivalent_table<T>::insert_range(I i, I j)
+    };
+
+    template <class H, class P, class A>
+    struct multiset : public types<
+        BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
+        BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
+        H, P, A,
+        set_extractor<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>,
+        false>
     {
-        BOOST_DEDUCED_TYPENAME boost::iterator_traversal<I>::type
-            iterator_traversal_tag;
-        insert_for_range(i, j, iterator_traversal_tag);
-    }
-}}
+        typedef equivalent_table<multiset<H, P, A> > impl;
+        typedef table<multiset<H, P, A> > table_base;
+    };
+
+    template <class K, class H, class P, class A>
+    struct multimap : public types<
+        K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
+        H, P, A,
+        map_extractor<K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>,
+        false>
+    {
+        typedef equivalent_table<multimap<K, H, P, A> > impl;
+        typedef table<multimap<K, H, P, A> > table_base;
+    };
+}}}
 
 #endif
Modified: branches/release/boost/unordered/detail/extract_key.hpp
==============================================================================
--- branches/release/boost/unordered/detail/extract_key.hpp	(original)
+++ branches/release/boost/unordered/detail/extract_key.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -1,17 +1,16 @@
 
-// Copyright (C) 2005-2009 Daniel James
+// Copyright (C) 2005-2011 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_EXTRACT_KEY_HPP_INCLUDED
 #define BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
 
-#include <boost/config.hpp>
-#include <boost/type_traits/remove_const.hpp>
-#include <boost/unordered/detail/fwd.hpp>
+#include <boost/unordered/detail/table.hpp>
 
 namespace boost {
-namespace unordered_detail {
+namespace unordered {
+namespace detail {
 
     // key extractors
     //
@@ -39,12 +38,19 @@
             return v;
         }
 
+#if BOOST_UNORDERED_USE_RV_REF
+        static key_type const& extract(BOOST_RV_REF(key_type) v)
+        {
+            return v;
+        }
+#endif
+
         static no_key extract()
         {
             return no_key();
         }
         
-#if defined(BOOST_UNORDERED_STD_FORWARD)
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
         template <class... Args>
         static no_key extract(Args const&...)
         {
@@ -75,7 +81,7 @@
     struct map_extractor
     {
         typedef ValueType value_type;
-        typedef BOOST_DEDUCED_TYPENAME boost::remove_const<Key>::type key_type;
+        typedef BOOST_DEDUCED_TYPENAME ::boost::remove_const<Key>::type key_type;
 
         static key_type const& extract(value_type const& v)
         {
@@ -87,6 +93,13 @@
             return v;
         }
 
+        // TODO: Why does this cause errors?
+        //
+        //static key_type const& extract(BOOST_RV_REF(key_type) v)
+        //{
+        //    return v;
+        //}
+
         template <class Second>
         static key_type const& extract(std::pair<key_type, Second> const& v)
         {
@@ -100,7 +113,7 @@
             return v.first;
         }
 
-#if defined(BOOST_UNORDERED_STD_FORWARD)
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
         template <class Arg1, class... Args>
         static key_type const& extract(key_type const& k,
             Arg1 const&, Args const&...)
@@ -143,6 +156,6 @@
             return x.second == y.second;
         }
     };
-}}
+}}}
 
 #endif
Copied: branches/release/boost/unordered/detail/fwd.hpp (from r72401, /trunk/boost/unordered/detail/fwd.hpp)
==============================================================================
--- /trunk/boost/unordered/detail/fwd.hpp	(original)
+++ branches/release/boost/unordered/detail/fwd.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -25,15 +25,6 @@
         class P = std::equal_to<K>,
         class A = std::allocator<std::pair<const K, T> > >
     class unordered_map;
-    template <class K, class T, class H, class P, class A>
-    inline bool operator==(unordered_map<K, T, H, P, A> const&,
-        unordered_map<K, T, H, P, A> const&);
-    template <class K, class T, class H, class P, class A>
-    inline bool operator!=(unordered_map<K, T, H, P, A> const&,
-        unordered_map<K, T, H, P, A> const&);
-    template <class K, class T, class H, class P, class A>
-    inline void swap(unordered_map<K, T, H, P, A>&,
-            unordered_map<K, T, H, P, A>&);
 
     template <class K,
         class T,
@@ -41,46 +32,18 @@
         class P = std::equal_to<K>,
         class A = std::allocator<std::pair<const K, T> > >
     class unordered_multimap;
-    template <class K, class T, class H, class P, class A>
-    inline bool operator==(unordered_multimap<K, T, H, P, A> const&,
-        unordered_multimap<K, T, H, P, A> const&);
-    template <class K, class T, class H, class P, class A>
-    inline bool operator!=(unordered_multimap<K, T, H, P, A> const&,
-        unordered_multimap<K, T, H, P, A> const&);
-    template <class K, class T, class H, class P, class A>
-    inline void swap(unordered_multimap<K, T, H, P, A>&,
-            unordered_multimap<K, T, H, P, A>&);
 
     template <class T,
         class H = hash<T>,
         class P = std::equal_to<T>,
         class A = std::allocator<T> >
     class unordered_set;
-    template <class T, class H, class P, class A>
-    inline bool operator==(unordered_set<T, H, P, A> const&,
-        unordered_set<T, H, P, A> const&);
-    template <class T, class H, class P, class A>
-    inline bool operator!=(unordered_set<T, H, P, A> const&,
-        unordered_set<T, H, P, A> const&);
-    template <class T, class H, class P, class A>
-    inline void swap(unordered_set<T, H, P, A> &m1,
-            unordered_set<T, H, P, A> &m2);
 
     template <class T,
         class H = hash<T>,
         class P = std::equal_to<T>,
         class A = std::allocator<T> >
     class unordered_multiset;
-    template <class T, class H, class P, class A>
-    inline bool operator==(unordered_multiset<T, H, P, A> const&,
-        unordered_multiset<T, H, P, A> const&);
-    template <class T, class H, class P, class A>
-    inline bool operator!=(unordered_multiset<T, H, P, A> const&,
-        unordered_multiset<T, H, P, A> const&);
-    template <class T, class H, class P, class A>
-    inline void swap(unordered_multiset<T, H, P, A> &m1,
-            unordered_multiset<T, H, P, A> &m2);
-
 }
 }
 
Deleted: branches/release/boost/unordered/detail/move.hpp
==============================================================================
--- branches/release/boost/unordered/detail/move.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
+++ (empty file)
@@ -1,243 +0,0 @@
-/*
-    Copyright 2005-2007 Adobe Systems Incorporated
-   
-    Use, modification and distribution are subject to 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_MOVE_HEADER
-#define BOOST_UNORDERED_DETAIL_MOVE_HEADER
-
-#include <boost/config.hpp>
-#include <boost/mpl/bool.hpp>
-#include <boost/mpl/and.hpp>
-#include <boost/mpl/or.hpp>
-#include <boost/mpl/not.hpp>
-#include <boost/type_traits/is_convertible.hpp>
-#include <boost/type_traits/is_same.hpp>
-#include <boost/type_traits/is_class.hpp>
-#include <boost/utility/enable_if.hpp>
-#include <boost/detail/workaround.hpp>
-
-/*************************************************************************************************/
-
-#if defined(BOOST_NO_SFINAE)
-#  define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
-#elif defined(__GNUC__) && \
-    (__GNUC__ < 3 || __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
-#  define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
-#elif BOOST_WORKAROUND(BOOST_INTEL, < 900) || \
-    BOOST_WORKAROUND(__EDG_VERSION__, < 304) || \
-    BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0593))
-#  define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
-#endif
-
-/*************************************************************************************************/
-
-namespace boost {
-namespace unordered_detail {
-
-/*************************************************************************************************/
-
-namespace move_detail {
-
-/*************************************************************************************************/
-
-#if !defined(BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN)
-
-/*************************************************************************************************/
-
-template <typename T>  
-struct class_has_move_assign {  
-    class type {
-        typedef T& (T::*E)(T t);  
-        typedef char (&no_type)[1];  
-        typedef char (&yes_type)[2];  
-        template <E e> struct sfinae { typedef yes_type type; };  
-        template <class U>  
-        static typename sfinae<&U::operator=>::type test(int);  
-        template <class U>  
-        static no_type test(...);  
-    public:  
-        enum {value = sizeof(test<T>(1)) == sizeof(yes_type)};  
-    };
- };  
-
-/*************************************************************************************************/
-
-template<typename T>
-struct has_move_assign : boost::mpl::and_<boost::is_class<T>, class_has_move_assign<T> > {};
-
-/*************************************************************************************************/
-
-class test_can_convert_anything { };
-
-/*************************************************************************************************/
-
-#endif // BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
-
-/*************************************************************************************************/
-
-/*
-    REVISIT (sparent_at_[hidden]): This is a work around for Boost 1.34.1 and VC++ 2008 where
-    boost::is_convertible<T, T> fails to compile.
-*/
-
-template <typename T, typename U>
-struct is_convertible : boost::mpl::or_<
-    boost::is_same<T, U>,
-    boost::is_convertible<T, U>
-> { };
-
-/*************************************************************************************************/
-
-} //namespace move_detail
-
-
-/*************************************************************************************************/
-
-/*!
-\ingroup move_related
-\brief move_from is used for move_ctors.
-*/
-
-template <typename T>
-struct move_from
-{
-    explicit move_from(T& x) : source(x) { }
-    T& source;
-private:
-    move_from& operator=(move_from const&);
-};
-
-/*************************************************************************************************/
-
-#if !defined(BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN)
-
-/*************************************************************************************************/
-
-/*!
-\ingroup move_related
-\brief The is_movable trait can be used to identify movable types.
-*/
-template <typename T>
-struct is_movable : boost::mpl::and_<
-                        boost::is_convertible<move_from<T>, T>,
-                        move_detail::has_move_assign<T>,
-                        boost::mpl::not_<boost::is_convertible<move_detail::test_can_convert_anything, T> >
-                    > { };
-
-/*************************************************************************************************/
-
-#else // BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
-
-// On compilers which don't have adequate SFINAE support, treat most types as unmovable,
-// unless the trait is specialized.
-
-template <typename T>
-struct is_movable : boost::mpl::false_ { };
-
-#endif
-
-/*************************************************************************************************/
-
-#if !defined(BOOST_NO_SFINAE)
-
-/*************************************************************************************************/
-
-/*!
-\ingroup move_related
-\brief copy_sink and move_sink are used to select between overloaded operations according to
- whether type T is movable and convertible to type U.
-\sa move
-*/
-
-template <typename T,
-          typename U = T,
-          typename R = void*>
-struct copy_sink : boost::enable_if<
-                        boost::mpl::and_<
-                            boost::unordered_detail::move_detail::is_convertible<T, U>,                           
-                            boost::mpl::not_<is_movable<T> >
-                        >,
-                        R
-                    >
-{ };
-
-/*************************************************************************************************/
-
-/*!
-\ingroup move_related
-\brief move_sink and copy_sink are used to select between overloaded operations according to
- whether type T is movable and convertible to type U.
- \sa move
-*/
-
-template <typename T,
-          typename U = T,
-          typename R = void*>
-struct move_sink : boost::enable_if<
-                        boost::mpl::and_<
-                            boost::unordered_detail::move_detail::is_convertible<T, U>,                            
-                            is_movable<T>
-                        >,
-                        R
-                    >
-{ };
-
-/*************************************************************************************************/
-
-/*!
-\ingroup move_related
-\brief This version of move is selected when T is_movable . It in turn calls the move
-constructor. This call, with the help of the return value optimization, will cause x to be moved
-instead of copied to its destination. See adobe/test/move/main.cpp for examples.
-
-*/
-template <typename T>
-T move(T& x, typename move_sink<T>::type = 0) { return T(move_from<T>(x)); }
-
-/*************************************************************************************************/
-
-/*!
-\ingroup move_related
-\brief This version of move is selected when T is not movable . The net result will be that
-x gets copied.
-*/
-template <typename T>
-T& move(T& x, typename copy_sink<T>::type = 0) { return x; }
-
-/*************************************************************************************************/
-
-#else // BOOST_NO_SFINAE
-
-// On compilers without SFINAE, define copy_sink to always use the copy function.
-
-template <typename T,
-          typename U = T,
-          typename R = void*>
-struct copy_sink
-{
-    typedef R type;
-};
-
-// Always copy the element unless this is overloaded.
-
-template <typename T>
-T& move(T& x) {
-    return x;
-}
-
-#endif // BOOST_NO_SFINAE
-
-} // namespace unordered_detail
-} // namespace boost
-
-/*************************************************************************************************/
-
-#endif
-
-/*************************************************************************************************/
Modified: branches/release/boost/unordered/detail/node.hpp
==============================================================================
--- branches/release/boost/unordered/detail/node.hpp	(original)
+++ branches/release/boost/unordered/detail/node.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -1,6 +1,6 @@
 
 // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
-// Copyright (C) 2005-2009 Daniel James
+// Copyright (C) 2005-2011 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)
 
@@ -11,10 +11,7 @@
 #ifndef BOOST_UNORDERED_DETAIL_NODE_HPP_INCLUDED
 #define BOOST_UNORDERED_DETAIL_NODE_HPP_INCLUDED
 
-#include <boost/config.hpp>
-#include <boost/assert.hpp>
-#include <boost/detail/workaround.hpp>
-#include <boost/unordered/detail/fwd.hpp>
+#include <boost/unordered/detail/util.hpp>
 
 #if BOOST_WORKAROUND(__BORLANDC__, <= 0X0582)
 #define BOOST_UNORDERED_BORLAND_BOOL(x) (bool)(x)
@@ -22,205 +19,348 @@
 #define BOOST_UNORDERED_BORLAND_BOOL(x) x
 #endif
 
-namespace boost { namespace unordered_detail {
+namespace boost { namespace unordered { namespace detail {
+
+    // Some forward declarations for buckets and tables
+    
+    template <typename T> class table;
+    template <class A, bool Unique> class buckets;
 
     ////////////////////////////////////////////////////////////////////////////
-    // ungrouped node implementation
+    //
+    // This section implements buckets and nodes. Here's a rough
+    // inheritance diagram, to show how they pull together.
+    //
+    // For unordered_set/unordered_map:
+    //
+    //  bucket<A>              value_base<allocator_traits<A>::value_type>
+    //     |                            |
+    //     +--------------+-------------+
+    //                    |
+    //             ungrouped_node<A>
+    //
+    // For unordered_multiset/unordered_multimap:
+    //
+    //  bucket<A>              value_base<allocator_traits<A>::value_type>
+    //     |                            |
+    //     +--------------+-------------+
+    //                    |
+    //              grouped_node<A>
+
+    // bucket
+    //
+    // bucket is used for both the buckets and as a base class for
+    // nodes. By using 'bucket_ptr' for 'node_ptr', 'next_' can point
+    // to either a bucket or a node. This is used later to implement a
+    // sentinel at the end of the bucket array.
     
     template <class A>
-    inline BOOST_DEDUCED_TYPENAME ungrouped_node_base<A>::node_ptr&
-        ungrouped_node_base<A>::next_group(node_ptr ptr)
+    class bucket
     {
-        return ptr->next_;
-    }
+        bucket& operator=(bucket const&);
+    public:
+        typedef BOOST_DEDUCED_TYPENAME
+            ::boost::unordered::detail::rebind_wrap<A, bucket>::type
+            bucket_allocator;
+        typedef BOOST_DEDUCED_TYPENAME
+            allocator_traits<bucket_allocator>::pointer bucket_ptr;
+        typedef bucket_ptr node_ptr;
+    
+        node_ptr next_;
 
-    template <class A>
-    inline std::size_t ungrouped_node_base<A>::group_count(node_ptr)
-    {
-        return 1;
-    }
+        bucket() : next_() {}
+    };
 
-    template <class A>
-    inline void ungrouped_node_base<A>::add_to_bucket(node_ptr n, bucket& b)
-    {
-        n->next_ = b.next_;
-        b.next_ = n;
-    }
+    // The space used to store values in a node.
 
-    template <class A>
-    inline void ungrouped_node_base<A>::add_after_node(node_ptr n,
-        node_ptr position)
-    {
-        n->next_ = position->next_;
-        position->next_ = position;
-    }
-    
-    template <class A>
-    inline void ungrouped_node_base<A>::unlink_nodes(bucket& b,
-        node_ptr begin, node_ptr end)
+    template <class ValueType>
+    struct value_base
     {
-        node_ptr* pos = &b.next_;
-        while(*pos != begin) pos = &(*pos)->next_;
-        *pos = end;
-    }
+        typedef ValueType value_type;
+        BOOST_DEDUCED_TYPENAME ::boost::aligned_storage<
+            sizeof(value_type),
+            ::boost::alignment_of<value_type>::value>::type data_;
 
-    template <class A>
-    inline void ungrouped_node_base<A>::unlink_nodes(bucket& b, node_ptr end)
-    {
-        b.next_ = end;
-    }
+        void* address() {
+            return this;
+        }
+        value_type& value() {
+            return *(ValueType*) this;
+        }
+        value_type* value_ptr() {
+            return (ValueType*) this;
+        }
+    private:
+        value_base& operator=(value_base const&);
+    };
 
-    template <class A>
-    inline void ungrouped_node_base<A>::unlink_node(bucket& b, node_ptr n)
-    {
-        unlink_nodes(b, n, n->next_);
-    }
+    // In containers with equivalent keys (unordered_multimap and
+    // unordered_multiset) equivalent nodes are grouped together, in
+    // containers with unique keys (unordered_map and unordered_set)
+    // individual nodes are treated as groups of one. The following two
+    // classes implement the data structure.
 
-    ////////////////////////////////////////////////////////////////////////////
-    // 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>::next_group(node_ptr ptr)
-    {
-        return get(ptr).group_prev_->next_;
-    }
+    // This is used for containers with unique keys. There are no groups
+    // so it doesn't add any extra members, and just treats individual
+    // nodes as groups of one.
 
     template <class A>
-    inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr
-        grouped_node_base<A>::first_in_group(node_ptr ptr)
+    struct ungrouped_node
+      : ::boost::unordered::detail::bucket<A>,
+        value_base<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>
     {
-        while(next_group(ptr) == ptr)
-            ptr = get(ptr).group_prev_;
-        return ptr;
-    }
+        typedef ::boost::unordered::detail::bucket<A> bucket;
+        typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
+        typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
+        typedef BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type value_type;
 
-    template <class A>
-    inline std::size_t grouped_node_base<A>::group_count(node_ptr ptr)
-    {
-        node_ptr start = ptr;
-        std::size_t size = 0;
-        do {
-            ++size;
-            ptr = get(ptr).group_prev_;
-        } while(ptr != start);
-        return size;
-    }
+        std::size_t hash_;
 
-    template <class A>
-    inline void grouped_node_base<A>::add_to_bucket(node_ptr n, bucket& b)
-    {
-        n->next_ = b.next_;
-        get(n).group_prev_ = n;
-        b.next_ = n;
-    }
+        ungrouped_node() : bucket() {}
 
-    template <class A>
-    inline void grouped_node_base<A>::add_after_node(node_ptr n, node_ptr pos)
-    {
-        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
-    // of the second group (if split is at the beginning then don't
-    // split).
-    template <class A>
-    inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr
-        grouped_node_base<A>::split_group(node_ptr split)
-    {
-        node_ptr first = first_in_group(split);
-        if(first == split) return split;
+        void init(node_ptr) {}
+
+        static node_ptr next_group(node_ptr ptr)
+        {
+            return ptr->next_;
+        }
+
+        static node_ptr next_group2(node_ptr ptr)
+        {
+            return ptr->next_;
+        }
+
+        static std::size_t group_count(node_ptr n)
+        {
+            return !n ? 0 : 1;
+        }
+
+        static void add_after_node(node_ptr n, node_ptr position)
+        {
+            n->next_ = position->next_;
+            position->next_ = position;            
+        }
+
+        static node_ptr unlink_node(bucket& b, node_ptr n)
+        {
+            return unlink_nodes(b, n, n->next_);
+        }
+
+        static node_ptr unlink_nodes(bucket& b, node_ptr begin, node_ptr end)
+        {
+            node_ptr prev = b.next_;
+            while(prev->next_ != begin) prev = prev->next_;
+            prev->next_ = end;
+            return prev;
+        }
+        
+        static std::size_t get_hash(node_ptr p)
+        {
+            return static_cast<ungrouped_node&>(*p).hash_;
+        }
+
+        static void set_hash(node_ptr p, std::size_t hash)
+        {
+            static_cast<ungrouped_node&>(*p).hash_ = hash;
+        }
+
+        static value_type& get_value(node_ptr p)
+        {
+            return static_cast<ungrouped_node&>(*p).value();
+        }
 
-        node_ptr last = get(first).group_prev_;
-        get(first).group_prev_ = get(split).group_prev_;
-        get(split).group_prev_ = last;
+        static value_type* get_value_ptr(node_ptr p)
+        {
+            return static_cast<ungrouped_node&>(*p).value_ptr();
+        }
+    };
 
-        return first;
-    }
+    // This is used for containers with equivalent keys. It implements a
+    // circular list running in the opposite direction to the linked
+    // list through the nodes.
 
     template <class A>
-    void grouped_node_base<A>::unlink_node(bucket& b, node_ptr n)
+    struct grouped_node
+      : ::boost::unordered::detail::bucket<A>,
+        value_base<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>
     {
-        node_ptr next = n->next_;
-        node_ptr* pos = &next_group(n);
+        typedef ::boost::unordered::detail::bucket<A> bucket;
+        typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
+        typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
+        typedef BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type value_type;
+
+        std::size_t hash_;
+        node_ptr group_prev_;
+
+        grouped_node() : bucket(), group_prev_() {}
+        void init(node_ptr n)
+        {
+            group_prev_ = n;
+        }
+
+        static node_ptr next_group(node_ptr ptr)
+        {
+            return get(ptr).group_prev_->next_;
+        }
+
+        static node_ptr next_group2(node_ptr ptr)
+        {
+            return get(ptr->next_).group_prev_;
+        }
+
+        static std::size_t group_count(node_ptr ptr)
+        {
+            if (!ptr) return 0;
 
-        if(*pos != n) {
-            // The node is at the beginning of a group.
+            node_ptr start = ptr;
+            std::size_t size = 0;
+            do {
+                ++size;
+                ptr = get(ptr).group_prev_;
+            } while(ptr != start);
+            return size;
+        }
 
-            // Find the previous node pointer:
-            pos = &b.next_;
-            while(*pos != n) pos = &next_group(*pos);
+        static void add_after_node(node_ptr n, node_ptr pos)
+        {
+            n->next_ = get(pos).group_prev_->next_;
+            get(n).group_prev_ = get(pos).group_prev_;
+            get(pos).group_prev_->next_ = n;
+            get(pos).group_prev_ = n;
+        }
 
-            // Remove from group
-            if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
+        static node_ptr unlink_node(bucket& b, node_ptr n)
+        {
+            node_ptr next = n->next_;
+            node_ptr prev = get(n).group_prev_;
+    
+            if(prev->next_ != n) {
+                // The node is at the beginning of a group.
+    
+                // Find the previous node pointer:
+                prev = b.next_;
+                while(prev->next_ != n) {
+                    prev = next_group2(prev);
+                }
+    
+                // Remove from group
+                if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
+                    get(next).group_prev_ == n)
+                {
+                    get(next).group_prev_ = get(n).group_prev_;
+                }
+            }
+            else if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
                 get(next).group_prev_ == n)
             {
+                // The deleted node is not at the end of the group, so
+                // change the link from the next node.
                 get(next).group_prev_ = get(n).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 = get(n).group_prev_;
+                while(get(x).group_prev_ != n) {
+                    x = get(x).group_prev_;
+                }
+                get(x).group_prev_ = get(n).group_prev_;
+            }
+            prev->next_ = next;
+    
+            return prev;
         }
-        else if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
-            get(next).group_prev_ == n)
+
+        static node_ptr unlink_nodes(bucket& b, node_ptr begin, node_ptr end)
         {
-            // The deleted node is not at the end of the group, so
-            // change the link from the next node.
-            get(next).group_prev_ = get(n).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 = get(n).group_prev_;
-            while(get(x).group_prev_ != n) {
-                x = get(x).group_prev_;
+            node_ptr prev = get(begin).group_prev_;
+    
+            if(prev->next_ != begin) {
+                // The node is at the beginning of a group.
+    
+                // Find the previous node pointer:
+                prev = b.next_;
+                while(prev->next_ != begin) prev = next_group2(prev);
+    
+                if(BOOST_UNORDERED_BORLAND_BOOL(end)) split_group(end);
+            }
+            else {
+                node_ptr group1 = split_group(begin);
+                if(BOOST_UNORDERED_BORLAND_BOOL(end)) {
+                    node_ptr group2 = split_group(end);
+    
+                    if(begin == group2) {
+                        node_ptr end1 = get(group1).group_prev_;
+                        node_ptr end2 = get(group2).group_prev_;
+                        get(group1).group_prev_ = end2;
+                        get(group2).group_prev_ = end1;
+                    }
+                }
             }
-            get(x).group_prev_ = get(n).group_prev_;
+    
+            prev->next_ = end;
+    
+            return prev;
         }
-        *pos = next;
-    }
 
-    template <class A>
-    void grouped_node_base<A>::unlink_nodes(bucket& b,
-        node_ptr begin, node_ptr end)
-    {
-        node_ptr* pos = &next_group(begin);
+        // Break a ciruclar list into two, with split as the beginning
+        // of the second group (if split is at the beginning then don't
+        // split).
+        static node_ptr split_group(node_ptr split)
+        {
+            // Find first node in group.
+            node_ptr first = split;
+            while(next_group(first) == first)
+                first = get(first).group_prev_;
 
-        if(*pos != begin) {
-            // The node is at the beginning of a group.
+            if(first == split) return split;
+    
+            node_ptr last = get(first).group_prev_;
+            get(first).group_prev_ = get(split).group_prev_;
+            get(split).group_prev_ = last;
+    
+            return first;
+        }
 
-            // Find the previous node pointer:
-            pos = &b.next_;
-            while(*pos != begin) pos = &next_group(*pos);
-
-            // Remove from group
-            if(BOOST_UNORDERED_BORLAND_BOOL(end)) split_group(end);
-        }
-        else {
-            node_ptr group1 = split_group(begin);
-            if(BOOST_UNORDERED_BORLAND_BOOL(end)) {
-                node_ptr group2 = split_group(end);
-
-                if(begin == group2) {
-                    node_ptr end1 = get(group1).group_prev_;
-                    node_ptr end2 = get(group2).group_prev_;
-                    get(group1).group_prev_ = end2;
-                    get(group2).group_prev_ = end1;
-                }
-            }
+        static std::size_t get_hash(node_ptr p) {
+            return static_cast<grouped_node&>(*p).hash_;
+        }
+        static void set_hash(node_ptr p, std::size_t hash) {
+            static_cast<grouped_node&>(*p).hash_ = hash;
+        }
+        static value_type& get_value(node_ptr p) {
+            return static_cast<grouped_node&>(*p).value();
+        }
+        static value_type* get_value_ptr(node_ptr p) {
+            return static_cast<grouped_node&>(*p).value_ptr();
         }
-        *pos = end;
-    }
 
-    template <class A>
-    void grouped_node_base<A>::unlink_nodes(bucket& b, node_ptr end)
+        static grouped_node& get(node_ptr ptr) {
+            return static_cast<grouped_node&>(*ptr);
+        }
+    };
+
+    // These two classes implement an easy way to pass around the node
+    // group policy classes without the messy template parameters.
+    // Whenever you see the template parameter 'G' it's one of these.
+
+    struct ungrouped
     {
-        split_group(end);
-        b.next_ = end;
-    }
-}}
+        template <class A>
+        struct node {
+            typedef ungrouped_node<A> type;
+        };
+    };
+
+    struct grouped
+    {
+        template <class A>
+        struct node {
+            typedef grouped_node<A> type;
+        };
+    };
+
+}}}
 
 #endif
Modified: branches/release/boost/unordered/detail/table.hpp
==============================================================================
--- branches/release/boost/unordered/detail/table.hpp	(original)
+++ branches/release/boost/unordered/detail/table.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -1,444 +1,434 @@
 
 // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
-// Copyright (C) 2005-2009 Daniel James
+// Copyright (C) 2005-2011 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_ALL_HPP_INCLUDED
 #define BOOST_UNORDERED_DETAIL_ALL_HPP_INCLUDED
 
-#include <cstddef>
-#include <stdexcept>
-#include <algorithm>
-#include <boost/config/no_tr1/cmath.hpp>
-#include <boost/iterator/iterator_categories.hpp>
-#include <boost/throw_exception.hpp>
-
 #include <boost/unordered/detail/buckets.hpp>
 
-namespace boost { namespace unordered_detail {
+namespace boost { namespace unordered { namespace detail {
 
-    ////////////////////////////////////////////////////////////////////////////
-    // Helper methods
+    // This implements almost all of the required functionality, apart
+    // from some things that are specific to containers with unique and
+    // equivalent keys which is implemented in unique_table and
+    // equivalent_table. See unique.hpp and equivalent.hpp for
+    // their declaration and implementation.
+
+    template <class T>
+    class table : public T::buckets, public T::functions
+    {
+        table(table const&);
+        table& operator=(table const&);
+    public:
+        typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
+        typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
+        typedef BOOST_DEDUCED_TYPENAME T::value_allocator value_allocator;
+        typedef BOOST_DEDUCED_TYPENAME T::key_type key_type;
+        typedef BOOST_DEDUCED_TYPENAME T::value_type value_type;
+        typedef BOOST_DEDUCED_TYPENAME T::functions functions;
+        typedef BOOST_DEDUCED_TYPENAME T::buckets buckets;
+        typedef BOOST_DEDUCED_TYPENAME T::extractor extractor;
+        typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor;
+
+        typedef BOOST_DEDUCED_TYPENAME T::node node;
+        typedef BOOST_DEDUCED_TYPENAME T::bucket bucket;
+        typedef BOOST_DEDUCED_TYPENAME T::node_ptr node_ptr;
+        typedef BOOST_DEDUCED_TYPENAME T::bucket_ptr bucket_ptr;
+        typedef BOOST_DEDUCED_TYPENAME T::node_allocator node_allocator;
+        typedef BOOST_DEDUCED_TYPENAME T::iterator_pair iterator_pair;
 
-    // strong exception safety, no side effects
-    template <class T>
-    inline bool hash_table<T>::equal(
-        key_type const& k, value_type const& v) const
-    {
-        return this->key_eq()(k, get_key(v));
-    }
+        // Members
+        
+        float mlf_;
+        std::size_t max_load_; // Only use if this->buckets_.
 
-    // strong exception safety, no side effects
-    template <class T>
-    template <class Key, class Pred>
-    inline BOOST_DEDUCED_TYPENAME T::node_ptr
-        hash_table<T>::find_iterator(bucket_ptr bucket, Key const& k,
-            Pred const& eq) const
-    {
-        node_ptr it = bucket->next_;
-        while (BOOST_UNORDERED_BORLAND_BOOL(it) &&
-            !eq(k, get_key(node::get_value(it))))
-        {
-            it = node::next_group(it);
-        }
+        // Helper methods
 
-        return it;
-    }
+        key_type const& get_key(value_type const& v) const {
+            return extractor::extract(v);
+        }
 
-    // strong exception safety, no side effects
-    template <class T>
-    inline BOOST_DEDUCED_TYPENAME T::node_ptr
-        hash_table<T>::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)))
+    private:
+        // pre: this->buckets_ != null
+        template <class Key, class Pred>
+        node_ptr find_node_impl(
+                std::size_t bucket_index,
+                std::size_t hash,
+                Key const& k,
+                Pred const& eq) const
         {
-            it = node::next_group(it);
+            node_ptr n = this->buckets_[bucket_index].next_;
+            if (!n) return n;
+            n = n->next_;
+    
+            for (;;)
+            {
+                if (!n) return n;
+                std::size_t node_hash = node::get_hash(n);
+                if (hash == node_hash)
+                {
+                    if (eq(k, get_key(node::get_value(n))))
+                        return n;
+                }
+                else
+                {
+                    if (node_hash % this->bucket_count_ != bucket_index)
+                        return node_ptr();
+                }
+                n = node::next_group(n);
+            }
         }
 
-        return it;
-    }
-
-    // strong exception safety, no side effects
-    // pre: this->buckets_
-    template <class T>
-    inline BOOST_DEDUCED_TYPENAME T::node_ptr
-        hash_table<T>::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 T>
-    inline BOOST_DEDUCED_TYPENAME T::node_ptr*
-        hash_table<T>::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)))
+    public:
+        template <class Key, class Hash, class Pred>
+        node_ptr generic_find_node(
+                Key const& k,
+                Hash const& hash_function,
+                Pred const& eq) const
         {
-            it = &node::next_group(*it);
+            if (!this->size_) return node_ptr();
+            std::size_t hash = hash_function(k);
+            return this->find_node_impl(hash % this->bucket_count_, hash, k, eq);
+        }
+        
+        node_ptr find_node(
+                std::size_t bucket_index,
+                std::size_t hash,
+                key_type const& k) const
+        {
+            if (!this->size_) return node_ptr();
+            return this->find_node_impl(bucket_index, hash, k, this->key_eq());
         }
 
-        return it;
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Load methods
-
-    // no throw
-    template <class T>
-    std::size_t hash_table<T>::max_size() const
-    {
-        using namespace std;
-
-        // size < mlf_ * count
-        return double_to_size_t(ceil(
-                (double) this->mlf_ * this->max_bucket_count())) - 1;
-    }
-
-    // strong safety
-    template <class T>
-    inline std::size_t hash_table<T>::bucket_index(
-        key_type const& k) const
-    {
-        // hash_function can throw:
-        return this->hash_function()(k) % this->bucket_count_;
-    }
-
-
-    // no throw
-    template <class T>
-    inline std::size_t hash_table<T>::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 T>
-    void hash_table<T>::max_load_factor(float z)
-    {
-        BOOST_ASSERT(z > 0);
-        mlf_ = (std::max)(z, minimum_max_load_factor);
-        this->max_load_ = this->calculate_max_load();
-    }
-
-    // no throw
-    template <class T>
-    inline std::size_t hash_table<T>::min_buckets_for_size(
-        std::size_t size) const
-    {
-        BOOST_ASSERT(this->mlf_ != 0);
+        node_ptr find_node(key_type const& k) const
+        {
+            if (!this->size_) return node_ptr();
+            std::size_t hash = this->hash_function()(k);
+            return this->find_node_impl(hash % this->bucket_count_, hash, k,
+                this->key_eq());
+        }
 
-        using namespace std;
+        node_ptr find_matching_node(node_ptr n) const
+        {
+            // For some stupid reason, I decided to support equality comparison
+            // when different hash functions are used. So I can't use the hash
+            // value from the node here.
+    
+            return find_node(get_key(node::get_value(n)));
+        }
 
-        // From 6.3.1/13:
-        // size < mlf_ * count
-        // => count > size / mlf_
-        //
-        // Or from rehash post-condition:
-        // count > size / mlf_
-        return next_prime(double_to_size_t(floor(size / (double) mlf_)) + 1);
-    }
+        ////////////////////////////////////////////////////////////////////////
+        // Load methods
 
-    ////////////////////////////////////////////////////////////////////////////
-    // recompute_begin_bucket
+        std::size_t max_size() const
+        {
+            using namespace std;
+    
+            // size < mlf_ * count
+            return double_to_size_t(ceil(
+                    static_cast<double>(this->mlf_) *
+                    static_cast<double>(this->max_bucket_count())
+                )) - 1;
+        }
 
-    // init_buckets
+        std::size_t calculate_max_load()
+        {
+            using namespace std;
+    
+            // From 6.3.1/13:
+            // Only resize when size >= mlf_ * count
+            return double_to_size_t(ceil(
+                    static_cast<double>(this->mlf_) *
+                    static_cast<double>(this->bucket_count_)
+                ));
 
-    template <class T>
-    inline void hash_table<T>::init_buckets()
-    {
-        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();
-    }
 
-    // After an erase cached_begin_bucket_ might be left pointing to
-    // an empty bucket, so this is called to update it
-    //
-    // no throw
+        void max_load_factor(float z)
+        {
+            BOOST_ASSERT(z > 0);
+            mlf_ = (std::max)(z, minimum_max_load_factor);
+            if (BOOST_UNORDERED_BORLAND_BOOL(this->buckets_))
+                this->max_load_ = this->calculate_max_load();
+        }
 
-    template <class T>
-    inline void hash_table<T>::recompute_begin_bucket(bucket_ptr b)
-    {
-        BOOST_ASSERT(!(b < this->cached_begin_bucket_));
+        std::size_t min_buckets_for_size(std::size_t size) const
+        {
+            BOOST_ASSERT(this->mlf_ != 0);
+    
+            using namespace std;
+    
+            // From 6.3.1/13:
+            // size < mlf_ * count
+            // => count > size / mlf_
+            //
+            // Or from rehash post-condition:
+            // count > size / mlf_
+            return next_prime(double_to_size_t(floor(size / (double) mlf_)) + 1);
+        }
+
+        ////////////////////////////////////////////////////////////////////////
+        // Constructors
+
+        table(std::size_t num_buckets,
+                hasher const& hf,
+                key_equal const& eq,
+                node_allocator const& a)
+          : buckets(a, next_prime(num_buckets)),
+            functions(hf, eq),
+            mlf_(1.0f),
+            max_load_(0)
+        {
+        }
 
-        if(b == this->cached_begin_bucket_)
+        table(table const& x, node_allocator const& a)
+          : buckets(a, x.min_buckets_for_size(x.size_)),
+            functions(x),
+            mlf_(x.mlf_),
+            max_load_(0)
         {
-            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_);
+            if(x.size_) {
+                x.copy_buckets_to(*this);
+                this->max_load_ = calculate_max_load();
             }
         }
-    }
-
-    // This is called when a range has been erased
-    //
-    // no throw
 
-    template <class T>
-    inline void hash_table<T>::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_));
+        table(table& x, move_tag m)
+          : buckets(x, m),
+            functions(x),
+            mlf_(x.mlf_),
+            max_load_(calculate_max_load()) {}
+
+        // TODO: Why do I use x's bucket count?
+        table(table& x, node_allocator const& a, move_tag m)
+          : buckets(a, x.bucket_count_),
+            functions(x),
+            mlf_(x.mlf_),
+            max_load_(x.max_load_)
+        {
+            if(a == x.node_alloc()) {
+                this->buckets::swap(x, false_type());
+            }
+            else if(x.size_) {
+                // Use a temporary table because move_buckets_to leaves the
+                // source container in a complete mess.
+                buckets tmp(x, m);
+                tmp.move_buckets_to(*this);
+                this->max_load_ = calculate_max_load();
+            }
+        }
 
-        if(b1 == this->cached_begin_bucket_ && !b1->next_)
-            this->cached_begin_bucket_ = b2;
-    }
+        ~table()
+        {}
 
-    // no throw
-    template <class T>
-    inline float hash_table<T>::load_factor() const
-    {
-        BOOST_ASSERT(this->bucket_count_ != 0);
-        return static_cast<float>(this->size_)
-            / static_cast<float>(this->bucket_count_);
-    }
+        // Iterators
 
-    ////////////////////////////////////////////////////////////////////////////
-    // Constructors
+        node_ptr begin() const {
+            return !this->buckets_ ?
+                node_ptr() : this->buckets_[this->bucket_count_].next_;
+        }
 
-    template <class T>
-    hash_table<T>::hash_table(std::size_t num_buckets,
-        hasher const& hf, key_equal const& eq, node_allocator const& a)
-      : buckets(a, next_prime(num_buckets)),
-        base(hf, eq),
-        size_(),
-        mlf_(1.0f),
-        cached_begin_bucket_(),
-        max_load_(0)
-    {
-    }
+        void assign(table const& x)
+        {
+            assign(x, integral_constant<bool,
+                allocator_traits<node_allocator>::
+                propagate_on_container_copy_assignment::value>());
+        }
 
-    // Copy Construct with allocator
+        void assign(table const& x, false_type)
+        {
+            table tmp(x, this->node_alloc());
+            this->swap(tmp, false_type());
+        }
 
-    template <class T>
-    hash_table<T>::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();
+        void assign(table const& x, true_type)
+        {
+            table tmp(x, x.node_alloc());
+            // Need to delete before setting the allocator so that buckets
+            // aren't deleted with the wrong allocator.
+            if(this->buckets_) this->delete_buckets();
+            // TODO: Can allocator assignment throw?
+            this->allocators_.assign(x.allocators_);
+            this->swap(tmp, false_type());
         }
-    }
 
-    // Move Construct
+        void move_assign(table& x)
+        {
+            move_assign(x, integral_constant<bool,
+                allocator_traits<node_allocator>::
+                propagate_on_container_move_assignment::value>());
+        }
+        
+        void move_assign(table& x, true_type)
+        {
+            if(this->buckets_) this->delete_buckets();
+            this->allocators_.move_assign(x.allocators_);
+            move_assign_no_alloc(x);
+        }
 
-    template <class T>
-    hash_table<T>::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);
-    }
+        void move_assign(table& x, false_type)
+        {
+            if(this->node_alloc() == x.node_alloc()) {
+                if(this->buckets_) this->delete_buckets();
+                move_assign_no_alloc(x);
+            }
+            else {
+                set_hash_functions<hasher, key_equal> new_func_this(*this, x);
 
-    template <class T>
-    hash_table<T>::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(a == x.node_alloc()) {
-            this->partial_swap(x);
+                if (x.size_) {
+                    buckets b(this->node_alloc(), x.min_buckets_for_size(x.size_));
+                    buckets tmp(x, move_tag());
+                    tmp.move_buckets_to(b);
+                    b.swap(*this);
+                }
+                else {
+                    this->clear();
+                }
+                
+                this->mlf_ = x.mlf_;
+                if (this->buckets_) this->max_load_ = calculate_max_load();
+                new_func_this.commit();
+            }
         }
-        else if(x.size_) {
-            x.copy_buckets_to(*this);
-            this->size_ = x.size_;
-            this->init_buckets();
+        
+        void move_assign_no_alloc(table& x)
+        {
+            set_hash_functions<hasher, key_equal> new_func_this(*this, x);
+            // No throw from here.
+            this->move_buckets_from(x);
+            this->mlf_ = x.mlf_;
+            this->max_load_ = x.max_load_;
+            new_func_this.commit();
         }
-    }
 
-    template <class T>
-    hash_table<T>& hash_table<T>::operator=(
-        hash_table const& x)
-    {
-        hash_table tmp(x, this->node_alloc());
-        this->fast_swap(tmp);
-        return *this;
-    }
+        ////////////////////////////////////////////////////////////////////////
+        // Swap & Move
 
-    ////////////////////////////////////////////////////////////////////////////
-    // Swap & Move
-    
-    // Swap
-    //
-    // Strong exception safety
-    //
-    // Can throw if hash or predicate object's copy constructor throws
-    // or if allocators are unequal.
-
-    template <class T>
-    inline void hash_table<T>::partial_swap(hash_table& x)
-    {
-        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_);
-    }
+        void swap(table& x)
+        {
+            swap(x, integral_constant<bool,
+                    allocator_traits<node_allocator>::
+                    propagate_on_container_swap::value>());
+        }
 
-    template <class T>
-    inline void hash_table<T>::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.
+        // Only swaps the allocators if Propagate::value
+        template <typename Propagate>
+        void swap(table& x, Propagate p)
         {
             set_hash_functions<hasher, key_equal> op1(*this, x);
             set_hash_functions<hasher, key_equal> op2(x, *this);
+            // I think swap can throw if Propagate::value,
+            // since the allocators' swap can throw. Not sure though.
+            this->buckets::swap(x, p);
+            std::swap(this->mlf_, x.mlf_);
+            std::swap(this->max_load_, x.max_load_);
             op1.commit();
             op2.commit();
         }
-        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 T>
-    inline void hash_table<T>::slow_swap(hash_table& x)
-    {
-        if(this == &x) return;
 
+        // Swap everything but the allocators, and the functions objects.
+        void swap_contents(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.
-            set_hash_functions<hasher, key_equal> op1(*this, x);
-            set_hash_functions<hasher, key_equal> 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 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.
-        
-            b1.swap(*this);
-            b2.swap(x);
-            op1.commit();
-            op2.commit();
+            this->buckets::swap(x, false_type());
+            std::swap(this->mlf_, x.mlf_);
+            std::swap(this->max_load_, x.max_load_);
         }
-        
-        std::swap(this->size_, x.size_);
 
-        if(this->buckets_) this->init_buckets();
-        if(x.buckets_) x.init_buckets();
-    }
+        ////////////////////////////////////////////////////////////////////////
+        // Key methods
 
-    template <class T>
-    void hash_table<T>::swap(hash_table& x)
-    {
-        if(this->node_alloc() == x.node_alloc()) {
-            if(this != &x) this->fast_swap(x);
+        std::size_t count(key_type const& k) const
+        {
+            if(!this->size_) return 0;
+            return node::group_count(find_node(k));
         }
-        else {
-            this->slow_swap(x);
+
+        value_type& at(key_type const& k) const
+        {
+            if (this->size_) {
+                node_ptr it = find_node(k);
+                if (BOOST_UNORDERED_BORLAND_BOOL(it))
+                    return node::get_value(it);
+            }
+    
+            ::boost::throw_exception(
+                std::out_of_range("Unable to find key in unordered_map."));
         }
-    }
 
+        iterator_pair equal_range(key_type const& k) const
+        {
+            if(!this->size_)
+                return iterator_pair(node_ptr(), node_ptr());
     
-    // Move
-    //
-    // Strong exception safety (might change unused function objects)
-    //
-    // Can throw if hash or predicate object's copy constructor throws
-    // or if allocators are unequal.
+            node_ptr ptr = find_node(k);
+            return iterator_pair(ptr, !ptr ? ptr : node::next_group(ptr));
+        }
 
-    template <class T>
-    void hash_table<T>::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.
-        set_hash_functions<hasher, key_equal> 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;
+        // Erase
+        //
+        // no throw
+
+        std::size_t erase_key(key_type const& k)
+        {
+            if(!this->size_) return 0;
+    
+            std::size_t hash = this->hash_function()(k);
+            std::size_t bucket_index = hash % this->bucket_count_;
+            bucket_ptr bucket = this->get_bucket(bucket_index);
+    
+            node_ptr prev = bucket->next_;
+            if (!prev) return 0;
+    
+            for (;;)
+            {
+                if (!prev->next_) return 0;
+                std::size_t node_hash = node::get_hash(prev->next_);
+                if (node_hash % this->bucket_count_ != bucket_index)
+                    return 0;
+                if (node_hash == hash &&
+                    this->key_eq()(k, get_key(node::get_value(prev->next_))))
+                    break;
+                prev = node::next_group2(prev);
+            }
+    
+            node_ptr pos = prev->next_;
+            node_ptr end = node::next_group(pos);
+            prev->next_ = end;
+            this->fix_buckets(bucket, prev, end);
+            return this->delete_nodes(pos, end);
         }
-        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 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->size_ = x.size_;
-            b.swap(*this);
-            this->init_buckets();
-        }
-
-        // We've made it, the rest is no throw.
-        this->mlf_ = x.mlf_;
-        new_func_this.commit();
-    }
+
+        // Reserve and rehash
+
+        bool reserve_for_insert(std::size_t);
+        void rehash(std::size_t);
+    };
     
     ////////////////////////////////////////////////////////////////////////////
     // Reserve & Rehash
 
     // basic exception safety
     template <class T>
-    inline void hash_table<T>::create_for_insert(std::size_t size)
+    inline bool table<T>::reserve_for_insert(std::size_t size)
     {
-        this->bucket_count_ = (std::max)(this->bucket_count_,
-            this->min_buckets_for_size(size));
-        this->create_buckets();
-        this->init_buckets();
-    }
-
-    // basic exception safety
-    template <class T>
-    inline bool hash_table<T>::reserve_for_insert(std::size_t size)
-    {
-        if(size >= max_load_) {
+        if (!this->buckets_) {
+            std::size_t old_bucket_count = this->bucket_count_;
+            this->bucket_count_ = (std::max)(this->bucket_count_,
+                this->min_buckets_for_size(size));
+            this->create_buckets();
+            this->max_load_ = calculate_max_load();
+            return old_bucket_count != this->bucket_count_;
+        }
+        else if(size >= max_load_) {
             std::size_t num_buckets
                 = this->min_buckets_for_size((std::max)(size,
                     this->size_ + (this->size_ >> 1)));
-            if(num_buckets != this->bucket_count_) {
-                rehash_impl(num_buckets);
+            if (num_buckets != this->bucket_count_) {
+                this->rehash_impl(num_buckets);
+                this->max_load_ = calculate_max_load();
                 return true;
             }
         }
@@ -450,7 +440,7 @@
     // strong otherwise.
 
     template <class T>
-    inline void hash_table<T>::rehash(std::size_t min_buckets)
+    void table<T>::rehash(std::size_t min_buckets)
     {
         using namespace std;
 
@@ -462,317 +452,301 @@
             // no throw:
             min_buckets = next_prime((std::max)(min_buckets,
                     double_to_size_t(floor(this->size_ / (double) mlf_)) + 1));
-            if(min_buckets != this->bucket_count_) rehash_impl(min_buckets);
-        }
-    }
-
-    // if hash function throws, basic exception safety
-    // strong otherwise
-
-    template <class T>
-    void hash_table<T>
-        ::rehash_impl(std::size_t num_buckets)
-    {    
-        hasher const& hf = this->hash_function();
-        std::size_t size = this->size_;
-        bucket_ptr end = this->get_bucket(this->bucket_count_);
-
-        buckets dst(this->node_alloc(), num_buckets);
-        dst.create_buckets();
-
-        buckets src(this->node_alloc(), this->bucket_count_);
-        src.swap(*this);
-        this->size_ = 0;
-
-        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(get_key_from_ptr(group)));
-
-                node_ptr& next_group = node::next_group(group);
-                bucket->next_ = next_group;
-                next_group = dst_bucket->next_;
-                dst_bucket->next_ = group;
-                group = bucket->next_;
+            if(min_buckets != this->bucket_count_) {
+                this->rehash_impl(min_buckets);
+                this->max_load_ = calculate_max_load();
             }
         }
-
-        // Swap the new nodes back into the container and setup the local
-        // variables.
-        this->size_ = size;
-        dst.swap(*this);                        // no throw
-        this->init_buckets();
     }
 
     ////////////////////////////////////////////////////////////////////////////
-    // copy_buckets_to
-
-    // copy_buckets_to
     //
-    // basic excpetion safety. If an exception is thrown this will
-    // leave dst partially filled.
+    // types
+    //
+    // This is used to convieniently pass around a container's typedefs
+    // without having 7 template parameters.
 
-    template <class T>
-    void hash_table<T>
-        ::copy_buckets_to(buckets& dst) const
+    template <class K, class V, class H, class P, class A, class E, bool Unique>
+    struct types
     {
-        BOOST_ASSERT(this->buckets_ && !dst.buckets_);
-
-        hasher const& hf = this->hash_function();
-        bucket_ptr end = this->get_bucket(this->bucket_count_);
-
-        node_constructor a(dst);
-        dst.create_buckets();
-
-        // no throw:
-        for(bucket_ptr i = this->cached_begin_bucket_; i != end; ++i) {
-            // no throw:
-            for(node_ptr it = i->next_; it;) {
-                // hash function can throw.
-                bucket_ptr dst_bucket = dst.bucket_ptr_from_hash(
-                    hf(get_key_from_ptr(it)));
-                // throws, strong
-
-                node_ptr group_end = node::next_group(it);
-
-                a.construct(node::get_value(it));
-                node_ptr n = a.release();
-                node::add_to_bucket(n, *dst_bucket);
+    public:
+        typedef K key_type;
+        typedef V value_type;
+        typedef H hasher;
+        typedef P key_equal;
+        typedef A value_allocator;
+        typedef E extractor;
         
-                for(it = it->next_; it != group_end; it = it->next_) {
-                    a.construct(node::get_value(it));
-                    node::add_after_node(a.release(), n);
-                }
-            }
-        }
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Misc. key methods
+        typedef ::boost::unordered::detail::node_constructor<value_allocator, Unique> node_constructor;
+        typedef ::boost::unordered::detail::buckets<value_allocator, Unique> buckets;
+        typedef ::boost::unordered::detail::functions<hasher, key_equal> functions;
+
+        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::node_allocator node_allocator;
+
+        typedef std::pair<node_ptr, node_ptr> iterator_pair;
+    };
+}}}
 
-    // strong exception safety
+namespace boost { namespace unordered { namespace iterator_detail {
 
-    // count
+    // Iterators
     //
-    // strong exception safety, no side effects
+    // all no throw
 
-    template <class T>
-    std::size_t hash_table<T>::count(key_type const& k) const
-    {
-        if(!this->size_) return 0;
-        node_ptr it = find_iterator(k); // throws, strong
-        return BOOST_UNORDERED_BORLAND_BOOL(it) ? node::group_count(it) : 0;
-    }
+    template <class A, bool Unique> class iterator;
+    template <class A, bool Unique> class c_iterator;
+    template <class A, bool Unique> class l_iterator;
+    template <class A, bool Unique> class cl_iterator;
 
-    // find
+    // Local Iterators
     //
-    // strong exception safety, no side effects
-    template <class T>
-    BOOST_DEDUCED_TYPENAME T::iterator_base
-        hash_table<T>::find(key_type const& k) const
-    {
-        if(!this->size_) return 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))
-            return iterator_base(bucket, it);
-        else
-            return this->end();
-    }
-
-    template <class T>
-    template <class Key, class Hash, class Pred>
-    BOOST_DEDUCED_TYPENAME T::iterator_base hash_table<T>::find(Key const& k,
-        Hash const& h, Pred const& eq) const
-    {
-        if(!this->size_) return this->end();
-
-        bucket_ptr bucket = this->get_bucket(h(k) % this->bucket_count_);
-        node_ptr it = find_iterator(bucket, k, eq);
+    // all no throw
 
-        if (BOOST_UNORDERED_BORLAND_BOOL(it))
-            return iterator_base(bucket, it);
-        else
-            return this->end();
-    }
+    template <class A, bool Unique>
+    class l_iterator
+        : public ::boost::iterator <
+            std::forward_iterator_tag,
+            BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type,
+            std::ptrdiff_t,
+            BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::pointer,
+            BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type&>
+    {
+    public:
+        typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type value_type;
+
+    private:
+        typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
+        typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
+        typedef BOOST_DEDUCED_TYPENAME buckets::node node;
+        typedef cl_iterator<A, Unique> const_local_iterator;
 
-    template <class T>
-    BOOST_DEDUCED_TYPENAME T::value_type&
-        hash_table<T>::at(key_type const& k) const
-    {
-        if(!this->size_)
-            boost::throw_exception(std::out_of_range("Unable to find key in unordered_map."));
-
-        bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
-        node_ptr it = find_iterator(bucket, k);
-
-        if (!it)
-            boost::throw_exception(std::out_of_range("Unable to find key in unordered_map."));
+        friend class cl_iterator<A, Unique>;
+        
+        node_ptr ptr_;
+        std::size_t bucket_;
+        std::size_t bucket_count_;
+
+    public:
+        l_iterator() : ptr_() {}
+        l_iterator(node_ptr x, std::size_t b, std::size_t c)
+            : ptr_(x), bucket_(b), bucket_count_(c) {}
+        BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type& operator*() const {
+            return node::get_value(ptr_);
+        }
+        value_type* operator->() const {
+            return node::get_value_ptr(ptr_);
+        }
+        l_iterator& operator++() {
+            ptr_ = ptr_->next_;
+            if (ptr_ && node::get_hash(ptr_) % bucket_count_ != bucket_)
+                ptr_ = node_ptr();
+            return *this;
+        }
+        l_iterator operator++(int) {
+            l_iterator tmp(*this);
+            ptr_ = ptr_->next_;
+            if (ptr_ && node::get_hash(ptr_) % bucket_count_ != bucket_)
+                ptr_ = node_ptr();
+            return tmp;
+        }
+        bool operator==(l_iterator x) const {
+            return ptr_ == x.ptr_;
+        }
+        bool operator==(const_local_iterator x) const {
+            return ptr_ == x.ptr_;
+        }
+        bool operator!=(l_iterator x) const {
+            return ptr_ != x.ptr_;
+        }
+        bool operator!=(const_local_iterator x) const {
+            return ptr_ != x.ptr_;
+        }
+    };
+
+    template <class A, bool Unique>
+    class cl_iterator
+        : public ::boost::iterator <
+            std::forward_iterator_tag,
+            BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type,
+            std::ptrdiff_t,
+            BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::const_pointer,
+            BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type const& >
+    {
+    public:
+        typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type value_type;
+
+    private:
+        typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
+        typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
+        typedef BOOST_DEDUCED_TYPENAME buckets::node node;
+        typedef l_iterator<A, Unique> local_iterator;
+
+        friend class l_iterator<A, Unique>;
+
+        node_ptr ptr_;
+        std::size_t bucket_;
+        std::size_t bucket_count_;
+
+    public:
+        cl_iterator() : ptr_() {}
+        cl_iterator(node_ptr x, std::size_t b, std::size_t c)
+            : ptr_(x), bucket_(b), bucket_count_(c) {}
+        cl_iterator(local_iterator x)
+            : ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
+        {}
+        BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type const&
+            operator*() const {
+            return node::get_value(ptr_);
+        }
+        value_type const* operator->() const {
+            return node::get_value_ptr(ptr_);
+        }
+        cl_iterator& operator++() {
+            ptr_ = ptr_->next_;
+            if (ptr_ && node::get_hash(ptr_) % bucket_count_ != bucket_)
+                ptr_ = node_ptr();
+            return *this;
+        }
+        cl_iterator operator++(int) {
+            cl_iterator tmp(*this);
+            ptr_ = ptr_->next_;
+            if (ptr_ && node::get_hash(ptr_) % bucket_count_ != bucket_)
+                ptr_ = node_ptr();
+            return tmp;
+        }
+        bool operator==(local_iterator x) const {
+            return ptr_ == x.ptr_;
+        }
+        bool operator==(cl_iterator x) const {
+            return ptr_ == x.ptr_;
+        }
+        bool operator!=(local_iterator x) const {
+            return ptr_ != x.ptr_;
+        }
+        bool operator!=(cl_iterator x) const {
+            return ptr_ != x.ptr_;
+        }
+    };
+
+    template <class A, bool Unique>
+    class iterator
+        : public ::boost::iterator <
+            std::forward_iterator_tag,
+            BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type,
+            std::ptrdiff_t,
+            BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::pointer,
+            BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type& >
+    {
+    public:
+        typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type value_type;
+
+    private:
+        typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
+        typedef BOOST_DEDUCED_TYPENAME buckets::node node;
+        typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
+        typedef c_iterator<A, Unique> const_iterator;
+        friend class c_iterator<A, Unique>;
+        node_ptr node_;
+
+    public:
+
+        iterator() : node_() {}
+        explicit iterator(node_ptr const& x) : node_(x) {}
+        BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type& operator*() const {
+            return node::get_value(node_);
+        }
+        value_type* operator->() const {
+            return &node::get_value(node_);
+        }
+        iterator& operator++() {
+            node_ = node_->next_; return *this;
+        }
+        iterator operator++(int) {
+            iterator tmp(node_); node_ = node_->next_; return tmp;
+        }
+        bool operator==(iterator const& x) const {
+            return node_ == x.node_;
+        }
+        bool operator==(const_iterator const& x) const {
+            return node_ == x.node_;
+        }
+        bool operator!=(iterator const& x) const {
+            return node_ != x.node_;
+        }
+        bool operator!=(const_iterator const& x) const {
+            return node_ != x.node_;
+        }
+    };
+
+    template <class A, bool Unique>
+    class c_iterator
+        : public ::boost::iterator <
+            std::forward_iterator_tag,
+            BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type,
+            std::ptrdiff_t,
+            BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::const_pointer,
+            BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type const& >
+    {
+    public:
+        typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type value_type;
+
+    private:
+        typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
+        typedef BOOST_DEDUCED_TYPENAME buckets::node node;
+        typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
+        typedef ::boost::unordered::iterator_detail::iterator<A, Unique>
+            iterator;
+        friend class ::boost::unordered::iterator_detail::iterator<A, Unique>;
+
+#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+        template <class K, class T, class H, class P, class A2>
+        friend class ::boost::unordered::unordered_map;
+        template <class K, class T, class H, class P, class A2>
+        friend class ::boost::unordered::unordered_multimap;
+        template <class T, class H, class P, class A2>
+        friend class ::boost::unordered::unordered_set;
+        template <class T, class H, class P, class A2>
+        friend class ::boost::unordered::unordered_multiset;
+#else
+    public:
+#endif
 
-        return node::get_value(it);
-    }
+        node_ptr node_;
 
-    // equal_range
-    //
-    // strong exception safety, no side effects
-    template <class T>
-    BOOST_DEDUCED_TYPENAME T::iterator_pair
-        hash_table<T>::equal_range(key_type const& k) const
-    {
-        if(!this->size_)
-            return iterator_pair(this->end(), this->end());
+    public:
 
-        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_bucket(node::next_group(second.node_));
-            return iterator_pair(first, second);
+        c_iterator() : node_() {}
+        explicit c_iterator(node_ptr const& x) : node_(x) {}
+        c_iterator(iterator const& x) : node_(x.node_) {}
+        BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type const& operator*() const {
+            return node::get_value(node_);
         }
-        else {
-            return iterator_pair(this->end(), this->end());
+        value_type const* operator->() const {
+            return &node::get_value(node_);
         }
-    }
-    
-    ////////////////////////////////////////////////////////////////////////////
-    // Erase methods    
-    
-    template <class T>
-    void hash_table<T>::clear()
-    {
-        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);
+        c_iterator& operator++() {
+            node_ = node_->next_; return *this;
         }
-
-        this->size_ = 0;
-        this->cached_begin_bucket_ = end;
-    }
-
-    template <class T>
-    inline std::size_t hash_table<T>::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 T>
-    std::size_t hash_table<T>::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);
-
-        // No throw.
-        return *it ? this->erase_group(it, bucket) : 0;
-    }
-
-    template <class T>
-    void hash_table<T>::erase(iterator_base r)
-    {
-        BOOST_ASSERT(r.node_);
-        --this->size_;
-        node::unlink_node(*r.bucket_, r.node_);
-        this->delete_node(r.node_);
-        // r has been invalidated but its bucket is still valid
-        this->recompute_begin_bucket(r.bucket_);
-    }
-
-    template <class T>
-    BOOST_DEDUCED_TYPENAME T::iterator_base
-        hash_table<T>::erase_return_iterator(iterator_base r)
-    {
-        BOOST_ASSERT(r.node_);
-        iterator_base next = r;
-        next.increment();
-        --this->size_;
-        node::unlink_node(*r.bucket_, 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 T>
-    BOOST_DEDUCED_TYPENAME T::iterator_base
-        hash_table<T>::erase_range(
-            iterator_base r1, iterator_base r2)
-    {
-        if(r1 != r2)
-        {
-            BOOST_ASSERT(r1.node_);
-            if (r1.bucket_ == r2.bucket_) {
-                node::unlink_nodes(*r1.bucket_, 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_);
-            }
-            else {
-                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->size_ -= this->delete_nodes(r1.node_, node_ptr());
-
-                bucket_ptr i = r1.bucket_;
-                for(++i; i != end_bucket; ++i) {
-                    this->size_ -= this->delete_nodes(i->next_, node_ptr());
-                    i->next_ = node_ptr();
-                }
-
-                if(r2.node_) {
-                    node_ptr first = r2.bucket_->next_;
-                    node::unlink_nodes(*r2.bucket_, 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_, end_bucket);
-            }
+        c_iterator operator++(int) {
+            c_iterator tmp(node_); node_ = node_->next_; return tmp;
         }
-
-        return r2;
-    }
-
-    template <class T>
-    BOOST_DEDUCED_TYPENAME hash_table<T>::iterator_base
-        hash_table<T>::emplace_empty_impl_with_node(
-            node_constructor& a, std::size_t size)
-    {
-        key_type const& k = get_key(a.value());
-        std::size_t hash_value = this->hash_function()(k);
-        if(this->buckets_) this->reserve_for_insert(size);
-        else this->create_for_insert(size);
-        bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
-        node_ptr n = a.release();
-        node::add_to_bucket(n, *bucket);
-        ++this->size_;
-        this->cached_begin_bucket_ = bucket;
-        return iterator_base(bucket, n);
-    }
-}}
+        bool operator==(iterator const& x) const {
+            return node_ == x.node_;
+        }
+        bool operator==(c_iterator const& x) const {
+            return node_ == x.node_;
+        }
+        bool operator!=(iterator const& x) const {
+            return node_ != x.node_;
+        }
+        bool operator!=(c_iterator const& x) const {
+            return node_ != x.node_;
+        }
+    };
+}}}
 
 #endif
Modified: branches/release/boost/unordered/detail/unique.hpp
==============================================================================
--- branches/release/boost/unordered/detail/unique.hpp	(original)
+++ branches/release/boost/unordered/detail/unique.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -1,19 +1,18 @@
 
 // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
-// Copyright (C) 2005-2010 Daniel James
+// Copyright (C) 2005-2011 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 {
+namespace boost { namespace unordered { namespace detail {
 
     template <class T>
-    class hash_unique_table : public T::table
+    class unique_table : public T::table_base
     {
     public:
         typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
@@ -21,493 +20,398 @@
         typedef BOOST_DEDUCED_TYPENAME T::value_allocator value_allocator;
         typedef BOOST_DEDUCED_TYPENAME T::key_type key_type;
         typedef BOOST_DEDUCED_TYPENAME T::value_type value_type;
-        typedef BOOST_DEDUCED_TYPENAME T::table table;
+        typedef BOOST_DEDUCED_TYPENAME T::table_base table_base;
         typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor;
+        typedef BOOST_DEDUCED_TYPENAME T::node_allocator node_allocator;
 
         typedef BOOST_DEDUCED_TYPENAME T::node node;
         typedef BOOST_DEDUCED_TYPENAME T::node_ptr node_ptr;
         typedef BOOST_DEDUCED_TYPENAME T::bucket_ptr bucket_ptr;
-        typedef BOOST_DEDUCED_TYPENAME T::iterator_base iterator_base;
         typedef BOOST_DEDUCED_TYPENAME T::extractor extractor;
         
-        typedef std::pair<iterator_base, bool> emplace_return;
+        typedef std::pair<node_ptr, bool> emplace_return;
 
         // Constructors
 
-        hash_unique_table(std::size_t n, hasher const& hf, key_equal const& eq,
+        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,
+          : table_base(n, hf, eq, a) {}
+        unique_table(unique_table const& x)
+          : table_base(x,
+                allocator_traits<node_allocator>::
+                select_on_container_copy_construction(x.node_alloc())) {}
+        unique_table(unique_table const& x, value_allocator const& a)
+          : table_base(x, a) {}
+        unique_table(unique_table& x, move_tag m)
+          : table_base(x, m) {}
+        unique_table(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);
+          : table_base(x, a, m) {}
+        ~unique_table() {}
 
         // 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>
-        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
-
-#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)>                         \
-        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_PP_REPEAT_FROM_TO(1, 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 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_impl2(node_constructor&, 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>
-    struct set : public types<
-        BOOST_DEDUCED_TYPENAME A::value_type,
-        BOOST_DEDUCED_TYPENAME A::value_type,
-        H, P, A,
-        set_extractor<BOOST_DEDUCED_TYPENAME A::value_type>,
-        ungrouped>
-    {        
-        typedef hash_unique_table<set<H, P, A> > impl;
-        typedef hash_table<set<H, P, A> > table;
-    };
-
-    template <class K, class H, class P, class A>
-    struct map : public types<
-        K, BOOST_DEDUCED_TYPENAME A::value_type,
-        H, P, A,
-        map_extractor<K, BOOST_DEDUCED_TYPENAME A::value_type>,
-        ungrouped>
-    {
-        typedef hash_unique_table<map<K, H, P, A> > impl;
-        typedef hash_table<map<K, H, P, A> > table;
-    };
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Equality
-
-    template <class T>
-    bool hash_unique_table<T>
-        ::equals(hash_unique_table<T> 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)
+        bool equals(unique_table const& other) const
         {
-            node_ptr it1 = i->next_;
-            while(BOOST_UNORDERED_BORLAND_BOOL(it1))
+            if(this->size_ != other.size_) return false;
+            if(!this->size_) return true;
+    
+            for(node_ptr n1 = this->get_bucket(this->bucket_count_)->next_;
+                n1; n1 = n1->next_)
             {
-                node_ptr it2 = other.find_iterator(this->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)))
+                node_ptr n2 = other.find_matching_node(n1);
+                if(!n2 || node::get_value(n1) != node::get_value(n2))
                     return false;
-                it1 = it1->next_;
             }
+    
+            return true;
         }
 
-        return true;
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    // A convenience method for adding nodes.
-
-    template <class T>
-    inline BOOST_DEDUCED_TYPENAME hash_unique_table<T>::node_ptr
-        hash_unique_table<T>::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 T>
-    BOOST_DEDUCED_TYPENAME hash_unique_table<T>::value_type&
-        hash_unique_table<T>::operator[](key_type const& k)
-    {
-        typedef BOOST_DEDUCED_TYPENAME value_type::second_type mapped_type;
+        ////////////////////////////////////////////////////////////////////////
+        // A convenience method for adding nodes.
 
-        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 add_node(
+                node_constructor& a,
+                std::size_t bucket_index,
+                std::size_t hash)        
+        {
+            bucket_ptr b = this->get_bucket(bucket_index);
+            node_ptr n = a.release();
+            node::set_hash(n, hash);
+    
+            if (!b->next_)
+            {
+                bucket_ptr start_node = this->get_bucket(this->bucket_count_);
+                
+                if (start_node->next_) {
+                    this->buckets_[
+                        node::get_hash(start_node->next_) % this->bucket_count_
+                    ].next_ = n;
+                }
+    
+                b->next_ = start_node;
+                n->next_ = start_node->next_;
+                start_node->next_ = n;
+            }
+            else
+            {
+                n->next_ = b->next_->next_;
+                b->next_->next_ = n;
+            }
+    
+            ++this->size_;
+            return n;
         }
 
-        node_ptr pos = this->find_iterator(bucket, k);
+        ////////////////////////////////////////////////////////////////////////////
+        // Insert methods
 
-        if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
-            return node::get_value(pos);
-        }
-        else {
-            // Side effects only in this block.
+        // if hash function throws, basic exception safety
+        // strong otherwise
 
+        value_type& operator[](key_type const& k)
+        {
+            typedef BOOST_DEDUCED_TYPENAME value_type::second_type mapped_type;
+    
+            std::size_t hash = this->hash_function()(k);
+            std::size_t bucket_index = hash % this->bucket_count_;
+            node_ptr pos = this->find_node(bucket_index, hash, k);
+    
+            if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
+                return node::get_value(pos);
+            }
+    
             // 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);
-
+                bucket_index = hash % this->bucket_count_;
+    
             // Nothing after this point can throw.
-
-            return node::get_value(add_node(a, bucket));
+    
+            return node::get_value(add_node(a, bucket_index, hash));
         }
-    }
 
-    template <class T>
-    inline BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
-    hash_unique_table<T>::emplace_impl_with_node(node_constructor& a)
-    {
-        // No side effects in this initial code
-        key_type const& k = this->get_key(a.value());
-        std::size_t hash_value = this->hash_function()(k);
-        bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
-        node_ptr pos = this->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 {
+        emplace_return emplace_impl_with_node(node_constructor& a)
+        {
+            // No side effects in this initial code
+            key_type const& k = this->get_key(a.value());
+            std::size_t hash = this->hash_function()(k);
+            std::size_t bucket_index = hash % this->bucket_count_;
+            node_ptr pos = this->find_node(bucket_index, hash, k);
+            
+            if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
+                // Found an existing key, return it (no throw).
+                return emplace_return(pos, false);
+            }
+    
             // 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);
-
+                bucket_index = hash % this->bucket_count_;
+    
             // Nothing after this point can throw.
+    
+            return emplace_return(add_node(a, bucket_index, hash), true);
+        }
 
-            return emplace_return(
-                iterator_base(bucket, add_node(a, bucket)),
-                true);
+        emplace_return insert(value_type const& v)
+        {
+            key_type const& k = extractor::extract(v);
+            std::size_t hash = this->hash_function()(k);
+            std::size_t bucket_index = hash % this->bucket_count_;
+            node_ptr pos = this->find_node(bucket_index, hash, k);
+    
+            if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
+                // Found an existing key, return it (no throw).
+                return emplace_return(pos, false);
+            }
+    
+            // Isn't in table, add to bucket.
+    
+            // Create the node before rehashing in case it throws an
+            // exception (need strong safety in such a case).
+            node_constructor a(*this);
+            a.construct(v);
+    
+            // reserve has basic exception safety if the hash function
+            // throws, strong otherwise.
+            if(this->reserve_for_insert(this->size_ + 1))
+                bucket_index = hash % this->bucket_count_;
+    
+            // Nothing after this point can throw.
+    
+            return emplace_return(add_node(a, bucket_index, hash), true);
         }
-    }
 
-#if defined(BOOST_UNORDERED_STD_FORWARD)
 
-    template <class T>
-    template<class... Args>
-    inline BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
-        hash_unique_table<T>::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 = this->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);
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
 
-        } else {
+        template<class... Args>
+        emplace_return emplace(Args&&... args)
+        {
+            return emplace_impl(
+                    extractor::extract(std::forward<Args>(args)...),
+                    std::forward<Args>(args)...);
+        }
+
+        template<class... Args>
+        emplace_return emplace_impl(key_type const& k, Args&&... args)
+        {
+            // No side effects in this initial code
+            std::size_t hash = this->hash_function()(k);
+            std::size_t bucket_index = hash % this->bucket_count_;
+            node_ptr pos = this->find_node(bucket_index, hash, k);
+    
+            if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
+                // Found an existing key, return it (no throw).
+                return emplace_return(pos, false);
+            }
+    
             // 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);
-
+                bucket_index = hash % this->bucket_count_;
+    
             // Nothing after this point can throw.
-
-            return emplace_return(
-                iterator_base(bucket, add_node(a, bucket)),
-                true);
+    
+            return emplace_return(add_node(a, bucket_index, hash), true);
         }
-    }
-
-    template <class T>
-    template<class... Args>
-    inline BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
-        hash_unique_table<T>::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 T>
-    template<class... Args>
-    inline BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
-        hash_unique_table<T>::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);
-    }
 
+        template<class... Args>
+        emplace_return emplace_impl(no_key, Args&&... args)
+        {
+            // Construct the node regardless - in order to get the key.
+            // It will be discarded if it isn't used
+            node_constructor a(*this);
+            a.construct(std::forward<Args>(args)...);
+            return emplace_impl_with_node(a);
+        }
 #else
 
-#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _)                          \
-    template <class T>                                                         \
-    template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)>                    \
-    inline BOOST_DEDUCED_TYPENAME                                              \
-        hash_unique_table<T>::emplace_return                                   \
-            hash_unique_table<T>::emplace_impl(                                \
-                key_type const& k,                                             \
-                BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params))                \
-    {                                                                          \
-        std::size_t hash_value = this->hash_function()(k);                     \
-        bucket_ptr bucket                                                      \
-            = this->bucket_ptr_from_hash(hash_value);                          \
-        node_ptr pos = this->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, num_params));           \
-                                                                               \
-            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 T>                                                         \
-    template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)>                    \
-    inline BOOST_DEDUCED_TYPENAME                                              \
-        hash_unique_table<T>::emplace_return                                   \
-            hash_unique_table<T>::                                             \
-                emplace_impl(no_key,                                           \
-                    BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params))            \
-    {                                                                          \
-        node_constructor a(*this);                                             \
-        a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params));               \
-        return emplace_impl_with_node(a);                                      \
-    }                                                                          \
-                                                                               \
-    template <class T>                                                         \
-    template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)>                    \
-    inline BOOST_DEDUCED_TYPENAME                                              \
-        hash_unique_table<T>::emplace_return                                   \
-            hash_unique_table<T>::                                             \
-                emplace_empty_impl(                                            \
-                    BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params))            \
-    {                                                                          \
-        node_constructor a(*this);                                             \
-        a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params));               \
-        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 T>
-    template<class... Args>
-    BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
-        hash_unique_table<T>::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)...);
-    }
+        template <class Arg0>
+        emplace_return emplace(BOOST_FWD_REF(Arg0) arg0)
+        {
+            return emplace_impl(
+                extractor::extract(boost::forward<Arg0>(arg0)),
+                boost::forward<Arg0>(arg0));
+        }
 
-#else
+#define BOOST_UNORDERED_INSERT1_IMPL(z, n, _)                               \
+        template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)>                      \
+        emplace_return emplace(                                             \
+            BOOST_UNORDERED_FUNCTION_PARAMS(z, n))                          \
+        {                                                                   \
+            return emplace_impl(extractor::extract(arg0, arg1),             \
+                    BOOST_UNORDERED_CALL_PARAMS(z, n));                     \
+        }
 
-    template <class T>
-    template <class Arg0>
-    BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
-        hash_unique_table<T>::emplace(Arg0 const& arg0)
-    {
-        return this->size_ ?
-            emplace_impl(extractor::extract(arg0), arg0) :
-            emplace_empty_impl(arg0);
-    }
-
-#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _)                          \
-    template <class T>                                                         \
-    template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)>                    \
-    BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return                \
-        hash_unique_table<T>::emplace(                                         \
-            BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params))                    \
-    {                                                                          \
-        return this->size_ ?                                                   \
-            emplace_impl(extractor::extract(arg0, arg1),                       \
-                BOOST_UNORDERED_CALL_PARAMS(z, num_params)) :                  \
-            emplace_empty_impl(                                                \
-                BOOST_UNORDERED_CALL_PARAMS(z, num_params));                   \
-    }
+#define BOOST_UNORDERED_INSERT2_IMPL(z, n, _)                               \
+        template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)>                      \
+        emplace_return emplace_impl(key_type const& k,                      \
+           BOOST_UNORDERED_FUNCTION_PARAMS(z, n))                           \
+        {                                                                   \
+            std::size_t hash = this->hash_function()(k);                    \
+            std::size_t bucket_index = hash % this->bucket_count_;          \
+            node_ptr pos = this->find_node(bucket_index, hash, k);          \
+                                                                            \
+            if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {                        \
+                return emplace_return(pos, false);                          \
+            } else {                                                        \
+                node_constructor a(*this);                                  \
+                a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n));             \
+                                                                            \
+                if(this->reserve_for_insert(this->size_ + 1))               \
+                    bucket_index = hash % this->bucket_count_;              \
+                                                                            \
+                return emplace_return(                                      \
+                    add_node(a, bucket_index, hash),                        \
+                    true);                                                  \
+            }                                                               \
+        }                                                                   \
+                                                                            \
+        template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)>                      \
+        emplace_return emplace_impl(no_key,                                 \
+           BOOST_UNORDERED_FUNCTION_PARAMS(z, n))                           \
+        {                                                                   \
+            node_constructor a(*this);                                      \
+            a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n));                 \
+            return emplace_impl_with_node(a);                               \
+        }
 
-    BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT,
-        BOOST_UNORDERED_INSERT_IMPL, _)
+        BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT,
+            BOOST_UNORDERED_INSERT1_IMPL, _)
+        BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
+            BOOST_UNORDERED_INSERT2_IMPL, _)
 
-#undef BOOST_UNORDERED_INSERT_IMPL
+#undef BOOST_UNORDERED_INSERT1_IMPL
+#undef BOOST_UNORDERED_INSERT2_IMPL
 
 #endif
-    
-    ////////////////////////////////////////////////////////////////////////////
-    // Insert range methods
 
-    template <class T>
-    template <class InputIt>
-    inline void hash_unique_table<T>::insert_range_impl2(
-        node_constructor& a, key_type const& k, InputIt i, InputIt j)
-    {
-        // No side effects in this initial code
-        std::size_t hash_value = this->hash_function()(k);
-        bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
-        node_ptr pos = this->find_iterator(bucket, k);
+        ////////////////////////////////////////////////////////////////////////
+        // Insert range methods
+        //
+        // if hash function throws, or inserting > 1 element, basic exception
+        // safety strong otherwise
 
-        if (!BOOST_UNORDERED_BORLAND_BOOL(pos)) {
-            // Doesn't already exist, add to bucket.
-            // Side effects only in this block.
+        template <class InputIt>
+        void insert_range(InputIt i, InputIt j)
+        {
+            if(i != j)
+                return insert_range_impl(extractor::extract(*i), i, j);
+        }
 
-            // Create the node before rehashing in case it throws an
-            // exception (need strong safety in such a case).
-            a.construct(*i);
+        template <class InputIt>
+        void insert_range_impl(key_type const&, InputIt i, InputIt j)
+        {
+            node_constructor a(*this);
 
-            // 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);
+            // Special case for empty buckets so that we can use
+            // max_load_ (which isn't valid when buckets_ is null).
+            if (!this->buckets_) {
+                insert_range_empty(a, extractor::extract(*i), i, j);
+                if (++i == j) return;
             }
 
-            // Nothing after this point can throw.
-            add_node(a, bucket);
+            do {
+                // Note: can't use get_key as '*i' might not be value_type - it
+                // could be a pair with first_types as key_type without const or a
+                // different second_type.
+                //
+                // TODO: Might be worth storing the value_type instead of the key
+                // here. Could be more efficient if '*i' is expensive. Could be
+                // less efficient if copying the full value_type is expensive.
+                insert_range_impl2(a, extractor::extract(*i), i, j);
+            } while(++i != j);
         }
-    }
 
-    template <class T>
-    template <class InputIt>
-    inline void hash_unique_table<T>::insert_range_impl(
-        key_type const&, InputIt i, InputIt j)
-    {
-        node_constructor a(*this);
-
-        if(!this->size_) {
+        template <class InputIt>
+        void insert_range_empty(node_constructor& a, key_type const& k,
+            InputIt i, InputIt j)
+        {
+            std::size_t hash = this->hash_function()(k);
             a.construct(*i);
-            this->emplace_empty_impl_with_node(a, 1);
-            ++i;
-            if(i == j) return;
-        }
-
-        do {
-            // Note: can't use get_key as '*i' might not be value_type - it
-            // could be a pair with first_types as key_type without const or a
-            // different second_type.
-            //
-            // TODO: Might be worth storing the value_type instead of the key
-            // here. Could be more efficient if '*i' is expensive. Could be
-            // less efficient if copying the full value_type is expensive.
-            insert_range_impl2(a, extractor::extract(*i), i, j);
-        } while(++i != j);
-    }
+            this->reserve_for_insert(this->size_ + insert_size(i, j));
+            add_node(a, hash % this->bucket_count_, hash);
+        }
 
-    template <class T>
-    template <class InputIt>
-    inline void hash_unique_table<T>::insert_range_impl(
-        no_key, InputIt i, InputIt j)
-    {
-        node_constructor a(*this);
+        template <class InputIt>
+        void insert_range_impl2(node_constructor& a, key_type const& k,
+            InputIt i, InputIt j)
+        {
+            // No side effects in this initial code
+            std::size_t hash = this->hash_function()(k);
+            std::size_t bucket_index = hash % this->bucket_count_;
+            node_ptr pos = this->find_node(bucket_index, hash, k);
+    
+            if (!BOOST_UNORDERED_BORLAND_BOOL(pos)) {
+                // Doesn't already exist, add to bucket.
+                // Side effects only in this block.
+    
+                // Create the node before rehashing in case it throws an
+                // exception (need strong safety in such a case).
+                a.construct(*i);
+    
+                // reserve has basic exception safety if the hash function
+                // throws, strong otherwise.
+                if(this->size_ + 1 >= this->max_load_) {
+                    this->reserve_for_insert(this->size_ + insert_size(i, j));
+                    bucket_index = hash % this->bucket_count_;
+                }
+    
+                // Nothing after this point can throw.
+                add_node(a, bucket_index, hash);
+            }
+        }
 
-        if(!this->size_) {
-            a.construct(*i);
-            this->emplace_empty_impl_with_node(a, 1);
-            ++i;
-            if(i == j) return;
+        template <class InputIt>
+        void insert_range_impl(no_key, InputIt i, InputIt j)
+        {
+            node_constructor a(*this);
+
+            do {
+                // No side effects in this initial code
+                a.construct(*i);
+                emplace_impl_with_node(a);
+            } while(++i != j);
         }
+    };
 
-        do {
-            // No side effects in this initial code
-            a.construct(*i);
-            emplace_impl_with_node(a);
-        } while(++i != j);
-    }
+    template <class H, class P, class A>
+    struct set : public types<
+        BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
+        BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
+        H, P, A,
+        set_extractor<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>,
+        true>
+    {        
+        typedef ::boost::unordered::detail::unique_table<set<H, P, A> > impl;
+        typedef ::boost::unordered::detail::table<set<H, P, A> > table_base;
+    };
 
-    // if hash function throws, or inserting > 1 element, basic exception safety
-    // strong otherwise
-    template <class T>
-    template <class InputIt>
-    void hash_unique_table<T>::insert_range(InputIt i, InputIt j)
+    template <class K, class H, class P, class A>
+    struct map : public types<
+        K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
+        H, P, A,
+        map_extractor<K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>,
+        true>
     {
-        if(i != j)
-            return insert_range_impl(extractor::extract(*i), i, j);
-    }
-}}
+        typedef ::boost::unordered::detail::unique_table<map<K, H, P, A> > impl;
+        typedef ::boost::unordered::detail::table<map<K, H, P, A> > table_base;
+    };
+}}}
 
 #endif
Modified: branches/release/boost/unordered/detail/util.hpp
==============================================================================
--- branches/release/boost/unordered/detail/util.hpp	(original)
+++ branches/release/boost/unordered/detail/util.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -1,22 +1,127 @@
 
 // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
-// Copyright (C) 2005-2009 Daniel James
+// Copyright (C) 2005-2011 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_UTIL_HPP_INCLUDED
 #define BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
 
+#include <algorithm>
 #include <cstddef>
+#include <stdexcept>
 #include <utility>
-#include <algorithm>
 #include <boost/limits.hpp>
+#include <boost/config.hpp>
+#include <boost/config/no_tr1/cmath.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/detail/select_type.hpp>
+#include <boost/assert.hpp>
+#include <boost/iterator.hpp>
 #include <boost/iterator/iterator_categories.hpp>
+#include <boost/type_traits/aligned_storage.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/is_empty.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/unordered/detail/allocator_helpers.hpp>
 #include <boost/preprocessor/seq/size.hpp>
 #include <boost/preprocessor/seq/enum.hpp>
-#include <boost/unordered/detail/fwd.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/move/move.hpp>
+#include <boost/swap.hpp>
+
+// Template parameters:
+//
+// H = Hash Function
+// P = Predicate
+// A = Value Allocator
+// G = Bucket group policy, 'grouped' or 'ungrouped'
+// E = Key Extractor
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES) && \
+        !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#   if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
+#   elif defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)
+#   elif defined(_LIBCPP_VERSION)
+#       define BOOST_UNORDERED_STD_FORWARD_MOVE
+#   elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
+#       if defined(__GLIBCXX__) && __GLIBCXX__ >= 20090804
+#           define BOOST_UNORDERED_STD_FORWARD_MOVE
+#       endif
+#    elif defined(__STL_CONFIG_H)
+#    elif defined(__MSL_CPP__)
+#    elif defined(__IBMCPP__)
+#    elif defined(MSIPL_COMPILE_H)
+#    elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)
+        // Visual C++. A version check would be a good idea.
+#       define BOOST_UNORDERED_STD_FORWARD_MOVE    
+#   endif
+#endif
+
+#if !defined(BOOST_UNORDERED_EMPLACE_LIMIT)
+#define BOOST_UNORDERED_EMPLACE_LIMIT 10
+#endif
+
+#if defined(__SUNPRO_CC)
+#define BOOST_UNORDERED_USE_RV_REF 0
+#else
+#define BOOST_UNORDERED_USE_RV_REF 1
+#endif
+
+#if !defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+
+#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, num_params) \
+    BOOST_PP_ENUM_PARAMS_Z(z, num_params, class Arg)
+
+#define BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
+    BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_FUNCTION_PARAMS2, _)
+#define BOOST_UNORDERED_FUNCTION_PARAMS2(z, i, _) \
+    BOOST_FWD_REF(Arg##i) arg##i
+
+#define BOOST_UNORDERED_CALL_PARAMS(z, num_params) \
+    BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_PARAMS2, _)
+#define BOOST_UNORDERED_CALL_PARAMS2(z, i, _) \
+    boost::forward<Arg##i>(arg##i)
+
+#endif
+
+namespace boost { namespace unordered { namespace detail {
+
+    static const float minimum_max_load_factor = 1e-3f;
+    static const std::size_t default_bucket_count = 11;
+    struct move_tag {};
+
+    struct empty_emplace {};
+
+    template <class T> class unique_table;
+    template <class T> class equivalent_table;
+    template <class Alloc, bool Unique> class node_constructor;
+    template <class ValueType>
+    struct set_extractor;
+    template <class Key, class ValueType>
+    struct map_extractor;
+    struct no_key;
+
+    // Explicitly call a destructor
+
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+#pragma warning(disable:4100) // unreferenced formal parameter
+#endif
 
-namespace boost { namespace unordered_detail {
+    template <class T>
+    inline void destroy(T* x) {
+        x->~T();
+    }
+
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#endif
 
     ////////////////////////////////////////////////////////////////////////////
     // convert double to std::size_t
@@ -95,12 +200,19 @@
     ////////////////////////////////////////////////////////////////////////////
     // pair_cast - because some libraries don't have the full pair constructors.
 
+#if 0
     template <class Dst1, class Dst2, class Src1, class Src2>
     inline std::pair<Dst1, Dst2> pair_cast(std::pair<Src1, Src2> const& x)
     {
         return std::pair<Dst1, Dst2>(Dst1(x.first), Dst2(x.second));
     }
 
+#define BOOST_UNORDERED_PAIR_CAST(First, Last, Argument) \
+    ::boost::unordered::detail::pair_cast<First, Last>(Argument)
+#else
+#define BOOST_UNORDERED_PAIR_CAST(First, Last, Argument) \
+    Argument
+#endif
     ////////////////////////////////////////////////////////////////////////////
     // insert_size/initial_size
 
@@ -116,13 +228,13 @@
 #endif
 
     template <class I>
-    inline std::size_t insert_size(I i, I j, boost::forward_traversal_tag)
+    inline std::size_t insert_size(I i, I j, ::boost::forward_traversal_tag)
     {
         return std::distance(i, j);
     }
 
     template <class I>
-    inline std::size_t insert_size(I, I, boost::incrementable_traversal_tag)
+    inline std::size_t insert_size(I, I, ::boost::incrementable_traversal_tag)
     {
         return 1;
     }
@@ -130,202 +242,114 @@
     template <class I>
     inline std::size_t insert_size(I i, I j)
     {
-        BOOST_DEDUCED_TYPENAME boost::iterator_traversal<I>::type
+        BOOST_DEDUCED_TYPENAME ::boost::iterator_traversal<I>::type
             iterator_traversal_tag;
         return insert_size(i, j, iterator_traversal_tag);
     }
     
     template <class I>
     inline std::size_t initial_size(I i, I j,
-        std::size_t num_buckets = boost::unordered_detail::default_bucket_count)
+        std::size_t num_buckets = ::boost::unordered::detail::default_bucket_count)
     {
         return (std::max)(static_cast<std::size_t>(insert_size(i, j)) + 1,
             num_buckets);
     }
 
     ////////////////////////////////////////////////////////////////////////////
-    // Node Constructors
-
-#if defined(BOOST_UNORDERED_STD_FORWARD)
+    // compressed_pair
 
-    template <class T, class... Args>
-    inline void construct_impl(T*, void* address, Args&&... args)
+    template <typename T, int Index>
+    struct compressed_base : private T
     {
-        new(address) T(std::forward<Args>(args)...);
-    }
+        compressed_base(T const& x) : T(x) {}
+        compressed_base(T& x, move_tag) : T(boost::move(x)) {}
 
-#if defined(BOOST_UNORDERED_CPP0X_PAIR)
-    template <class First, class Second, class Key, class Arg0, class... Args>
-    inline void construct_impl(std::pair<First, Second>*, void* address,
-        Key&& k, Arg0&& arg0, Args&&... args)
-    )
+        T& get() { return *this; }
+        T const& get() const { return *this; }
+    };
+    
+    template <typename T, int Index>
+    struct uncompressed_base
     {
-        new(address) std::pair<First, Second>(k,
-            Second(arg0, std::forward<Args>(args)...);
-    }
-#endif
-
-#else
-
-#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _)                       \
-    template <                                                                 \
-        class T,                                                               \
-        BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)                           \
-    >                                                                          \
-    inline void construct_impl(                                                \
-        T*, void* address,                                                     \
-        BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)                         \
-    )                                                                          \
-    {                                                                          \
-        new(address) T(                                                        \
-            BOOST_UNORDERED_CALL_PARAMS(z, num_params));                       \
-    }                                                                          \
-                                                                               \
-    template <class First, class Second, class Key,                            \
-        BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)                           \
-    >                                                                          \
-    inline void construct_impl(                                                \
-        std::pair<First, Second>*, void* address,                              \
-        Key const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params))          \
-    {                                                                          \
-        new(address) std::pair<First, Second>(k,                               \
-            Second(BOOST_UNORDERED_CALL_PARAMS(z, num_params)));               \
-    }
+        uncompressed_base(T const& x) : value_(x) {}
+        uncompressed_base(T& x, move_tag) : value_(boost::move(x)) {}
 
-    BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
-        BOOST_UNORDERED_CONSTRUCT_IMPL, _)
-
-#undef BOOST_UNORDERED_CONSTRUCT_IMPL
-#endif
-
-    // hash_node_constructor
-    //
-    // Used to construct nodes in an exception safe manner.
-
-    template <class Alloc, class Grouped>
-    class hash_node_constructor
-    {
-        typedef hash_buckets<Alloc, Grouped> buckets;
-        typedef BOOST_DEDUCED_TYPENAME buckets::node node;
-        typedef BOOST_DEDUCED_TYPENAME buckets::real_node_ptr real_node_ptr;
-        typedef BOOST_DEDUCED_TYPENAME buckets::value_type value_type;
-
-        buckets& buckets_;
-        real_node_ptr node_;
-        bool node_constructed_;
-        bool value_constructed_;
-
-    public:
-
-        hash_node_constructor(buckets& m) :
-            buckets_(m),
-            node_(),
-            node_constructed_(false),
-            value_constructed_(false)
-        {
+        T& get() { return value_; }
+        T const& get() const { return value_; }
+    private:
+        T value_;
+    };
+    
+    template <typename T, int Index>
+    struct generate_base
+      : boost::detail::if_true<
+            boost::is_empty<T>::value
+        >:: BOOST_NESTED_TEMPLATE then<
+            compressed_base<T, Index>,
+            uncompressed_base<T, Index>
+        >
+    {};
+    
+    template <typename T1, typename T2>
+    struct compressed_pair
+      : private generate_base<T1, 1>::type,
+        private generate_base<T2, 2>::type
+    {
+        typedef BOOST_DEDUCED_TYPENAME generate_base<T1, 1>::type base1;
+        typedef BOOST_DEDUCED_TYPENAME generate_base<T2, 2>::type base2;
+
+        typedef T1 first_type;
+        typedef T2 second_type;
+        
+        first_type& first() {
+            return static_cast<base1*>(this)->get();
         }
 
-        ~hash_node_constructor();
-        void construct_preamble();
+        first_type const& first() const {
+            return static_cast<base1 const*>(this)->get();
+        }
 
-#if defined(BOOST_UNORDERED_STD_FORWARD)
-        template <class... Args>
-        void construct(Args&&... args)
-        {
-            construct_preamble();
-            construct_impl((value_type*) 0, node_->address(),
-                std::forward<Args>(args)...);
-            value_constructed_ = true;
+        second_type& second() {
+            return static_cast<base2*>(this)->get();
         }
-#else
 
-#define BOOST_UNORDERED_CONSTRUCT(z, num_params, _)                            \
-        template <                                                             \
-            BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)                       \
-        >                                                                      \
-        void construct(                                                        \
-            BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)                     \
-        )                                                                      \
-        {                                                                      \
-            construct_preamble();                                              \
-            construct_impl(                                                    \
-                (value_type*) 0, node_->address(),                             \
-                BOOST_UNORDERED_CALL_PARAMS(z, num_params)                     \
-            );                                                                 \
-            value_constructed_ = true;                                         \
+        second_type const& second() const {
+            return static_cast<base2 const*>(this)->get();
         }
 
-        BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
-            BOOST_UNORDERED_CONSTRUCT, _)
+        template <typename First, typename Second>
+        compressed_pair(First const& x1, Second const& x2)
+            : base1(x1), base2(x2) {}
 
-#undef BOOST_UNORDERED_CONSTRUCT
+        compressed_pair(compressed_pair const& x)
+            : base1(x.first()), base2(x.second()) {}
 
-#endif
-        template <class K, class M>
-        void construct_pair(K const& k, M*)
+        compressed_pair(compressed_pair& x, move_tag m)
+            : base1(x.first(), m), base2(x.second(), m) {}
+
+        void assign(compressed_pair const& x)
         {
-            construct_preamble();
-            new(node_->address()) value_type(k, M());                    
-            value_constructed_ = true;
+            first() = x.first();
+            second() = x.second();
         }
 
-        value_type& value() const
+        void move_assign(compressed_pair& x)
         {
-            BOOST_ASSERT(node_);
-            return node_->value();
+            first() = boost::move(x.first());
+            second() = boost::move(x.second());
         }
-
-        // no throw
-        BOOST_DEDUCED_TYPENAME buckets::node_ptr release()
+        
+        void swap(compressed_pair& x)
         {
-            real_node_ptr p = node_;
-            node_ = real_node_ptr();
-            // node_ptr cast
-            return buckets_.bucket_alloc().address(*p);
+            boost::swap(first(), x.first());
+            boost::swap(second(), x.second());
         }
 
     private:
-        hash_node_constructor(hash_node_constructor const&);
-        hash_node_constructor& operator=(hash_node_constructor const&);
+        // Prevent assignment just to make use of assign or
+        // move_assign explicit.
+        compressed_pair& operator=(compressed_pair const&);
     };
-    
-    // hash_node_constructor
-
-    template <class Alloc, class Grouped>
-    inline hash_node_constructor<Alloc, Grouped>::~hash_node_constructor()
-    {
-        if (node_) {
-            if (value_constructed_) {
-#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
-                struct dummy { hash_node<Alloc, Grouped> x; };
-#endif
-                boost::unordered_detail::destroy(node_->value_ptr());
-            }
-
-            if (node_constructed_)
-                buckets_.node_alloc().destroy(node_);
-
-            buckets_.node_alloc().deallocate(node_, 1);
-        }
-    }
-
-    template <class Alloc, class Grouped>
-    inline void hash_node_constructor<Alloc, Grouped>::construct_preamble()
-    {
-        if(!node_) {
-            node_constructed_ = false;
-            value_constructed_ = false;
-
-            node_ = buckets_.node_alloc().allocate(1);
-            buckets_.node_alloc().construct(node_, node());
-            node_constructed_ = true;
-        }
-        else {
-            BOOST_ASSERT(node_constructed_ && value_constructed_);
-            boost::unordered_detail::destroy(node_->value_ptr());
-            value_constructed_ = false;
-        }
-    }
-}}
+}}}
 
 #endif
Modified: branches/release/boost/unordered/unordered_map.hpp
==============================================================================
--- branches/release/boost/unordered/unordered_map.hpp	(original)
+++ branches/release/boost/unordered/unordered_map.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -1,6 +1,6 @@
 
 // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
-// Copyright (C) 2005-2009 Daniel James.
+// Copyright (C) 2005-2011 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)
 
@@ -19,10 +19,6 @@
 #include <boost/unordered/detail/equivalent.hpp>
 #include <boost/unordered/detail/unique.hpp>
 
-#if defined(BOOST_NO_RVALUE_REFERENCES)
-#include <boost/unordered/detail/move.hpp>
-#endif
-
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
 #include <initializer_list>
 #endif
@@ -38,9 +34,12 @@
 
 namespace boost
 {
+namespace unordered
+{
     template <class K, class T, class H, class P, class A>
     class unordered_map
     {
+        BOOST_COPYABLE_AND_MOVABLE(unordered_map)
     public:
         typedef K key_type;
         typedef std::pair<const K, T> value_type;
@@ -54,42 +53,38 @@
 #endif
 
         typedef BOOST_DEDUCED_TYPENAME
-            boost::unordered_detail::rebind_wrap<
+            ::boost::unordered::detail::rebind_wrap<
                 allocator_type, value_type>::type
             value_allocator;
+        typedef ::boost::unordered::detail::allocator_traits<value_allocator> allocator_traits;
 
-        typedef boost::unordered_detail::map<K, H, P,
+        typedef ::boost::unordered::detail::map<K, H, P,
             value_allocator> types;
         typedef BOOST_DEDUCED_TYPENAME types::impl table;
 
-        typedef BOOST_DEDUCED_TYPENAME types::iterator_base iterator_base;
+        typedef BOOST_DEDUCED_TYPENAME types::node_ptr node_ptr;
 
     public:
 
         typedef BOOST_DEDUCED_TYPENAME
-            value_allocator::pointer pointer;
-        typedef BOOST_DEDUCED_TYPENAME
-            value_allocator::const_pointer const_pointer;
+            allocator_traits::pointer pointer;
         typedef BOOST_DEDUCED_TYPENAME
-            value_allocator::reference reference;
-        typedef BOOST_DEDUCED_TYPENAME
-            value_allocator::const_reference const_reference;
+            allocator_traits::const_pointer const_pointer;
+
+        typedef value_type& reference;
+        typedef value_type const& 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;
-        typedef boost::unordered_detail::hash_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;
-        typedef boost::unordered_detail::hash_iterator<
-            value_allocator, boost::unordered_detail::ungrouped>
-                iterator;
+        typedef ::boost::unordered::iterator_detail::cl_iterator<
+            value_allocator, true> const_local_iterator;
+        typedef ::boost::unordered::iterator_detail::l_iterator<
+            value_allocator, true> local_iterator;
+        typedef ::boost::unordered::iterator_detail::c_iterator<
+            value_allocator, true> const_iterator;
+        typedef ::boost::unordered::iterator_detail::iterator<
+            value_allocator, true> iterator;
 
 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
     private:
@@ -97,131 +92,76 @@
 
         table table_;
         
-        BOOST_DEDUCED_TYPENAME types::iterator_base const&
-            get(const_iterator const& it)
-        {
-            return boost::unordered_detail::iterator_access::get(it);
-        }
-
     public:
 
         // construct/destroy/copy
 
         explicit unordered_map(
-                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)
-        {
-        }
+                size_type = ::boost::unordered::detail::default_bucket_count,
+                const hasher& = hasher(),
+                const key_equal& = key_equal(),
+                const allocator_type& = allocator_type());
 
-        explicit unordered_map(allocator_type const& a)
-          : table_(boost::unordered_detail::default_bucket_count,
-                hasher(), key_equal(), a)
-        {
-        }
+        explicit unordered_map(allocator_type const&);
 
-        unordered_map(unordered_map const& other, allocator_type const& a)
-          : table_(other.table_, a)
-        {
-        }
+        unordered_map(unordered_map const&, allocator_type const&);
 
         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);
-        }
+        unordered_map(InputIt f, InputIt 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_.insert_range(f, l);
-        }
+        unordered_map(
+                InputIt, InputIt,
+                size_type,
+                const hasher& = hasher(),
+                const key_equal& = key_equal());        
 
         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_.insert_range(f, l);
-        }
-
-        ~unordered_map() {}
-
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
-        unordered_map(unordered_map const& other)
-          : table_(other.table_)
-        {
-        }
-
-        unordered_map(unordered_map&& other)
-          : 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())
-        {
-        }
+        unordered_map(
+                InputIt, InputIt,
+                size_type,
+                const hasher&,
+                const key_equal&,
+                const allocator_type&);
+        
+        ~unordered_map();
 
-        unordered_map& operator=(unordered_map const& x)
+        unordered_map& operator=(
+                BOOST_COPY_ASSIGN_REF(unordered_map) x)
         {
-            table_ = x.table_;
+            table_.assign(x.table_);
             return *this;
         }
 
-        unordered_map& operator=(unordered_map&& x)
+        unordered_map(unordered_map const&);
+
+#if BOOST_UNORDERED_USE_RV_REF
+        unordered_map& operator=(
+                BOOST_RV_REF(unordered_map) x)
         {
-            table_.move(x.table_);
+            table_.move_assign(x.table_);
             return *this;
         }
-#else
-        unordered_map(boost::unordered_detail::move_from<
-                unordered_map<K, T, H, P, A>
-            > other)
-          : table_(other.source.table_, boost::unordered_detail::move_tag())
-        {
-        }
 
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0593)
-        unordered_map& operator=(unordered_map x)
+        unordered_map(BOOST_RV_REF(unordered_map) other)
+            : table_(other.table_, ::boost::unordered::detail::move_tag())
         {
-            table_.move(x.table_);
-            return *this;
         }
 #endif
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES)
+        unordered_map(unordered_map&&, allocator_type const&);
 #endif
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
-        unordered_map(std::initializer_list<value_type> list,
-                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, a)
-        {
-            table_.insert_range(list.begin(), list.end());
-        }
+        unordered_map(
+                std::initializer_list<value_type>,
+                size_type = ::boost::unordered::detail::default_bucket_count,
+                const hasher& = hasher(),
+                const key_equal&l = key_equal(),
+                const allocator_type& = allocator_type());
 
-        unordered_map& operator=(std::initializer_list<value_type> list)
-        {
-            table_.clear();
-            table_.insert_range(list.begin(), list.end());
-            return *this;
-        }
+        unordered_map& operator=(std::initializer_list<value_type>);
 #endif
 
         allocator_type get_allocator() const
@@ -241,10 +181,7 @@
             return table_.size_;
         }
 
-        size_type max_size() const
-        {
-            return table_.max_size();
-        }
+        size_type max_size() const;
 
         // iterators
 
@@ -260,12 +197,12 @@
 
         iterator end()
         {
-            return iterator(table_.end());
+            return iterator();
         }
 
         const_iterator end() const
         {
-            return const_iterator(table_.end());
+            return const_iterator();
         }
 
         const_iterator cbegin() const
@@ -275,39 +212,30 @@
 
         const_iterator cend() const
         {
-            return const_iterator(table_.end());
+            return const_iterator();
         }
 
         // modifiers
 
-#if defined(BOOST_UNORDERED_STD_FORWARD)
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
         template <class... Args>
-        std::pair<iterator, bool> emplace(Args&&... args)
-        {
-            return boost::unordered_detail::pair_cast<iterator, bool>(
-                table_.emplace(std::forward<Args>(args)...));
-        }
-
+        std::pair<iterator, bool> emplace(Args&&...);
         template <class... Args>
-        iterator emplace_hint(const_iterator, Args&&... args)
-        {
-            return iterator(table_.emplace(std::forward<Args>(args)...).first);
-        }
+        iterator emplace_hint(const_iterator, Args&&...);
 #else
 
-        #if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
-        std::pair<iterator, bool> emplace(value_type const& v = value_type())
-        {
-            return boost::unordered_detail::pair_cast<iterator, bool>(
-                table_.emplace(v));
-        }
-
+#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
+        std::pair<iterator, bool> emplace(
+                boost::unordered::detail::empty_emplace
+                    = boost::unordered::detail::empty_emplace(),
+                value_type v = value_type()
+            );
         iterator emplace_hint(const_iterator,
-            value_type const& v = value_type())
-        {
-            return iterator(table_.emplace(v).first);
-        }
-        #endif
+                boost::unordered::detail::empty_emplace
+                    = boost::unordered::detail::empty_emplace(),
+                value_type v = value_type()
+            );
+#endif
 
 #define BOOST_UNORDERED_EMPLACE(z, n, _)                                       \
             template <                                                         \
@@ -315,24 +243,14 @@
             >                                                                  \
             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,                              \
                 BOOST_UNORDERED_FUNCTION_PARAMS(z, n)                          \
-            )                                                                  \
-            {                                                                  \
-                return iterator(table_.emplace(                                \
-                    BOOST_UNORDERED_CALL_PARAMS(z, n)).first);                 \
-            }
+            );
 
         BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
             BOOST_UNORDERED_EMPLACE, _)
@@ -341,144 +259,61 @@
 
 #endif
 
-        std::pair<iterator, bool> insert(const value_type& obj)
-        {
-            return boost::unordered_detail::pair_cast<iterator, bool>(
-                    table_.emplace(obj));
-        }
-
-        iterator insert(const_iterator, const value_type& obj)
-        {
-            return iterator(table_.emplace(obj).first);
-        }
-
-        template <class InputIt>
-            void insert(InputIt first, InputIt last)
-        {
-            table_.insert_range(first, last);
-        }
+        std::pair<iterator, bool> insert(value_type const&);
+        iterator insert(const_iterator, value_type const&);
+#if BOOST_UNORDERED_USE_RV_REF
+        std::pair<iterator, bool> insert(BOOST_RV_REF(value_type));
+        iterator insert(const_iterator, BOOST_RV_REF(value_type));
+#endif
+        template <class InputIt> void insert(InputIt, InputIt);
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
-        void insert(std::initializer_list<value_type> list)
-        {
-            table_.insert_range(list.begin(), list.end());
-        }
+        void insert(std::initializer_list<value_type>);
 #endif
 
-        iterator erase(const_iterator position)
-        {
-            return iterator(table_.erase_return_iterator(get(position)));
-        }
-
-        size_type erase(const key_type& k)
-        {
-            return table_.erase_key(k);
-        }
-
-        iterator erase(const_iterator first, const_iterator last)
-        {
-            return iterator(table_.erase_range(get(first), get(last)));
-        }
-
-        void quick_erase(const_iterator position)
-        {
-            table_.erase(get(position));
-        }
-
-        void erase_return_void(const_iterator position)
-        {
-            table_.erase(get(position));
-        }
-
-        void clear()
-        {
-            table_.clear();
-        }
+        iterator erase(const_iterator);
+        size_type erase(const key_type&);
+        iterator erase(const_iterator, const_iterator);
+        void quick_erase(const_iterator it) { erase(it); }
+        void erase_return_void(const_iterator it) { erase(it); }
 
-        void swap(unordered_map& other)
-        {
-            table_.swap(other.table_);
-        }
+        void clear();
+        void swap(unordered_map&);
 
         // observers
 
-        hasher hash_function() const
-        {
-            return table_.hash_function();
-        }
-
-        key_equal key_eq() const
-        {
-            return table_.key_eq();
-        }
-
-        mapped_type& operator[](const key_type &k)
-        {
-            return table_[k].second;
-        }
-
-        mapped_type& at(const key_type& k)
-        {
-            return table_.at(k).second;
-        }
+        hasher hash_function() const;
+        key_equal key_eq() const;
 
-        mapped_type const& at(const key_type& k) const
-        {
-            return table_.at(k).second;
-        }
+        mapped_type& operator[](const key_type&);
+        mapped_type& at(const key_type&);
+        mapped_type const& at(const key_type&) const;
 
         // lookup
 
-        iterator find(const key_type& k)
-        {
-            return iterator(table_.find(k));
-        }
-
-        const_iterator find(const key_type& k) const
-        {
-            return const_iterator(table_.find(k));
-        }
+        iterator find(const key_type&);
+        const_iterator find(const key_type&) const;
 
         template <class CompatibleKey, class CompatibleHash,
             class CompatiblePredicate>
         iterator find(
-            CompatibleKey const& k,
-            CompatibleHash const& hash,
-            CompatiblePredicate const& eq)
-        {
-            return iterator(table_.find(k, hash, eq));
-        }
+                CompatibleKey const&,
+                CompatibleHash const&,
+                CompatiblePredicate const&);
 
         template <class CompatibleKey, class CompatibleHash,
             class CompatiblePredicate>
         const_iterator find(
-            CompatibleKey const& k,
-            CompatibleHash const& hash,
-            CompatiblePredicate const& eq) const
-        {
-            return iterator(table_.find(k, hash, eq));
-        }
+                CompatibleKey const&,
+                CompatibleHash const&,
+                CompatiblePredicate const&) const;
 
-        size_type count(const key_type& k) const
-        {
-            return table_.count(k);
-        }
+        size_type count(const key_type&) const;
 
         std::pair<iterator, iterator>
-            equal_range(const key_type& k)
-        {
-            return boost::unordered_detail::pair_cast<
-                iterator, iterator>(
-                    table_.equal_range(k));
-        }
-
+        equal_range(const key_type&);
         std::pair<const_iterator, const_iterator>
-            equal_range(const key_type& k) const
-        {
-            return boost::unordered_detail::pair_cast<
-                const_iterator, const_iterator>(
-                    table_.equal_range(k));
-        }
+        equal_range(const key_type&) const;
 
         // bucket interface
 
@@ -492,24 +327,23 @@
             return table_.max_bucket_count();
         }
 
-        size_type bucket_size(size_type n) const
-        {
-            return table_.bucket_size(n);
-        }
+        size_type bucket_size(size_type n) const;
 
         size_type bucket(const key_type& k) const
         {
-            return table_.bucket_index(k);
+            return table_.hash_function()(k) % table_.bucket_count_;
         }
 
         local_iterator begin(size_type n)
         {
-            return local_iterator(table_.bucket_begin(n));
+            return local_iterator(
+                table_.bucket_begin(n), n, table_.bucket_count_);
         }
 
         const_local_iterator begin(size_type n) const
         {
-            return const_local_iterator(table_.bucket_begin(n));
+            return const_local_iterator(
+                table_.bucket_begin(n), n, table_.bucket_count_);
         }
 
         local_iterator end(size_type)
@@ -524,7 +358,8 @@
 
         const_local_iterator cbegin(size_type n) const
         {
-            return const_local_iterator(table_.bucket_begin(n));
+            return const_local_iterator(
+                table_.bucket_begin(n), n, table_.bucket_count_);
         }
 
         const_local_iterator cend(size_type) const
@@ -534,67 +369,27 @@
 
         // hash policy
 
-        float load_factor() const
-        {
-            return table_.load_factor();
-        }
-
         float max_load_factor() const
         {
             return table_.mlf_;
         }
 
-        void max_load_factor(float m)
-        {
-            table_.max_load_factor(m);
-        }
+        float load_factor() const;
+        void max_load_factor(float);
+        void rehash(size_type n);
 
-        void rehash(size_type n)
-        {
-            table_.rehash(n);
-        }
-        
 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
-        friend bool operator==<K, T, H, P, A>(
-            unordered_map const&, unordered_map const&);
-        friend bool operator!=<K, T, H, P, A>(
-            unordered_map const&, unordered_map const&);
+        friend bool operator==<K,T,H,P,A>(
+                unordered_map const&, unordered_map const&);
+        friend bool operator!=<K,T,H,P,A>(
+                unordered_map const&, unordered_map const&);
 #endif
     }; // class template unordered_map
 
     template <class K, class T, class H, class P, class A>
-    inline bool operator==(unordered_map<K, T, H, P, A> const& m1,
-        unordered_map<K, T, H, P, A> const& m2)
-    {
-#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
-        struct dummy { unordered_map<K,T,H,P,A> x; };
-#endif
-        return m1.table_.equals(m2.table_);
-    }
-
-    template <class K, class T, class H, class P, class A>
-    inline bool operator!=(unordered_map<K, T, H, P, A> const& m1,
-        unordered_map<K, T, H, P, A> const& m2)
-    {
-#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
-        struct dummy { unordered_map<K,T,H,P,A> x; };
-#endif
-        return !m1.table_.equals(m2.table_);
-    }
-
-    template <class K, class T, class H, class P, class A>
-    inline void swap(unordered_map<K, T, H, P, A> &m1,
-            unordered_map<K, T, H, P, A> &m2)
-    {
-#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
-        struct dummy { unordered_map<K,T,H,P,A> x; };
-#endif
-        m1.swap(m2);
-    }
-
-    template <class K, class T, class H, class P, class A>
     class unordered_multimap
     {
+        BOOST_COPYABLE_AND_MOVABLE(unordered_multimap)
     public:
 
         typedef K key_type;
@@ -609,42 +404,39 @@
 #endif
 
         typedef BOOST_DEDUCED_TYPENAME
-            boost::unordered_detail::rebind_wrap<
+            ::boost::unordered::detail::rebind_wrap<
                 allocator_type, value_type>::type
             value_allocator;
+        typedef ::boost::unordered::detail::allocator_traits<value_allocator>
+            allocator_traits;
 
-        typedef boost::unordered_detail::multimap<K, H, P,
+        typedef ::boost::unordered::detail::multimap<K, H, P,
             value_allocator> types;
         typedef BOOST_DEDUCED_TYPENAME types::impl table;
 
-        typedef BOOST_DEDUCED_TYPENAME types::iterator_base iterator_base;
+        typedef BOOST_DEDUCED_TYPENAME types::node_ptr node_ptr;
 
     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;
+            allocator_traits::pointer pointer;
         typedef BOOST_DEDUCED_TYPENAME
-            value_allocator::const_reference const_reference;
+            allocator_traits::const_pointer const_pointer;
+
+        typedef value_type& reference;
+        typedef value_type const& 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;
-        typedef boost::unordered_detail::hash_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;
-        typedef boost::unordered_detail::hash_iterator<
-            value_allocator, boost::unordered_detail::grouped>
-                iterator;
+        typedef ::boost::unordered::iterator_detail::cl_iterator<
+            value_allocator, false> const_local_iterator;
+        typedef ::boost::unordered::iterator_detail::l_iterator<
+            value_allocator, false> local_iterator;
+        typedef ::boost::unordered::iterator_detail::c_iterator<
+            value_allocator, false> const_iterator;
+        typedef ::boost::unordered::iterator_detail::iterator<
+            value_allocator, false> iterator;
 
 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
     private:
@@ -652,132 +444,76 @@
 
         table table_;
         
-        BOOST_DEDUCED_TYPENAME types::iterator_base const&
-            get(const_iterator const& it)
-        {
-            return boost::unordered_detail::iterator_access::get(it);
-        }
-
     public:
 
         // construct/destroy/copy
 
         explicit unordered_multimap(
-                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)
-        {
-        }
+                size_type = ::boost::unordered::detail::default_bucket_count,
+                const hasher& = hasher(),
+                const key_equal& = key_equal(),
+                const allocator_type& = allocator_type());
 
-        explicit unordered_multimap(allocator_type const& a)
-          : table_(boost::unordered_detail::default_bucket_count,
-                hasher(), key_equal(), a)
-        {
-        }
+        explicit unordered_multimap(allocator_type const&);
 
-        unordered_multimap(unordered_multimap const& other,
-            allocator_type const& a)
-          : table_(other.table_, a)
-        {
-        }
+        unordered_multimap(unordered_multimap const&, allocator_type const&);
 
         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);
-        }
+        unordered_multimap(InputIt, InputIt);
 
         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_.insert_range(f, l);
-        }
+        unordered_multimap(
+                InputIt, InputIt,
+                size_type,
+                const hasher& = hasher(),
+                const key_equal& = key_equal());
 
         template <class InputIt>
-        unordered_multimap(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_.insert_range(f, l);
-        }
+        unordered_multimap(
+                InputIt, InputIt,
+                size_type,
+                const hasher&,
+                const key_equal&,
+                const allocator_type&);
 
-        ~unordered_multimap() {}
+        ~unordered_multimap();
 
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
-        unordered_multimap(unordered_multimap const& other)
-          : table_(other.table_)
-        {
-        }
-
-        unordered_multimap(unordered_multimap&& other)
-          : 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())
-        {
-        }
-
-        unordered_multimap& operator=(unordered_multimap const& x)
+        unordered_multimap& operator=(
+                BOOST_COPY_ASSIGN_REF(unordered_multimap) x)
         {
-            table_ = x.table_;
+            table_.assign(x.table_);
             return *this;
         }
 
-        unordered_multimap& operator=(unordered_multimap&& x)
+        unordered_multimap(unordered_multimap const&);
+
+#if BOOST_UNORDERED_USE_RV_REF
+        unordered_multimap& operator=(
+                BOOST_RV_REF(unordered_multimap) x)
         {
-            table_.move(x.table_);
+            table_.move_assign(x.table_);
             return *this;
         }
-#else
-        unordered_multimap(boost::unordered_detail::move_from<
-                unordered_multimap<K, T, H, P, A>
-            > other)
-          : table_(other.source.table_, boost::unordered_detail::move_tag())
-        {
-        }
 
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0593)
-        unordered_multimap& operator=(unordered_multimap x)
+        unordered_multimap(BOOST_RV_REF(unordered_multimap) other)
+            : table_(other.table_, ::boost::unordered::detail::move_tag())
         {
-            table_.move(x.table_);
-            return *this;
         }
 #endif
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES)
+        unordered_multimap(unordered_multimap&&, allocator_type const&);
 #endif
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
-        unordered_multimap(std::initializer_list<value_type> list,
-                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, a)
-        {
-            table_.insert_range(list.begin(), list.end());
-        }
+        unordered_multimap(
+                std::initializer_list<value_type>,
+                size_type = ::boost::unordered::detail::default_bucket_count,
+                const hasher& = hasher(),
+                const key_equal&l = key_equal(),
+                const allocator_type& = allocator_type());
 
-        unordered_multimap& operator=(std::initializer_list<value_type> list)
-        {
-            table_.clear();
-            table_.insert_range(list.begin(), list.end());
-            return *this;
-        }
+        unordered_multimap& operator=(std::initializer_list<value_type>);
 #endif
 
         allocator_type get_allocator() const
@@ -797,10 +533,7 @@
             return table_.size_;
         }
 
-        size_type max_size() const
-        {
-            return table_.max_size();
-        }
+        size_type max_size() const;
 
         // iterators
 
@@ -816,12 +549,12 @@
 
         iterator end()
         {
-            return iterator(table_.end());
+            return iterator();
         }
 
         const_iterator end() const
         {
-            return const_iterator(table_.end());
+            return const_iterator();
         }
 
         const_iterator cbegin() const
@@ -831,37 +564,30 @@
 
         const_iterator cend() const
         {
-            return const_iterator(table_.end());
+            return const_iterator();
         }
 
         // modifiers
 
-#if defined(BOOST_UNORDERED_STD_FORWARD)
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
         template <class... Args>
-        iterator emplace(Args&&... args)
-        {
-            return iterator(table_.emplace(std::forward<Args>(args)...));
-        }
-
+        iterator emplace(Args&&...);
         template <class... Args>
-        iterator emplace_hint(const_iterator, Args&&... args)
-        {
-            return iterator(table_.emplace(std::forward<Args>(args)...));
-        }
+        iterator emplace_hint(const_iterator, Args&&...);
 #else
 
-        #if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
-        iterator emplace(value_type const& v = value_type())
-        {
-            return iterator(table_.emplace(v));
-        }
-        
+#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
+        iterator emplace(
+                boost::unordered::detail::empty_emplace
+                    = boost::unordered::detail::empty_emplace(),
+                value_type v = value_type()
+            );
         iterator emplace_hint(const_iterator,
-            value_type const& v = value_type())
-        {
-            return iterator(table_.emplace(v));
-        }
-        #endif
+                boost::unordered::detail::empty_emplace
+                    = boost::unordered::detail::empty_emplace(),
+                value_type v = value_type()
+            );
+#endif
 
 #define BOOST_UNORDERED_EMPLACE(z, n, _)                                       \
             template <                                                         \
@@ -869,25 +595,14 @@
             >                                                                  \
             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,                              \
                 BOOST_UNORDERED_FUNCTION_PARAMS(z, n)                          \
-            )                                                                  \
-            {                                                                  \
-                return iterator(table_.emplace(                                \
-                        BOOST_UNORDERED_CALL_PARAMS(z, n)                      \
-                ));                                                            \
-            }
+            );
 
         BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
             BOOST_UNORDERED_EMPLACE, _)
@@ -896,214 +611,956 @@
 
 #endif
 
-        iterator insert(const value_type& obj)
+        iterator insert(value_type const&);
+        iterator insert(const_iterator, value_type const&);
+#if BOOST_UNORDERED_USE_RV_REF
+        iterator insert(BOOST_RV_REF(value_type));
+        iterator insert(const_iterator, BOOST_RV_REF(value_type));
+#endif
+        template <class InputIt> void insert(InputIt, InputIt);
+
+#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
+        void insert(std::initializer_list<value_type>);
+#endif
+
+        iterator erase(const_iterator);
+        size_type erase(const key_type&);
+        iterator erase(const_iterator, const_iterator);
+        void quick_erase(const_iterator position) { erase(position); }
+        void erase_return_void(const_iterator position) { erase(position); }
+
+        void clear();
+        void swap(unordered_multimap&);
+
+        // observers
+
+        hasher hash_function() const;
+        key_equal key_eq() const;
+
+        // lookup
+
+        iterator find(const key_type&);
+        const_iterator find(const key_type&) const;
+
+        template <class CompatibleKey, class CompatibleHash,
+            class CompatiblePredicate>
+        iterator find(
+                CompatibleKey const&,
+                CompatibleHash const&,
+                CompatiblePredicate const&);
+
+        template <class CompatibleKey, class CompatibleHash,
+            class CompatiblePredicate>
+        const_iterator find(
+                CompatibleKey const&,
+                CompatibleHash const&,
+                CompatiblePredicate const&) const;
+
+        size_type count(const key_type&) const;
+
+        std::pair<iterator, iterator>
+        equal_range(const key_type&);
+        std::pair<const_iterator, const_iterator>
+        equal_range(const key_type&) const;
+
+        // bucket interface
+
+        size_type bucket_count() const
         {
-            return iterator(table_.emplace(obj));
+            return table_.bucket_count_;
         }
 
-        iterator insert(const_iterator, const value_type& obj)
+        size_type max_bucket_count() const
         {
-            return iterator(table_.emplace(obj));
+            return table_.max_bucket_count();
         }
 
-        template <class InputIt>
-            void insert(InputIt first, InputIt last)
+        size_type bucket_size(size_type) const;
+
+        size_type bucket(const key_type& k) const
         {
-            table_.insert_range(first, last);
+            return table_.hash_function()(k) % table_.bucket_count_;
         }
 
-#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
-        void insert(std::initializer_list<value_type> list)
+        local_iterator begin(size_type n)
         {
-            table_.insert_range(list.begin(), list.end());
+            return local_iterator(
+                table_.bucket_begin(n), n, table_.bucket_count_);
         }
-#endif
 
-        iterator erase(const_iterator position)
+        const_local_iterator begin(size_type n) const
         {
-            return iterator(table_.erase_return_iterator(get(position)));
+            return const_local_iterator(
+                table_.bucket_begin(n), n, table_.bucket_count_);
         }
 
-        size_type erase(const key_type& k)
+        local_iterator end(size_type)
         {
-            return table_.erase_key(k);
+            return local_iterator();
         }
 
-        iterator erase(const_iterator first, const_iterator last)
+        const_local_iterator end(size_type) const
         {
-            return iterator(table_.erase_range(get(first), get(last)));
+            return const_local_iterator();
         }
 
-        void quick_erase(const_iterator position)
+        const_local_iterator cbegin(size_type n) const
         {
-            table_.erase(get(position));
+            return const_local_iterator(
+                table_.bucket_begin(n), n, table_.bucket_count_);
         }
 
-        void erase_return_void(const_iterator position)
+        const_local_iterator cend(size_type) const
         {
-            table_.erase(get(position));
+            return const_local_iterator();
         }
 
-        void clear()
-        {
-            table_.clear();
-        }
+        // hash policy
 
-        void swap(unordered_multimap& other)
+        float max_load_factor() const
         {
-            table_.swap(other.table_);
+            return table_.mlf_;
         }
 
-        // observers
+        float load_factor() const;
+        void max_load_factor(float);
+        void rehash(size_type);
 
-        hasher hash_function() const
-        {
-            return table_.hash_function();
-        }
+#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
+        friend bool operator==<K,T,H,P,A>(
+            unordered_multimap const&, unordered_multimap const&);
+        friend bool operator!=<K,T,H,P,A>(
+            unordered_multimap const&, unordered_multimap const&);
+#endif
+    }; // class template unordered_multimap
 
-        key_equal key_eq() const
-        {
-            return table_.key_eq();
-        }
+////////////////////////////////////////////////////////////////////////////////
 
-        // lookup
+    template <class K, class T, class H, class P, class A>
+    unordered_map<K,T,H,P,A>::unordered_map(
+            size_type n, const hasher &hf, const key_equal &eql,
+            const allocator_type &a)
+      : table_(n, hf, eql, a)
+    {
+    }
 
-        iterator find(const key_type& k)
-        {
-            return iterator(table_.find(k));
-        }
+    template <class K, class T, class H, class P, class A>
+    unordered_map<K,T,H,P,A>::unordered_map(allocator_type const& a)
+      : table_(::boost::unordered::detail::default_bucket_count,
+            hasher(), key_equal(), a)
+    {
+    }
 
-        const_iterator find(const key_type& k) const
-        {
-            return const_iterator(table_.find(k));
+    template <class K, class T, class H, class P, class A>
+    unordered_map<K,T,H,P,A>::unordered_map(
+            unordered_map const& other, allocator_type const& a)
+      : table_(other.table_, a)
+    {
+    }
+
+    template <class K, class T, class H, class P, class A>
+    template <class InputIt>
+    unordered_map<K,T,H,P,A>::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 K, class T, class H, class P, class A>
+    template <class InputIt>
+    unordered_map<K,T,H,P,A>::unordered_map(
+            InputIt f, InputIt l,
+            size_type n,
+            const hasher &hf,
+            const key_equal &eql)
+      : table_(::boost::unordered::detail::initial_size(f, l, n),
+            hf, eql, allocator_type())
+    {
+        table_.insert_range(f, l);
+    }
+    
+    template <class K, class T, class H, class P, class A>
+    template <class InputIt>
+    unordered_map<K,T,H,P,A>::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_.insert_range(f, l);
+    }
+    
+    template <class K, class T, class H, class P, class A>
+    unordered_map<K,T,H,P,A>::~unordered_map() {}
+
+    template <class K, class T, class H, class P, class A>
+    unordered_map<K,T,H,P,A>::unordered_map(unordered_map const& other)
+      : table_(other.table_)
+    {
+    }
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES)
+
+    template <class K, class T, class H, class P, class A>
+    unordered_map<K,T,H,P,A>::unordered_map(
+            unordered_map&& other, allocator_type const& a)
+      : table_(other.table_, a, ::boost::unordered::detail::move_tag())
+    {
+    }
+
+#endif
+
+#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
+
+    template <class K, class T, class H, class P, class A>
+    unordered_map<K,T,H,P,A>::unordered_map(
+            std::initializer_list<value_type> list, size_type n,
+            const hasher &hf, const key_equal &eql, const allocator_type &a)
+      : table_(
+            ::boost::unordered::detail::initial_size(
+                list.begin(), list.end(), n),
+            hf, eql, a)
+    {
+        table_.insert_range(list.begin(), list.end());
+    }
+
+    template <class K, class T, class H, class P, class A>
+    unordered_map<K,T,H,P,A>& unordered_map<K,T,H,P,A>::operator=(
+            std::initializer_list<value_type> list)
+    {
+        table_.clear();
+        table_.insert_range(list.begin(), list.end());
+        return *this;
+    }
+
+#endif
+
+    // size and capacity
+
+    template <class K, class T, class H, class P, class A>
+    std::size_t unordered_map<K,T,H,P,A>::max_size() const
+    {
+        return table_.max_size();
+    }
+
+    // modifiers
+
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+    template <class K, class T, class H, class P, class A>
+    template <class... Args>
+    std::pair<BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator, bool>
+        unordered_map<K,T,H,P,A>::emplace(Args&&... args)
+    {
+        return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
+            table_.emplace(std::forward<Args>(args)...));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    template <class... Args>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
+        unordered_map<K,T,H,P,A>::emplace_hint(const_iterator, Args&&... args)
+    {
+        return iterator(table_.emplace(std::forward<Args>(args)...).first);
+    }
+#else
+
+#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
+    template <class K, class T, class H, class P, class A>
+    std::pair<BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator, bool>
+        unordered_map<K,T,H,P,A>::emplace(
+                boost::unordered::detail::empty_emplace,
+                value_type v
+            )
+    {
+        return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
+                table_.emplace(boost::move(v)));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
+        unordered_map<K,T,H,P,A>::emplace_hint(const_iterator,
+                boost::unordered::detail::empty_emplace,
+                value_type v
+            )
+    {
+        return iterator(table_.emplace(boost::move(v)).first);
+    }
+#endif
+
+#define BOOST_UNORDERED_EMPLACE(z, n, _)                                    \
+        template <class K, class T, class H, class P, class A>              \
+        template <                                                          \
+            BOOST_UNORDERED_TEMPLATE_ARGS(z, n)                             \
+        >                                                                   \
+        std::pair<                                                          \
+                BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator,  \
+                bool>                                                       \
+            unordered_map<K,T,H,P,A>::emplace(                              \
+                BOOST_UNORDERED_FUNCTION_PARAMS(z, n))                      \
+        {                                                                   \
+            return                                                          \
+                BOOST_UNORDERED_PAIR_CAST(iterator, bool,                   \
+                    table_.emplace(                                         \
+                        BOOST_UNORDERED_CALL_PARAMS(z, n)));                \
+        }                                                                   \
+                                                                            \
+        template <class K, class T, class H, class P, class A>              \
+        template <                                                          \
+            BOOST_UNORDERED_TEMPLATE_ARGS(z, n)                             \
+        >                                                                   \
+        BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator           \
+            unordered_map<K,T,H,P,A>::emplace_hint(                         \
+                const_iterator,                                             \
+                BOOST_UNORDERED_FUNCTION_PARAMS(z, n)                       \
+        )                                                                   \
+        {                                                                   \
+            return iterator(table_.emplace(                                 \
+                BOOST_UNORDERED_CALL_PARAMS(z, n)).first);                  \
         }
 
-        template <class CompatibleKey, class CompatibleHash,
-            class CompatiblePredicate>
-        iterator find(
+    BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
+        BOOST_UNORDERED_EMPLACE, _)
+
+#undef BOOST_UNORDERED_EMPLACE
+
+#endif
+
+    template <class K, class T, class H, class P, class A>
+    std::pair<BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator, bool>
+        unordered_map<K,T,H,P,A>::insert(value_type const& obj)
+    {
+        return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
+                table_.emplace(obj));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
+        unordered_map<K,T,H,P,A>::insert(const_iterator,
+                value_type const& obj)
+    {
+        return iterator(table_.emplace(obj).first);
+    }
+
+#if BOOST_UNORDERED_USE_RV_REF
+    template <class K, class T, class H, class P, class A>
+    std::pair<BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator, bool>
+        unordered_map<K,T,H,P,A>::insert(BOOST_RV_REF(value_type) obj)
+    {
+        return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
+                table_.emplace(boost::move(obj)));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
+        unordered_map<K,T,H,P,A>::insert(const_iterator,
+                BOOST_RV_REF(value_type) obj)
+    {
+        return iterator(table_.emplace(boost::move(obj)).first);
+    }
+#endif
+
+    template <class K, class T, class H, class P, class A>
+    template <class InputIt>
+    void unordered_map<K,T,H,P,A>::insert(InputIt first, InputIt last)
+    {
+        table_.insert_range(first, last);
+    }
+
+#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
+    template <class K, class T, class H, class P, class A>
+    void unordered_map<K,T,H,P,A>::insert(
+            std::initializer_list<value_type> list)
+    {
+        table_.insert_range(list.begin(), list.end());
+    }
+#endif
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
+        unordered_map<K,T,H,P,A>::erase(const_iterator position)
+    {
+        return iterator(table_.erase(position.node_));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::size_type
+        unordered_map<K,T,H,P,A>::erase(const key_type& k)
+    {
+        return table_.erase_key(k);
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
+        unordered_map<K,T,H,P,A>::erase(
+            const_iterator first, const_iterator last)
+    {
+        return iterator(table_.erase_range(first.node_, last.node_));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    void unordered_map<K,T,H,P,A>::clear()
+    {
+        table_.clear();
+    }
+
+    template <class K, class T, class H, class P, class A>
+    void unordered_map<K,T,H,P,A>::swap(unordered_map& other)
+    {
+        table_.swap(other.table_);
+    }
+
+    // observers
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::hasher
+        unordered_map<K,T,H,P,A>::hash_function() const
+    {
+        return table_.hash_function();
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::key_equal
+        unordered_map<K,T,H,P,A>::key_eq() const
+    {
+        return table_.key_eq();
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::mapped_type&
+        unordered_map<K,T,H,P,A>::operator[](const key_type &k)
+    {
+        return table_[k].second;
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::mapped_type&
+        unordered_map<K,T,H,P,A>::at(const key_type& k)
+    {
+        return table_.at(k).second;
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::mapped_type const&
+        unordered_map<K,T,H,P,A>::at(const key_type& k) const
+    {
+        return table_.at(k).second;
+    }
+
+    // lookup
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
+        unordered_map<K,T,H,P,A>::find(const key_type& k)
+    {
+        return iterator(table_.find_node(k));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::const_iterator
+        unordered_map<K,T,H,P,A>::find(const key_type& k) const
+    {
+        return const_iterator(table_.find_node(k));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    template <class CompatibleKey, class CompatibleHash,
+        class CompatiblePredicate>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
+        unordered_map<K,T,H,P,A>::find(
             CompatibleKey const& k,
             CompatibleHash const& hash,
             CompatiblePredicate const& eq)
-        {
-            return iterator(table_.find(k, hash, eq));
-        }
+    {
+        return iterator(table_.generic_find_node(k, hash, eq));
+    }
 
-        template <class CompatibleKey, class CompatibleHash,
-            class CompatiblePredicate>
-        const_iterator find(
+    template <class K, class T, class H, class P, class A>
+    template <class CompatibleKey, class CompatibleHash,
+        class CompatiblePredicate>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::const_iterator
+        unordered_map<K,T,H,P,A>::find(
             CompatibleKey const& k,
             CompatibleHash const& hash,
             CompatiblePredicate const& eq) const
-        {
-            return iterator(table_.find(k, hash, eq));
-        }
+    {
+        return const_iterator(table_.generic_find_node(k, hash, eq));
+    }
 
-        size_type count(const key_type& k) const
-        {
-            return table_.count(k);
-        }
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::size_type
+        unordered_map<K,T,H,P,A>::count(const key_type& k) const
+    {
+        return table_.count(k);
+    }
 
-        std::pair<iterator, iterator>
-            equal_range(const key_type& k)
-        {
-            return boost::unordered_detail::pair_cast<
-                iterator, iterator>(
-                    table_.equal_range(k));
-        }
+    template <class K, class T, class H, class P, class A>
+    std::pair<
+            BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator,
+            BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator>
+        unordered_map<K,T,H,P,A>::equal_range(const key_type& k)
+    {
+        return BOOST_UNORDERED_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>(
-                    table_.equal_range(k));
-        }
+    template <class K, class T, class H, class P, class A>
+    std::pair<
+            BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::const_iterator,
+            BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::const_iterator>
+        unordered_map<K,T,H,P,A>::equal_range(const key_type& k) const
+    {
+        return BOOST_UNORDERED_PAIR_CAST(const_iterator, const_iterator,
+            table_.equal_range(k));
+    }
 
-        // bucket interface
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::size_type
+        unordered_map<K,T,H,P,A>::bucket_size(size_type n) const
+    {
+        return table_.bucket_size(n);
+    }
 
-        size_type bucket_count() const
-        {
-            return table_.bucket_count_;
-        }
+    // hash policy
 
-        size_type max_bucket_count() const
-        {
-            return table_.max_bucket_count();
-        }
+    template <class K, class T, class H, class P, class A>
+    float unordered_map<K,T,H,P,A>::load_factor() const
+    {
+        return table_.load_factor();
+    }
 
-        size_type bucket_size(size_type n) const
-        {
-            return table_.bucket_size(n);
-        }
+    template <class K, class T, class H, class P, class A>
+    void unordered_map<K,T,H,P,A>::max_load_factor(float m)
+    {
+        table_.max_load_factor(m);
+    }
 
-        size_type bucket(const key_type& k) const
-        {
-            return table_.bucket_index(k);
-        }
+    template <class K, class T, class H, class P, class A>
+    void unordered_map<K,T,H,P,A>::rehash(size_type n)
+    {
+        table_.rehash(n);
+    }
 
-        local_iterator begin(size_type n)
-        {
-            return local_iterator(table_.bucket_begin(n));
-        }
+    template <class K, class T, class H, class P, class A>
+    inline bool operator==(
+            unordered_map<K,T,H,P,A> const& m1,
+            unordered_map<K,T,H,P,A> const& m2)
+    {
+#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
+        struct dummy { unordered_map<K,T,H,P,A> x; };
+#endif
+        return m1.table_.equals(m2.table_);
+    }
 
-        const_local_iterator begin(size_type n) const
-        {
-            return const_local_iterator(table_.bucket_begin(n));
-        }
+    template <class K, class T, class H, class P, class A>
+    inline bool operator!=(
+            unordered_map<K,T,H,P,A> const& m1,
+            unordered_map<K,T,H,P,A> const& m2)
+    {
+#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
+        struct dummy { unordered_map<K,T,H,P,A> x; };
+#endif
+        return !m1.table_.equals(m2.table_);
+    }
 
-        local_iterator end(size_type)
-        {
-            return local_iterator();
-        }
+    template <class K, class T, class H, class P, class A>
+    inline void swap(
+            unordered_map<K,T,H,P,A> &m1,
+            unordered_map<K,T,H,P,A> &m2)
+    {
+#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
+        struct dummy { unordered_map<K,T,H,P,A> x; };
+#endif
+        m1.swap(m2);
+    }
 
-        const_local_iterator end(size_type) const
-        {
-            return const_local_iterator();
-        }
+////////////////////////////////////////////////////////////////////////////////
 
-        const_local_iterator cbegin(size_type n) const
-        {
-            return const_local_iterator(table_.bucket_begin(n));
-        }
+    template <class K, class T, class H, class P, class A>
+    unordered_multimap<K,T,H,P,A>::unordered_multimap(
+            size_type n, const hasher &hf, const key_equal &eql,
+            const allocator_type &a)
+      : table_(n, hf, eql, a)
+    {
+    }
 
-        const_local_iterator cend(size_type) const
-        {
-            return const_local_iterator();
-        }
+    template <class K, class T, class H, class P, class A>
+    unordered_multimap<K,T,H,P,A>::unordered_multimap(allocator_type const& a)
+      : table_(::boost::unordered::detail::default_bucket_count,
+            hasher(), key_equal(), a)
+    {
+    }
 
-        // hash policy
+    template <class K, class T, class H, class P, class A>
+    unordered_multimap<K,T,H,P,A>::unordered_multimap(
+            unordered_multimap const& other, allocator_type const& a)
+      : table_(other.table_, a)
+    {
+    }
 
-        float load_factor() const
-        {
-            return table_.load_factor();
-        }
+    template <class K, class T, class H, class P, class A>
+    template <class InputIt>
+    unordered_multimap<K,T,H,P,A>::unordered_multimap(InputIt f, InputIt l)
+      : table_(::boost::unordered::detail::initial_size(f, l),
+        hasher(), key_equal(), allocator_type())
+    {
+        table_.insert_range(f, l);
+    }
 
-        float max_load_factor() const
-        {
-            return table_.mlf_;
-        }
+    template <class K, class T, class H, class P, class A>
+    template <class InputIt>
+    unordered_multimap<K,T,H,P,A>::unordered_multimap(
+            InputIt f, InputIt l,
+            size_type n,
+            const hasher &hf,
+            const key_equal &eql)
+      : table_(::boost::unordered::detail::initial_size(f, l, n),
+            hf, eql, allocator_type())
+    {
+        table_.insert_range(f, l);
+    }
+    
+    template <class K, class T, class H, class P, class A>
+    template <class InputIt>
+    unordered_multimap<K,T,H,P,A>::unordered_multimap(
+            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_.insert_range(f, l);
+    }
+    
+    template <class K, class T, class H, class P, class A>
+    unordered_multimap<K,T,H,P,A>::~unordered_multimap() {}
 
-        void max_load_factor(float m)
-        {
-            table_.max_load_factor(m);
-        }
+    template <class K, class T, class H, class P, class A>
+    unordered_multimap<K,T,H,P,A>::unordered_multimap(
+            unordered_multimap const& other)
+      : table_(other.table_)
+    {
+    }
 
-        void rehash(size_type n)
-        {
-            table_.rehash(n);
+#if !defined(BOOST_NO_RVALUE_REFERENCES)
+
+    template <class K, class T, class H, class P, class A>
+    unordered_multimap<K,T,H,P,A>::unordered_multimap(
+            unordered_multimap&& other, allocator_type const& a)
+      : table_(other.table_, a, ::boost::unordered::detail::move_tag())
+    {
+    }
+
+#endif
+
+#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
+    template <class K, class T, class H, class P, class A>
+    unordered_multimap<K,T,H,P,A>::unordered_multimap(
+            std::initializer_list<value_type> list, size_type n,
+            const hasher &hf, const key_equal &eql, const allocator_type &a)
+      : table_(
+            ::boost::unordered::detail::initial_size(
+                list.begin(), list.end(), n),
+            hf, eql, a)
+    {
+        table_.insert_range(list.begin(), list.end());
+    }
+
+    template <class K, class T, class H, class P, class A>
+    unordered_multimap<K,T,H,P,A>& unordered_multimap<K,T,H,P,A>::operator=(
+            std::initializer_list<value_type> list)
+    {
+        table_.clear();
+        table_.insert_range(list.begin(), list.end());
+        return *this;
+    }
+#endif
+
+    // size and capacity
+
+    template <class K, class T, class H, class P, class A>
+    std::size_t unordered_multimap<K,T,H,P,A>::max_size() const
+    {
+        return table_.max_size();
+    }
+
+    // modifiers
+
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+
+    template <class K, class T, class H, class P, class A>
+    template <class... Args>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+        unordered_multimap<K,T,H,P,A>::emplace(Args&&... args)
+    {
+        return iterator(table_.emplace(std::forward<Args>(args)...));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    template <class... Args>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+        unordered_multimap<K,T,H,P,A>::emplace_hint(
+            const_iterator, Args&&... args)
+    {
+        return iterator(table_.emplace(std::forward<Args>(args)...));
+    }
+
+#else
+
+#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+        unordered_multimap<K,T,H,P,A>::emplace(
+                boost::unordered::detail::empty_emplace,
+                value_type v
+            )
+    {
+        return iterator(table_.emplace(boost::move(v)));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+        unordered_multimap<K,T,H,P,A>::emplace_hint(const_iterator,
+                boost::unordered::detail::empty_emplace,
+                value_type v
+            )
+    {
+        return iterator(table_.emplace(boost::move(v)));
+    }
+#endif
+
+#define BOOST_UNORDERED_EMPLACE(z, n, _)                                    \
+        template <class K, class T, class H, class P, class A>              \
+        template <                                                          \
+            BOOST_UNORDERED_TEMPLATE_ARGS(z, n)                             \
+        >                                                                   \
+        BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator      \
+            unordered_multimap<K,T,H,P,A>::emplace(                         \
+                BOOST_UNORDERED_FUNCTION_PARAMS(z, n))                      \
+        {                                                                   \
+            return iterator(table_.emplace(                                 \
+                BOOST_UNORDERED_CALL_PARAMS(z, n)));                        \
+        }                                                                   \
+                                                                            \
+        template <class K, class T, class H, class P, class A>              \
+        template <                                                          \
+            BOOST_UNORDERED_TEMPLATE_ARGS(z, n)                             \
+        >                                                                   \
+        BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator      \
+            unordered_multimap<K,T,H,P,A>::emplace_hint(                    \
+                const_iterator,                                             \
+                BOOST_UNORDERED_FUNCTION_PARAMS(z, n))                      \
+        {                                                                   \
+            return iterator(table_.emplace(                                 \
+                BOOST_UNORDERED_CALL_PARAMS(z, n)));                        \
         }
 
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
-        friend bool operator==<K, T, H, P, A>(
-            unordered_multimap const&, unordered_multimap const&);
-        friend bool operator!=<K, T, H, P, A>(
-            unordered_multimap const&, unordered_multimap const&);
+    BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
+        BOOST_UNORDERED_EMPLACE, _)
+
+#undef BOOST_UNORDERED_EMPLACE
+
 #endif
-    }; // class template unordered_multimap
 
     template <class K, class T, class H, class P, class A>
-    inline bool operator==(unordered_multimap<K, T, H, P, A> const& m1,
-        unordered_multimap<K, T, H, P, A> const& m2)
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+        unordered_multimap<K,T,H,P,A>::insert(value_type const& obj)
+    {
+        return iterator(table_.emplace(obj));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+        unordered_multimap<K,T,H,P,A>::insert(
+            const_iterator, value_type const& obj)
+    {
+        return iterator(table_.emplace(obj));
+    }
+
+#if BOOST_UNORDERED_USE_RV_REF
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+        unordered_multimap<K,T,H,P,A>::insert(BOOST_RV_REF(value_type) obj)
+    {
+        return iterator(table_.emplace(boost::move(obj)));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+        unordered_multimap<K,T,H,P,A>::insert(
+            const_iterator, BOOST_RV_REF(value_type) obj)
+    {
+        return iterator(table_.emplace(boost::move(obj)));
+    }
+#endif
+
+    template <class K, class T, class H, class P, class A>
+    template <class InputIt>
+    void unordered_multimap<K,T,H,P,A>::insert(InputIt first, InputIt last)
+    {
+        table_.insert_range(first, last);
+    }
+
+#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
+    template <class K, class T, class H, class P, class A>
+    void unordered_multimap<K,T,H,P,A>::insert(
+            std::initializer_list<value_type> list)
+    {
+        table_.insert_range(list.begin(), list.end());
+    }
+#endif
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+        unordered_multimap<K,T,H,P,A>::erase(const_iterator position)
+    {
+        return iterator(table_.erase(position.node_));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::size_type
+        unordered_multimap<K,T,H,P,A>::erase(const key_type& k)
+    {
+        return table_.erase_key(k);
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+        unordered_multimap<K,T,H,P,A>::erase(
+            const_iterator first, const_iterator last)
+    {
+        return iterator(table_.erase_range(first.node_, last.node_));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    void unordered_multimap<K,T,H,P,A>::clear()
+    {
+        table_.clear();
+    }
+
+    template <class K, class T, class H, class P, class A>
+    void unordered_multimap<K,T,H,P,A>::swap(unordered_multimap& other)
+    {
+        table_.swap(other.table_);
+    }
+
+    // observers
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::hasher
+        unordered_multimap<K,T,H,P,A>::hash_function() const
+    {
+        return table_.hash_function();
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::key_equal
+        unordered_multimap<K,T,H,P,A>::key_eq() const
+    {
+        return table_.key_eq();
+    }
+
+    // lookup
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+        unordered_multimap<K,T,H,P,A>::find(const key_type& k)
+    {
+        return iterator(table_.find_node(k));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::const_iterator
+        unordered_multimap<K,T,H,P,A>::find(const key_type& k) const
+    {
+        return const_iterator(table_.find_node(k));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    template <class CompatibleKey, class CompatibleHash,
+        class CompatiblePredicate>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+        unordered_multimap<K,T,H,P,A>::find(
+            CompatibleKey const& k,
+            CompatibleHash const& hash,
+            CompatiblePredicate const& eq)
+    {
+        return iterator(table_.generic_find_node(k, hash, eq));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    template <class CompatibleKey, class CompatibleHash,
+        class CompatiblePredicate>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::const_iterator
+        unordered_multimap<K,T,H,P,A>::find(
+            CompatibleKey const& k,
+            CompatibleHash const& hash,
+            CompatiblePredicate const& eq) const
+    {
+        return const_iterator(table_.generic_find_node(k, hash, eq));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::size_type
+        unordered_multimap<K,T,H,P,A>::count(const key_type& k) const
+    {
+        return table_.count(k);
+    }
+
+    template <class K, class T, class H, class P, class A>
+    std::pair<
+            BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator,
+            BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator>
+        unordered_multimap<K,T,H,P,A>::equal_range(const key_type& k)
+    {
+        return BOOST_UNORDERED_PAIR_CAST(iterator, iterator,
+            table_.equal_range(k));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    std::pair<
+            BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::const_iterator,
+            BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::const_iterator>
+        unordered_multimap<K,T,H,P,A>::equal_range(const key_type& k) const
+    {
+        return BOOST_UNORDERED_PAIR_CAST(const_iterator, const_iterator,
+            table_.equal_range(k));
+    }
+
+    template <class K, class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::size_type
+        unordered_multimap<K,T,H,P,A>::bucket_size(size_type n) const
+    {
+        return table_.bucket_size(n);
+    }
+
+    // hash policy
+
+    template <class K, class T, class H, class P, class A>
+    float unordered_multimap<K,T,H,P,A>::load_factor() const
+    {
+        return table_.load_factor();
+    }
+
+    template <class K, class T, class H, class P, class A>
+    void unordered_multimap<K,T,H,P,A>::max_load_factor(float m)
+    {
+        table_.max_load_factor(m);
+    }
+
+    template <class K, class T, class H, class P, class A>
+    void unordered_multimap<K,T,H,P,A>::rehash(size_type n)
+    {
+        table_.rehash(n);
+    }
+
+    template <class K, class T, class H, class P, class A>
+    inline bool operator==(
+            unordered_multimap<K,T,H,P,A> const& m1,
+            unordered_multimap<K,T,H,P,A> const& m2)
     {
 #if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
         struct dummy { unordered_multimap<K,T,H,P,A> x; };
@@ -1112,8 +1569,9 @@
     }
 
     template <class K, class T, class H, class P, class A>
-    inline bool operator!=(unordered_multimap<K, T, H, P, A> const& m1,
-        unordered_multimap<K, T, H, P, A> const& m2)
+    inline bool operator!=(
+            unordered_multimap<K,T,H,P,A> const& m1,
+            unordered_multimap<K,T,H,P,A> const& m2)
     {
 #if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
         struct dummy { unordered_multimap<K,T,H,P,A> x; };
@@ -1122,8 +1580,9 @@
     }
 
     template <class K, class T, class H, class P, class A>
-    inline void swap(unordered_multimap<K, T, H, P, A> &m1,
-            unordered_multimap<K, T, H, P, A> &m2)
+    inline void swap(
+            unordered_multimap<K,T,H,P,A> &m1,
+            unordered_multimap<K,T,H,P,A> &m2)
     {
 #if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
         struct dummy { unordered_multimap<K,T,H,P,A> x; };
@@ -1131,6 +1590,7 @@
         m1.swap(m2);
     }
 
+} // namespace unordered
 } // namespace boost
 
 #if defined(BOOST_MSVC)
Modified: branches/release/boost/unordered/unordered_map_fwd.hpp
==============================================================================
--- branches/release/boost/unordered/unordered_map_fwd.hpp	(original)
+++ branches/release/boost/unordered/unordered_map_fwd.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -1,5 +1,5 @@
 
-// Copyright (C) 2008-2009 Daniel James.
+// Copyright (C) 2008-2011 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)
 
@@ -10,44 +10,38 @@
 # pragma once
 #endif
 
-#include <boost/config.hpp>
-#include <memory>
-#include <functional>
-#include <boost/functional/hash_fwd.hpp>
+#include <boost/unordered/detail/fwd.hpp>
 
 namespace boost
 {
-    template <class K,
-        class T,
-        class H = hash<K>,
-        class P = std::equal_to<K>,
-        class A = std::allocator<std::pair<const K, T> > >
-    class unordered_map;
-    template <class K, class T, class H, class P, class A>
-    inline bool operator==(unordered_map<K, T, H, P, A> const&,
-        unordered_map<K, T, H, P, A> const&);
-    template <class K, class T, class H, class P, class A>
-    inline bool operator!=(unordered_map<K, T, H, P, A> const&,
-        unordered_map<K, T, H, P, A> const&);
-    template <class K, class T, class H, class P, class A>
-    inline void swap(unordered_map<K, T, H, P, A>&,
-            unordered_map<K, T, H, P, A>&);
-
-    template <class K,
-        class T,
-        class H = hash<K>,
-        class P = std::equal_to<K>,
-        class A = std::allocator<std::pair<const K, T> > >
-    class unordered_multimap;
-    template <class K, class T, class H, class P, class A>
-    inline bool operator==(unordered_multimap<K, T, H, P, A> const&,
-        unordered_multimap<K, T, H, P, A> const&);
-    template <class K, class T, class H, class P, class A>
-    inline bool operator!=(unordered_multimap<K, T, H, P, A> const&,
-        unordered_multimap<K, T, H, P, A> const&);
-    template <class K, class T, class H, class P, class A>
-    inline void swap(unordered_multimap<K, T, H, P, A>&,
-            unordered_multimap<K, T, H, P, A>&);
+    namespace unordered
+    {
+        template <class K, class T, class H, class P, class A>
+        inline bool operator==(unordered_map<K, T, H, P, A> const&,
+            unordered_map<K, T, H, P, A> const&);
+        template <class K, class T, class H, class P, class A>
+        inline bool operator!=(unordered_map<K, T, H, P, A> const&,
+            unordered_map<K, T, H, P, A> const&);
+        template <class K, class T, class H, class P, class A>
+        inline void swap(unordered_map<K, T, H, P, A>&,
+                unordered_map<K, T, H, P, A>&);
+
+        template <class K, class T, class H, class P, class A>
+        inline bool operator==(unordered_multimap<K, T, H, P, A> const&,
+            unordered_multimap<K, T, H, P, A> const&);
+        template <class K, class T, class H, class P, class A>
+        inline bool operator!=(unordered_multimap<K, T, H, P, A> const&,
+            unordered_multimap<K, T, H, P, A> const&);
+        template <class K, class T, class H, class P, class A>
+        inline void swap(unordered_multimap<K, T, H, P, A>&,
+                unordered_multimap<K, T, H, P, A>&);
+    }
+
+    using ::boost::unordered::unordered_map;
+    using ::boost::unordered::unordered_multimap;
+    using ::boost::unordered::swap;
+    using ::boost::unordered::operator==;
+    using ::boost::unordered::operator!=;
 }
 
 #endif
Modified: branches/release/boost/unordered/unordered_set.hpp
==============================================================================
--- branches/release/boost/unordered/unordered_set.hpp	(original)
+++ branches/release/boost/unordered/unordered_set.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -1,6 +1,6 @@
 
 // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
-// Copyright (C) 2005-2009 Daniel James.
+// Copyright (C) 2005-2011 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)
 
@@ -19,10 +19,6 @@
 #include <boost/unordered/detail/equivalent.hpp>
 #include <boost/unordered/detail/unique.hpp>
 
-#if defined(BOOST_NO_RVALUE_REFERENCES)
-#include <boost/unordered/detail/move.hpp>
-#endif
-
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
 #include <initializer_list>
 #endif
@@ -38,9 +34,12 @@
 
 namespace boost
 {
+namespace unordered
+{
     template <class T, class H, class P, class A>
     class unordered_set
     {
+        BOOST_COPYABLE_AND_MOVABLE(unordered_set)
     public:
 
         typedef T key_type;
@@ -54,36 +53,35 @@
 #endif
 
         typedef BOOST_DEDUCED_TYPENAME
-            boost::unordered_detail::rebind_wrap<
+            ::boost::unordered::detail::rebind_wrap<
                 allocator_type, value_type>::type
             value_allocator;
+        typedef ::boost::unordered::detail::allocator_traits<value_allocator>
+            allocator_traits;
 
-        typedef boost::unordered_detail::set<H, P,
+        typedef ::boost::unordered::detail::set<H, P,
             value_allocator> types;
         typedef BOOST_DEDUCED_TYPENAME types::impl table;
 
-        typedef BOOST_DEDUCED_TYPENAME types::iterator_base iterator_base;
+        typedef BOOST_DEDUCED_TYPENAME types::node_ptr node_ptr;
 
     public:
 
         typedef BOOST_DEDUCED_TYPENAME
-            value_allocator::pointer pointer;
-        typedef BOOST_DEDUCED_TYPENAME
-            value_allocator::const_pointer const_pointer;
+            allocator_traits::pointer pointer;
         typedef BOOST_DEDUCED_TYPENAME
-            value_allocator::reference reference;
-        typedef BOOST_DEDUCED_TYPENAME
-            value_allocator::const_reference const_reference;
+            allocator_traits::const_pointer const_pointer;
+
+        typedef value_type& reference;
+        typedef value_type const& 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;
-        typedef boost::unordered_detail::hash_const_iterator<
-            value_allocator, boost::unordered_detail::ungrouped>
-                const_iterator;
+        typedef ::boost::unordered::iterator_detail::cl_iterator<
+            value_allocator, true> const_local_iterator;
+        typedef ::boost::unordered::iterator_detail::c_iterator<
+            value_allocator, true> const_iterator;
         typedef const_local_iterator local_iterator;
         typedef const_iterator iterator;
 
@@ -92,130 +90,77 @@
 #endif
 
         table table_;
-        
-        BOOST_DEDUCED_TYPENAME types::iterator_base const&
-            get(const_iterator const& it)
-        {
-            return boost::unordered_detail::iterator_access::get(it);
-        }
 
     public:
 
         // construct/destroy/copy
 
         explicit unordered_set(
-                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)
-        {
-        }
+                size_type = ::boost::unordered::detail::default_bucket_count,
+                const hasher& = hasher(),
+                const key_equal& = key_equal(),
+                const allocator_type& = allocator_type());
 
-        explicit unordered_set(allocator_type const& a)
-          : table_(boost::unordered_detail::default_bucket_count,
-                hasher(), key_equal(), a)
-        {
-        }
+        explicit unordered_set(allocator_type const&);
 
-        unordered_set(unordered_set const& other, allocator_type const& a)
-          : table_(other.table_, a)
-        {
-        }
+        unordered_set(unordered_set const&, allocator_type const&);
 
         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);
-        }
+        unordered_set(InputIt f, InputIt l);
 
         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_.insert_range(f, l);
-        }
-        
+        unordered_set(
+                InputIt, InputIt,
+                size_type,
+                const hasher& = hasher(),
+                const key_equal& = key_equal());        
+
         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_.insert_range(f, l);
-        }
+        unordered_set(
+                InputIt, InputIt,
+                size_type,
+                const hasher&,
+                const key_equal&,
+                const allocator_type&);
         
-        ~unordered_set() {}
-
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
-        unordered_set(unordered_set const& other)
-          : table_(other.table_)
-        {
-        }
-
-        unordered_set(unordered_set&& other)
-          : 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())
-        {
-        }
+        ~unordered_set();
 
-        unordered_set& operator=(unordered_set const& x)
+        unordered_set& operator=(
+                BOOST_COPY_ASSIGN_REF(unordered_set) x)
         {
-            table_ = x.table_;
+            table_.assign(x.table_);
             return *this;
         }
 
-        unordered_set& operator=(unordered_set&& x)
+        unordered_set(unordered_set const&);
+
+#if BOOST_UNORDERED_USE_RV_REF
+        unordered_set& operator=(
+                BOOST_RV_REF(unordered_set) x)
         {
-            table_.move(x.table_);
+            table_.move_assign(x.table_);
             return *this;
         }
-#else
-        unordered_set(boost::unordered_detail::move_from<
-                unordered_set<T, H, P, A>
-            > other)
-          : table_(other.source.table_, boost::unordered_detail::move_tag())
-        {
-        }
 
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0593)
-        unordered_set& operator=(unordered_set x)
+        unordered_set(BOOST_RV_REF(unordered_set) other)
+            : table_(other.table_, ::boost::unordered::detail::move_tag())
         {
-            table_.move(x.table_);
-            return *this;
         }
 #endif
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES)
+        unordered_set(unordered_set&&, allocator_type const&);
 #endif
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
-        unordered_set(std::initializer_list<value_type> list,
-                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, a)
-        {
-            table_.insert_range(list.begin(), list.end());
-        }
+        unordered_set(
+                std::initializer_list<value_type>,
+                size_type = ::boost::unordered::detail::default_bucket_count,
+                const hasher& = hasher(),
+                const key_equal&l = key_equal(),
+                const allocator_type& = allocator_type());
 
-        unordered_set& operator=(std::initializer_list<value_type> list)
-        {
-            table_.clear();
-            table_.insert_range(list.begin(), list.end());
-            return *this;
-        }
+        unordered_set& operator=(std::initializer_list<value_type>);
 #endif
 
         allocator_type get_allocator() const
@@ -235,10 +180,7 @@
             return table_.size_;
         }
 
-        size_type max_size() const
-        {
-            return table_.max_size();
-        }
+        size_type max_size() const;
 
         // iterators
 
@@ -254,12 +196,12 @@
 
         iterator end()
         {
-            return iterator(table_.end());
+            return iterator();
         }
 
         const_iterator end() const
         {
-            return const_iterator(table_.end());
+            return const_iterator();
         }
 
         const_iterator cbegin() const
@@ -269,37 +211,28 @@
 
         const_iterator cend() const
         {
-            return const_iterator(table_.end());
+            return const_iterator();
         }
 
         // modifiers
 
-#if defined(BOOST_UNORDERED_STD_FORWARD)
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
         template <class... Args>
-        std::pair<iterator, bool> emplace(Args&&... args)
-        {
-            return boost::unordered_detail::pair_cast<iterator, bool>(
-                table_.emplace(std::forward<Args>(args)...));
-        }
-
+        std::pair<iterator, bool> emplace(Args&&...);
         template <class... Args>
-        iterator emplace_hint(const_iterator, Args&&... args)
-        {
-            return iterator(table_.emplace(std::forward<Args>(args)...).first);
-        }
+        iterator emplace_hint(const_iterator, Args&&...);
 #else
 
-        std::pair<iterator, bool> emplace(value_type const& v = value_type())
-        {
-            return boost::unordered_detail::pair_cast<iterator, bool>(
-                table_.emplace(v));
-        }
-
+        std::pair<iterator, bool> emplace(
+                boost::unordered::detail::empty_emplace
+                    = boost::unordered::detail::empty_emplace(),
+                value_type v = value_type()
+            );
         iterator emplace_hint(const_iterator,
-            value_type const& v = value_type())
-        {
-            return iterator(table_.emplace(v).first);
-        }
+                boost::unordered::detail::empty_emplace
+                    = boost::unordered::detail::empty_emplace(),
+                value_type v = value_type()
+            );
 
 #define BOOST_UNORDERED_EMPLACE(z, n, _)                                       \
             template <                                                         \
@@ -307,24 +240,14 @@
             >                                                                  \
             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,                              \
                 BOOST_UNORDERED_FUNCTION_PARAMS(z, n)                          \
-            )                                                                  \
-            {                                                                  \
-                return iterator(table_.emplace(                                \
-                    BOOST_UNORDERED_CALL_PARAMS(z, n)).first);                 \
-            }
+            );
 
         BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
             BOOST_UNORDERED_EMPLACE, _)
@@ -333,105 +256,46 @@
 
 #endif
 
-        std::pair<iterator, bool> insert(const value_type& obj)
-        {
-            return boost::unordered_detail::pair_cast<iterator, bool>(
-                    table_.emplace(obj));
-        }
-
-        iterator insert(const_iterator, const value_type& obj)
-        {
-            return iterator(table_.emplace(obj).first);
-        }
-
-        template <class InputIt>
-            void insert(InputIt first, InputIt last)
-        {
-            table_.insert_range(first, last);
-        }
+        std::pair<iterator, bool> insert(value_type const&);
+        iterator insert(const_iterator, value_type const&);
+#if BOOST_UNORDERED_USE_RV_REF
+        std::pair<iterator, bool> insert(BOOST_RV_REF(value_type));
+        iterator insert(const_iterator, BOOST_RV_REF(value_type));
+#endif
+        template <class InputIt> void insert(InputIt, InputIt);
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
-        void insert(std::initializer_list<value_type> list)
-        {
-            table_.insert_range(list.begin(), list.end());
-        }
+        void insert(std::initializer_list<value_type>);
 #endif
 
-        iterator erase(const_iterator position)
-        {
-            return iterator(table_.erase_return_iterator(get(position)));
-        }
-
-        size_type erase(const key_type& k)
-        {
-            return table_.erase_key(k);
-        }
-
-        iterator erase(const_iterator first, const_iterator last)
-        {
-            return iterator(table_.erase_range(get(first), get(last)));
-        }
-
-        void quick_erase(const_iterator position)
-        {
-            table_.erase(get(position));
-        }
-
-        void erase_return_void(const_iterator position)
-        {
-            table_.erase(get(position));
-        }
-
-        void clear()
-        {
-            table_.clear();
-        }
+        iterator erase(const_iterator);
+        size_type erase(const key_type&);
+        iterator erase(const_iterator, const_iterator);
+        void quick_erase(const_iterator it) { erase(it); }
+        void erase_return_void(const_iterator it) { erase(it); }
 
-        void swap(unordered_set& other)
-        {
-            table_.swap(other.table_);
-        }
+        void clear();
+        void swap(unordered_set&);
 
         // observers
 
-        hasher hash_function() const
-        {
-            return table_.hash_function();
-        }
-
-        key_equal key_eq() const
-        {
-            return table_.key_eq();
-        }
+        hasher hash_function() const;
+        key_equal key_eq() const;
 
         // lookup
 
-        const_iterator find(const key_type& k) const
-        {
-            return const_iterator(table_.find(k));
-        }
+        const_iterator find(const key_type&) const;
 
         template <class CompatibleKey, class CompatibleHash,
             class CompatiblePredicate>
         const_iterator find(
-            CompatibleKey const& k,
-            CompatibleHash const& hash,
-            CompatiblePredicate const& eq) const
-        {
-            return iterator(table_.find(k, hash, eq));
-        }
-        size_type count(const key_type& k) const
-        {
-            return table_.count(k);
-        }
+                CompatibleKey const&,
+                CompatibleHash const&,
+                CompatiblePredicate const&) const;
 
+        size_type count(const key_type&) const;
         std::pair<const_iterator, const_iterator>
-            equal_range(const key_type& k) const
-        {
-            return boost::unordered_detail::pair_cast<
-                const_iterator, const_iterator>(
-                    table_.equal_range(k));
-        }
+        equal_range(const key_type&) const;
 
         // bucket interface
 
@@ -445,24 +309,23 @@
             return table_.max_bucket_count();
         }
 
-        size_type bucket_size(size_type n) const
-        {
-            return table_.bucket_size(n);
-        }
+        size_type bucket_size(size_type n) const;
 
         size_type bucket(const key_type& k) const
         {
-            return table_.bucket_index(k);
+            return table_.hash_function()(k) % table_.bucket_count_;
         }
 
         local_iterator begin(size_type n)
         {
-            return local_iterator(table_.bucket_begin(n));
+            return local_iterator(
+                table_.bucket_begin(n), n, table_.bucket_count_);
         }
 
         const_local_iterator begin(size_type n) const
         {
-            return const_local_iterator(table_.bucket_begin(n));
+            return const_local_iterator(
+                table_.bucket_begin(n), n, table_.bucket_count_);
         }
 
         local_iterator end(size_type)
@@ -477,7 +340,8 @@
 
         const_local_iterator cbegin(size_type n) const
         {
-            return const_local_iterator(table_.bucket_begin(n));
+            return const_local_iterator(
+                table_.bucket_begin(n), n, table_.bucket_count_);
         }
 
         const_local_iterator cend(size_type) const
@@ -487,67 +351,27 @@
 
         // hash policy
 
-        float load_factor() const
-        {
-            return table_.load_factor();
-        }
-
         float max_load_factor() const
         {
             return table_.mlf_;
         }
 
-        void max_load_factor(float m)
-        {
-            table_.max_load_factor(m);
-        }
-
-        void rehash(size_type n)
-        {
-            table_.rehash(n);
-        }
+        float load_factor() const;
+        void max_load_factor(float);
+        void rehash(size_type n);
 
 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
-        friend bool operator==<T, H, P, A>(
-            unordered_set const&, unordered_set const&);
-        friend bool operator!=<T, H, P, A>(
-            unordered_set const&, unordered_set const&);
+        friend bool operator==<T,H,P,A>(
+                unordered_set const&, unordered_set const&);
+        friend bool operator!=<T,H,P,A>(
+                unordered_set const&, unordered_set const&);
 #endif
     }; // class template unordered_set
 
     template <class T, class H, class P, class A>
-    inline bool operator==(unordered_set<T, H, P, A> const& m1,
-        unordered_set<T, H, P, A> const& m2)
-    {
-#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
-        struct dummy { unordered_set<T,H,P,A> x; };
-#endif
-        return m1.table_.equals(m2.table_);
-    }
-
-    template <class T, class H, class P, class A>
-    inline bool operator!=(unordered_set<T, H, P, A> const& m1,
-        unordered_set<T, H, P, A> const& m2)
-    {
-#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
-        struct dummy { unordered_set<T,H,P,A> x; };
-#endif
-        return !m1.table_.equals(m2.table_);
-    }
-
-    template <class T, class H, class P, class A>
-    inline void swap(unordered_set<T, H, P, A> &m1,
-            unordered_set<T, H, P, A> &m2)
-    {
-#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
-        struct dummy { unordered_set<T,H,P,A> x; };
-#endif
-        m1.swap(m2);
-    }
-
-    template <class T, class H, class P, class A>
     class unordered_multiset
     {
+        BOOST_COPYABLE_AND_MOVABLE(unordered_multiset)
     public:
 
         typedef T key_type;
@@ -561,36 +385,35 @@
 #endif
 
         typedef BOOST_DEDUCED_TYPENAME
-            boost::unordered_detail::rebind_wrap<
+            ::boost::unordered::detail::rebind_wrap<
                 allocator_type, value_type>::type
             value_allocator;
+        typedef ::boost::unordered::detail::allocator_traits<value_allocator>
+            allocator_traits;
 
-        typedef boost::unordered_detail::multiset<H, P,
+        typedef ::boost::unordered::detail::multiset<H, P,
             value_allocator> types;
         typedef BOOST_DEDUCED_TYPENAME types::impl table;
 
-        typedef BOOST_DEDUCED_TYPENAME types::iterator_base iterator_base;
+        typedef BOOST_DEDUCED_TYPENAME types::node_ptr node_ptr;
 
     public:
 
         typedef BOOST_DEDUCED_TYPENAME
-            value_allocator::pointer pointer;
-        typedef BOOST_DEDUCED_TYPENAME
-            value_allocator::const_pointer const_pointer;
+            allocator_traits::pointer pointer;
         typedef BOOST_DEDUCED_TYPENAME
-            value_allocator::reference reference;
-        typedef BOOST_DEDUCED_TYPENAME
-            value_allocator::const_reference const_reference;
+            allocator_traits::const_pointer const_pointer;
+
+        typedef value_type& reference;
+        typedef value_type const& 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;
-        typedef boost::unordered_detail::hash_const_iterator<
-            value_allocator, boost::unordered_detail::grouped>
-                const_iterator;
+        typedef ::boost::unordered::iterator_detail::cl_iterator<
+            value_allocator, false> const_local_iterator;
+        typedef ::boost::unordered::iterator_detail::c_iterator<
+            value_allocator, false> const_iterator;
         typedef const_local_iterator local_iterator;
         typedef const_iterator iterator;
 
@@ -599,131 +422,77 @@
 #endif
 
         table table_;
-        
-        BOOST_DEDUCED_TYPENAME types::iterator_base const&
-            get(const_iterator const& it)
-        {
-            return boost::unordered_detail::iterator_access::get(it);
-        }
 
     public:
 
         // construct/destroy/copy
 
         explicit unordered_multiset(
-                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)
-        {
-        }
+                size_type = ::boost::unordered::detail::default_bucket_count,
+                const hasher& = hasher(),
+                const key_equal& = key_equal(),
+                const allocator_type& = allocator_type());
 
-        explicit unordered_multiset(allocator_type const& a)
-          : table_(boost::unordered_detail::default_bucket_count,
-                hasher(), key_equal(), a)
-        {
-        }
+        explicit unordered_multiset(allocator_type const&);
 
-        unordered_multiset(unordered_multiset const& other,
-            allocator_type const& a)
-          : table_(other.table_, a)
-        {
-        }
+        unordered_multiset(unordered_multiset const&, allocator_type const&);
 
         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);
-        }
+        unordered_multiset(InputIt, InputIt);
 
         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_.insert_range(f, l);
-        }
+        unordered_multiset(
+                InputIt, InputIt,
+                size_type,
+                const hasher& = hasher(),
+                const key_equal& = key_equal());
 
         template <class InputIt>
-        unordered_multiset(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_.insert_range(f, l);
-        }
-
-        ~unordered_multiset() {}
-
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
-        unordered_multiset(unordered_multiset const& other)
-          : table_(other.table_)
-        {
-        }
-
-        unordered_multiset(unordered_multiset&& other)
-          : table_(other.table_, boost::unordered_detail::move_tag())
-        {
-        }
+        unordered_multiset(
+                InputIt, InputIt,
+                size_type,
+                const hasher&,
+                const key_equal&,
+                const allocator_type&);
 
-        unordered_multiset(unordered_multiset&& other, allocator_type const& a)
-          : table_(other.table_, a, boost::unordered_detail::move_tag())
-        {
-        }
+        ~unordered_multiset();
 
-        unordered_multiset& operator=(unordered_multiset const& x)
+        unordered_multiset& operator=(
+                BOOST_COPY_ASSIGN_REF(unordered_multiset) x)
         {
-            table_ = x.table_;
+            table_.assign(x.table_);
             return *this;
         }
 
-        unordered_multiset& operator=(unordered_multiset&& x)
+        unordered_multiset(unordered_multiset const&);
+
+#if BOOST_UNORDERED_USE_RV_REF
+        unordered_multiset& operator=(
+                BOOST_RV_REF(unordered_multiset) x)
         {
-            table_.move(x.table_);
+            table_.move_assign(x.table_);
             return *this;
         }
-#else
-        unordered_multiset(boost::unordered_detail::move_from<
-                unordered_multiset<T, H, P, A>
-            > other)
-          : table_(other.source.table_, boost::unordered_detail::move_tag())
-        {
-        }
 
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0593)
-        unordered_multiset& operator=(unordered_multiset x)
+        unordered_multiset(BOOST_RV_REF(unordered_multiset) other)
+            : table_(other.table_, ::boost::unordered::detail::move_tag())
         {
-            table_.move(x.table_);
-            return *this;
         }
 #endif
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES)
+        unordered_multiset(unordered_multiset&&, allocator_type const&);
 #endif
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
-        unordered_multiset(std::initializer_list<value_type> list,
-                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, a)
-        {
-            table_.insert_range(list.begin(), list.end());
-        }
+        unordered_multiset(
+                std::initializer_list<value_type>,
+                size_type = ::boost::unordered::detail::default_bucket_count,
+                const hasher& = hasher(),
+                const key_equal&l = key_equal(),
+                const allocator_type& = allocator_type());
 
-        unordered_multiset& operator=(std::initializer_list<value_type> list)
-        {
-            table_.clear();
-            table_.insert_range(list.begin(), list.end());
-            return *this;
-        }
+        unordered_multiset& operator=(std::initializer_list<value_type>);
 #endif
 
         allocator_type get_allocator() const
@@ -743,10 +512,7 @@
             return table_.size_;
         }
 
-        size_type max_size() const
-        {
-            return table_.max_size();
-        }
+        size_type max_size() const;
 
         // iterators
 
@@ -762,12 +528,12 @@
 
         iterator end()
         {
-            return iterator(table_.end());
+            return iterator();
         }
 
         const_iterator end() const
         {
-            return const_iterator(table_.end());
+            return const_iterator();
         }
 
         const_iterator cbegin() const
@@ -777,35 +543,28 @@
 
         const_iterator cend() const
         {
-            return const_iterator(table_.end());
+            return const_iterator();
         }
 
         // modifiers
 
-#if defined(BOOST_UNORDERED_STD_FORWARD)
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
         template <class... Args>
-        iterator emplace(Args&&... args)
-        {
-            return iterator(table_.emplace(std::forward<Args>(args)...));
-        }
-
+        iterator emplace(Args&&...);
         template <class... Args>
-        iterator emplace_hint(const_iterator, Args&&... args)
-        {
-            return iterator(table_.emplace(std::forward<Args>(args)...));
-        }
+        iterator emplace_hint(const_iterator, Args&&...);
 #else
 
-        iterator emplace(value_type const& v = value_type())
-        {
-            return iterator(table_.emplace(v));
-        }
-
+        iterator emplace(
+                boost::unordered::detail::empty_emplace
+                    = boost::unordered::detail::empty_emplace(),
+                value_type v = value_type()
+            );
         iterator emplace_hint(const_iterator,
-            value_type const& v = value_type())
-        {
-            return iterator(table_.emplace(v));
-        }
+                boost::unordered::detail::empty_emplace
+                    = boost::unordered::detail::empty_emplace(),
+                value_type v = value_type()
+            );
 
 #define BOOST_UNORDERED_EMPLACE(z, n, _)                                       \
             template <                                                         \
@@ -813,23 +572,14 @@
             >                                                                  \
             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,                              \
                 BOOST_UNORDERED_FUNCTION_PARAMS(z, n)                          \
-            )                                                                  \
-            {                                                                  \
-                return iterator(table_.emplace(                                \
-                        BOOST_UNORDERED_CALL_PARAMS(z, n)                      \
-                ));                                                            \
-            }
+            );
 
         BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
             BOOST_UNORDERED_EMPLACE, _)
@@ -838,105 +588,47 @@
 
 #endif
 
-        iterator insert(const value_type& obj)
-        {
-            return iterator(table_.emplace(obj));
-        }
-
-        iterator insert(const_iterator, const value_type& obj)
-        {
-            return iterator(table_.emplace(obj));
-        }
-
+        iterator insert(value_type const&);
+        iterator insert(const_iterator, value_type const&);
+#if BOOST_UNORDERED_USE_RV_REF
+        iterator insert(BOOST_RV_REF(value_type));
+        iterator insert(const_iterator, BOOST_RV_REF(value_type));
+#endif
         template <class InputIt>
-            void insert(InputIt first, InputIt last)
-        {
-            table_.insert_range(first, last);
-        }
+        void insert(InputIt, InputIt);
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
-        void insert(std::initializer_list<value_type> list)
-        {
-            table_.insert_range(list.begin(), list.end());
-        }
+        void insert(std::initializer_list<value_type>);
 #endif
 
-        iterator erase(const_iterator position)
-        {
-            return iterator(table_.erase_return_iterator(get(position)));
-        }
-
-        size_type erase(const key_type& k)
-        {
-            return table_.erase_key(k);
-        }
-
-        iterator erase(const_iterator first, const_iterator last)
-        {
-            return iterator(table_.erase_range(get(first), get(last)));
-        }
-
-        void quick_erase(const_iterator position)
-        {
-            table_.erase(get(position));
-        }
-
-        void erase_return_void(const_iterator position)
-        {
-            table_.erase(get(position));
-        }
+        iterator erase(const_iterator);
+        size_type erase(const key_type&);
+        iterator erase(const_iterator, const_iterator);
+        void quick_erase(const_iterator position) { erase(position); }
+        void erase_return_void(const_iterator position) { erase(position); }
 
-        void clear()
-        {
-            table_.clear();
-        }
-
-        void swap(unordered_multiset& other)
-        {
-            table_.swap(other.table_);
-        }
+        void clear();
+        void swap(unordered_multiset&);
 
         // observers
 
-        hasher hash_function() const
-        {
-            return table_.hash_function();
-        }
-
-        key_equal key_eq() const
-        {
-            return table_.key_eq();
-        }
+        hasher hash_function() const;
+        key_equal key_eq() const;
 
         // lookup
 
-        const_iterator find(const key_type& k) const
-        {
-            return const_iterator(table_.find(k));
-        }
+        const_iterator find(const key_type&) const;
 
         template <class CompatibleKey, class CompatibleHash,
             class CompatiblePredicate>
         const_iterator find(
-            CompatibleKey const& k,
-            CompatibleHash const& hash,
-            CompatiblePredicate const& eq) const
-        {
-            return iterator(table_.find(k, hash, eq));
-        }
-
-        size_type count(const key_type& k) const
-        {
-            return table_.count(k);
-        }
+                CompatibleKey const&,
+                CompatibleHash const&,
+                CompatiblePredicate const&) const;
 
+        size_type count(const key_type&) const;
         std::pair<const_iterator, const_iterator>
-            equal_range(const key_type& k) const
-        {
-            return boost::unordered_detail::pair_cast<
-                const_iterator, const_iterator>(
-                    table_.equal_range(k));
-        }
+        equal_range(const key_type&) const;
 
         // bucket interface
 
@@ -950,24 +642,23 @@
             return table_.max_bucket_count();
         }
 
-        size_type bucket_size(size_type n) const
-        {
-            return table_.bucket_size(n);
-        }
+        size_type bucket_size(size_type) const;
 
         size_type bucket(const key_type& k) const
         {
-            return table_.bucket_index(k);
+            return table_.hash_function()(k) % table_.bucket_count_;
         }
 
         local_iterator begin(size_type n)
         {
-            return local_iterator(table_.bucket_begin(n));
+            return local_iterator(
+                table_.bucket_begin(n), n, table_.bucket_count_);
         }
 
         const_local_iterator begin(size_type n) const
         {
-            return const_local_iterator(table_.bucket_begin(n));
+            return const_local_iterator(
+                table_.bucket_begin(n), n, table_.bucket_count_);
         }
 
         local_iterator end(size_type)
@@ -982,7 +673,8 @@
 
         const_local_iterator cbegin(size_type n) const
         {
-            return const_local_iterator(table_.bucket_begin(n));
+            return const_local_iterator(
+                table_.bucket_begin(n), n, table_.bucket_count_);
         }
 
         const_local_iterator cend(size_type) const
@@ -992,37 +684,763 @@
 
         // hash policy
 
-        float load_factor() const
-        {
-            return table_.load_factor();
-        }
-
         float max_load_factor() const
         {
             return table_.mlf_;
         }
 
-        void max_load_factor(float m)
-        {
-            table_.max_load_factor(m);
-        }
-
-        void rehash(size_type n)
-        {
-            table_.rehash(n);
-        }
+        float load_factor() const;
+        void max_load_factor(float);
+        void rehash(size_type);
 
 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
-        friend bool operator==<T, H, P, A>(
-            unordered_multiset const&, unordered_multiset const&);
-        friend bool operator!=<T, H, P, A>(
-            unordered_multiset const&, unordered_multiset const&);
+        friend bool operator==<T,H,P,A>(
+                unordered_multiset const&, unordered_multiset const&);
+        friend bool operator!=<T,H,P,A>(
+                unordered_multiset const&, unordered_multiset const&);
 #endif
     }; // class template unordered_multiset
 
+////////////////////////////////////////////////////////////////////////////////
+
+    template <class T, class H, class P, class A>
+    unordered_set<T,H,P,A>::unordered_set(
+            size_type n, const hasher &hf, const key_equal &eql,
+            const allocator_type &a)
+      : table_(n, hf, eql, a)
+    {
+    }
+
+    template <class T, class H, class P, class A>
+    unordered_set<T,H,P,A>::unordered_set(allocator_type const& a)
+      : table_(::boost::unordered::detail::default_bucket_count,
+            hasher(), key_equal(), a)
+    {
+    }
+
+    template <class T, class H, class P, class A>
+    unordered_set<T,H,P,A>::unordered_set(
+            unordered_set const& other, allocator_type const& a)
+      : table_(other.table_, a)
+    {
+    }
+
+    template <class T, class H, class P, class A>
+    template <class InputIt>
+    unordered_set<T,H,P,A>::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 T, class H, class P, class A>
+    template <class InputIt>
+    unordered_set<T,H,P,A>::unordered_set(
+            InputIt f, InputIt l,
+            size_type n,
+            const hasher &hf,
+            const key_equal &eql)
+      : table_(::boost::unordered::detail::initial_size(f, l, n),
+            hf, eql, allocator_type())
+    {
+        table_.insert_range(f, l);
+    }
+    
+    template <class T, class H, class P, class A>
+    template <class InputIt>
+    unordered_set<T,H,P,A>::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_.insert_range(f, l);
+    }
+    
+    template <class T, class H, class P, class A>
+    unordered_set<T,H,P,A>::~unordered_set() {}
+
+    template <class T, class H, class P, class A>
+    unordered_set<T,H,P,A>::unordered_set(unordered_set const& other)
+      : table_(other.table_)
+    {
+    }
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES)
+
+    template <class T, class H, class P, class A>
+    unordered_set<T,H,P,A>::unordered_set(
+            unordered_set&& other, allocator_type const& a)
+      : table_(other.table_, a, ::boost::unordered::detail::move_tag())
+    {
+    }
+
+#endif
+
+#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
+
+    template <class T, class H, class P, class A>
+    unordered_set<T,H,P,A>::unordered_set(
+            std::initializer_list<value_type> list, size_type n,
+            const hasher &hf, const key_equal &eql, const allocator_type &a)
+      : table_(
+            ::boost::unordered::detail::initial_size(
+                list.begin(), list.end(), n),
+            hf, eql, a)
+    {
+        table_.insert_range(list.begin(), list.end());
+    }
+
+    template <class T, class H, class P, class A>
+    unordered_set<T,H,P,A>& unordered_set<T,H,P,A>::operator=(
+            std::initializer_list<value_type> list)
+    {
+        table_.clear();
+        table_.insert_range(list.begin(), list.end());
+        return *this;
+    }
+
+#endif
+
+    // size and capacity
+
+    template <class T, class H, class P, class A>
+    std::size_t unordered_set<T,H,P,A>::max_size() const
+    {
+        return table_.max_size();
+    }
+
+    // modifiers
+
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+    template <class T, class H, class P, class A>
+    template <class... Args>
+    std::pair<BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator, bool>
+        unordered_set<T,H,P,A>::emplace(Args&&... args)
+    {
+        return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
+            table_.emplace(std::forward<Args>(args)...));
+    }
+
+    template <class T, class H, class P, class A>
+    template <class... Args>
+    BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
+        unordered_set<T,H,P,A>::emplace_hint(const_iterator, Args&&... args)
+    {
+        return iterator(table_.emplace(std::forward<Args>(args)...).first);
+    }
+#else
+
+    template <class T, class H, class P, class A>
+    std::pair<BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator, bool>
+        unordered_set<T,H,P,A>::emplace(
+                boost::unordered::detail::empty_emplace,
+                value_type v
+            )
+    {
+        return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
+                table_.emplace(boost::move(v)));
+    }
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
+        unordered_set<T,H,P,A>::emplace_hint(const_iterator,
+                boost::unordered::detail::empty_emplace,
+                value_type v
+            )
+    {
+        return iterator(table_.emplace(boost::move(v)).first);
+    }
+
+#define BOOST_UNORDERED_EMPLACE(z, n, _)                                    \
+        template <class T, class H, class P, class A>                       \
+        template <                                                          \
+            BOOST_UNORDERED_TEMPLATE_ARGS(z, n)                             \
+        >                                                                   \
+        std::pair<                                                          \
+                BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator,    \
+                bool>                                                       \
+            unordered_set<T,H,P,A>::emplace(                                \
+                BOOST_UNORDERED_FUNCTION_PARAMS(z, n))                      \
+        {                                                                   \
+            return                                                          \
+                BOOST_UNORDERED_PAIR_CAST(iterator, bool,                   \
+                    table_.emplace(                                         \
+                        BOOST_UNORDERED_CALL_PARAMS(z, n)));                \
+        }                                                                   \
+                                                                            \
+        template <class T, class H, class P, class A>                       \
+        template <                                                          \
+            BOOST_UNORDERED_TEMPLATE_ARGS(z, n)                             \
+        >                                                                   \
+        BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator             \
+            unordered_set<T,H,P,A>::emplace_hint(                           \
+                const_iterator,                                             \
+                BOOST_UNORDERED_FUNCTION_PARAMS(z, n)                       \
+        )                                                                   \
+        {                                                                   \
+            return iterator(table_.emplace(                                 \
+                BOOST_UNORDERED_CALL_PARAMS(z, n)).first);                  \
+        }
+
+    BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
+        BOOST_UNORDERED_EMPLACE, _)
+
+#undef BOOST_UNORDERED_EMPLACE
+
+#endif
+
+    template <class T, class H, class P, class A>
+    std::pair<BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator, bool>
+        unordered_set<T,H,P,A>::insert(value_type const& obj)
+    {
+        return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
+                table_.emplace(obj));
+    }
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
+        unordered_set<T,H,P,A>::insert(const_iterator,
+                value_type const& obj)
+    {
+        return iterator(table_.emplace(obj).first);
+    }
+
+#if BOOST_UNORDERED_USE_RV_REF
+    template <class T, class H, class P, class A>
+    std::pair<BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator, bool>
+        unordered_set<T,H,P,A>::insert(BOOST_RV_REF(value_type) obj)
+    {
+        return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
+                table_.emplace(boost::move(obj)));
+    }
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
+        unordered_set<T,H,P,A>::insert(const_iterator,
+                BOOST_RV_REF(value_type) obj)
+    {
+        return iterator(table_.emplace(boost::move(obj)).first);
+    }
+#endif
+
+    template <class T, class H, class P, class A>
+    template <class InputIt>
+    void unordered_set<T,H,P,A>::insert(InputIt first, InputIt last)
+    {
+        table_.insert_range(first, last);
+    }
+
+#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
+    template <class T, class H, class P, class A>
+    void unordered_set<T,H,P,A>::insert(std::initializer_list<value_type> list)
+    {
+        table_.insert_range(list.begin(), list.end());
+    }
+#endif
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
+        unordered_set<T,H,P,A>::erase(const_iterator position)
+    {
+        return iterator(table_.erase(position.node_));
+    }
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::size_type
+        unordered_set<T,H,P,A>::erase(const key_type& k)
+    {
+        return table_.erase_key(k);
+    }
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
+        unordered_set<T,H,P,A>::erase(const_iterator first, const_iterator last)
+    {
+        return iterator(table_.erase_range(first.node_, last.node_));
+    }
+
+    template <class T, class H, class P, class A>
+    void unordered_set<T,H,P,A>::clear()
+    {
+        table_.clear();
+    }
+
+    template <class T, class H, class P, class A>
+    void unordered_set<T,H,P,A>::swap(unordered_set& other)
+    {
+        table_.swap(other.table_);
+    }
+
+    // observers
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::hasher
+        unordered_set<T,H,P,A>::hash_function() const
+    {
+        return table_.hash_function();
+    }
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::key_equal
+        unordered_set<T,H,P,A>::key_eq() const
+    {
+        return table_.key_eq();
+    }
+
+    // lookup
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::const_iterator
+        unordered_set<T,H,P,A>::find(const key_type& k) const
+    {
+        return const_iterator(table_.find_node(k));
+    }
+
+    template <class T, class H, class P, class A>
+    template <class CompatibleKey, class CompatibleHash,
+        class CompatiblePredicate>
+    BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::const_iterator
+        unordered_set<T,H,P,A>::find(
+            CompatibleKey const& k,
+            CompatibleHash const& hash,
+            CompatiblePredicate const& eq) const
+    {
+        return const_iterator(table_.generic_find_node(k, hash, eq));
+    }
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::size_type
+        unordered_set<T,H,P,A>::count(const key_type& k) const
+    {
+        return table_.count(k);
+    }
+
+    template <class T, class H, class P, class A>
+    std::pair<
+            BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::const_iterator,
+            BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::const_iterator>
+        unordered_set<T,H,P,A>::equal_range(const key_type& k) const
+    {
+        return BOOST_UNORDERED_PAIR_CAST(const_iterator, const_iterator,
+            table_.equal_range(k));
+    }
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::size_type
+        unordered_set<T,H,P,A>::bucket_size(size_type n) const
+    {
+        return table_.bucket_size(n);
+    }
+
+    // hash policy
+
+    template <class T, class H, class P, class A>
+    float unordered_set<T,H,P,A>::load_factor() const
+    {
+        return table_.load_factor();
+    }
+
+    template <class T, class H, class P, class A>
+    void unordered_set<T,H,P,A>::max_load_factor(float m)
+    {
+        table_.max_load_factor(m);
+    }
+
+    template <class T, class H, class P, class A>
+    void unordered_set<T,H,P,A>::rehash(size_type n)
+    {
+        table_.rehash(n);
+    }
+
+    template <class T, class H, class P, class A>
+    inline bool operator==(
+            unordered_set<T,H,P,A> const& m1,
+            unordered_set<T,H,P,A> const& m2)
+    {
+#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
+        struct dummy { unordered_set<T,H,P,A> x; };
+#endif
+        return m1.table_.equals(m2.table_);
+    }
+
+    template <class T, class H, class P, class A>
+    inline bool operator!=(
+            unordered_set<T,H,P,A> const& m1,
+            unordered_set<T,H,P,A> const& m2)
+    {
+#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
+        struct dummy { unordered_set<T,H,P,A> x; };
+#endif
+        return !m1.table_.equals(m2.table_);
+    }
+
+    template <class T, class H, class P, class A>
+    inline void swap(
+            unordered_set<T,H,P,A> &m1,
+            unordered_set<T,H,P,A> &m2)
+    {
+#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
+        struct dummy { unordered_set<T,H,P,A> x; };
+#endif
+        m1.swap(m2);
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+
+    template <class T, class H, class P, class A>
+    unordered_multiset<T,H,P,A>::unordered_multiset(
+            size_type n, const hasher &hf, const key_equal &eql,
+            const allocator_type &a)
+      : table_(n, hf, eql, a)
+    {
+    }
+
+    template <class T, class H, class P, class A>
+    unordered_multiset<T,H,P,A>::unordered_multiset(allocator_type const& a)
+      : table_(::boost::unordered::detail::default_bucket_count,
+            hasher(), key_equal(), a)
+    {
+    }
+
+    template <class T, class H, class P, class A>
+    unordered_multiset<T,H,P,A>::unordered_multiset(
+            unordered_multiset const& other, allocator_type const& a)
+      : table_(other.table_, a)
+    {
+    }
+
+    template <class T, class H, class P, class A>
+    template <class InputIt>
+    unordered_multiset<T,H,P,A>::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 T, class H, class P, class A>
+    template <class InputIt>
+    unordered_multiset<T,H,P,A>::unordered_multiset(
+            InputIt f, InputIt l,
+            size_type n,
+            const hasher &hf,
+            const key_equal &eql)
+      : table_(::boost::unordered::detail::initial_size(f, l, n),
+            hf, eql, allocator_type())
+    {
+        table_.insert_range(f, l);
+    }
+    
+    template <class T, class H, class P, class A>
+    template <class InputIt>
+    unordered_multiset<T,H,P,A>::unordered_multiset(
+            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_.insert_range(f, l);
+    }
+    
+    template <class T, class H, class P, class A>
+    unordered_multiset<T,H,P,A>::~unordered_multiset() {}
+
+    template <class T, class H, class P, class A>
+    unordered_multiset<T,H,P,A>::unordered_multiset(
+            unordered_multiset const& other)
+      : table_(other.table_)
+    {
+    }
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES)
+
+    template <class T, class H, class P, class A>
+    unordered_multiset<T,H,P,A>::unordered_multiset(
+            unordered_multiset&& other, allocator_type const& a)
+      : table_(other.table_, a, ::boost::unordered::detail::move_tag())
+    {
+    }
+
+#endif
+
+#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
+    template <class T, class H, class P, class A>
+    unordered_multiset<T,H,P,A>::unordered_multiset(
+            std::initializer_list<value_type> list, size_type n,
+            const hasher &hf, const key_equal &eql, const allocator_type &a)
+      : table_(
+            ::boost::unordered::detail::initial_size(
+                list.begin(), list.end(), n),
+            hf, eql, a)
+    {
+        table_.insert_range(list.begin(), list.end());
+    }
+
+    template <class T, class H, class P, class A>
+    unordered_multiset<T,H,P,A>& unordered_multiset<T,H,P,A>::operator=(
+            std::initializer_list<value_type> list)
+    {
+        table_.clear();
+        table_.insert_range(list.begin(), list.end());
+        return *this;
+    }
+#endif
+
+    // size and capacity
+
+    template <class T, class H, class P, class A>
+    std::size_t unordered_multiset<T,H,P,A>::max_size() const
+    {
+        return table_.max_size();
+    }
+
+    // modifiers
+
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+
+    template <class T, class H, class P, class A>
+    template <class... Args>
+    BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+        unordered_multiset<T,H,P,A>::emplace(Args&&... args)
+    {
+        return iterator(table_.emplace(std::forward<Args>(args)...));
+    }
+
+    template <class T, class H, class P, class A>
+    template <class... Args>
+    BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+        unordered_multiset<T,H,P,A>::emplace_hint(
+            const_iterator, Args&&... args)
+    {
+        return iterator(table_.emplace(std::forward<Args>(args)...));
+    }
+
+#else
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+        unordered_multiset<T,H,P,A>::emplace(
+                boost::unordered::detail::empty_emplace,
+                value_type v
+            )
+    {
+        return iterator(table_.emplace(boost::move(v)));
+    }
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+        unordered_multiset<T,H,P,A>::emplace_hint(const_iterator,
+                boost::unordered::detail::empty_emplace,
+                value_type v
+            )
+    {
+        return iterator(table_.emplace(boost::move(v)));
+    }
+
+#define BOOST_UNORDERED_EMPLACE(z, n, _)                                    \
+        template <class T, class H, class P, class A>                       \
+        template <                                                          \
+            BOOST_UNORDERED_TEMPLATE_ARGS(z, n)                             \
+        >                                                                   \
+        BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator        \
+            unordered_multiset<T,H,P,A>::emplace(                           \
+                BOOST_UNORDERED_FUNCTION_PARAMS(z, n))                      \
+        {                                                                   \
+            return iterator(table_.emplace(                                 \
+                BOOST_UNORDERED_CALL_PARAMS(z, n)));                        \
+        }                                                                   \
+                                                                            \
+        template <class T, class H, class P, class A>                       \
+        template <                                                          \
+            BOOST_UNORDERED_TEMPLATE_ARGS(z, n)                             \
+        >                                                                   \
+        BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator        \
+            unordered_multiset<T,H,P,A>::emplace_hint(                      \
+                const_iterator,                                             \
+                BOOST_UNORDERED_FUNCTION_PARAMS(z, n))                      \
+        {                                                                   \
+            return iterator(table_.emplace(                                 \
+                BOOST_UNORDERED_CALL_PARAMS(z, n)));                        \
+        }
+
+    BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
+        BOOST_UNORDERED_EMPLACE, _)
+
+#undef BOOST_UNORDERED_EMPLACE
+
+#endif
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+        unordered_multiset<T,H,P,A>::insert(value_type const& obj)
+    {
+        return iterator(table_.emplace(obj));
+    }
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+        unordered_multiset<T,H,P,A>::insert(const_iterator,
+                value_type const& obj)
+    {
+        return iterator(table_.emplace(obj));
+    }
+
+#if BOOST_UNORDERED_USE_RV_REF
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+        unordered_multiset<T,H,P,A>::insert(BOOST_RV_REF(value_type) obj)
+    {
+        return iterator(table_.emplace(boost::move(obj)));
+    }
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+        unordered_multiset<T,H,P,A>::insert(const_iterator,
+                BOOST_RV_REF(value_type) obj)
+    {
+        return iterator(table_.emplace(boost::move(obj)));
+    }
+#endif
+
+    template <class T, class H, class P, class A>
+    template <class InputIt>
+    void unordered_multiset<T,H,P,A>::insert(InputIt first, InputIt last)
+    {
+        table_.insert_range(first, last);
+    }
+
+#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
+    template <class T, class H, class P, class A>
+    void unordered_multiset<T,H,P,A>::insert(std::initializer_list<value_type> list)
+    {
+        table_.insert_range(list.begin(), list.end());
+    }
+#endif
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+        unordered_multiset<T,H,P,A>::erase(const_iterator position)
+    {
+        return iterator(table_.erase(position.node_));
+    }
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::size_type
+        unordered_multiset<T,H,P,A>::erase(const key_type& k)
+    {
+        return table_.erase_key(k);
+    }
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+        unordered_multiset<T,H,P,A>::erase(const_iterator first, const_iterator last)
+    {
+        return iterator(table_.erase_range(first.node_, last.node_));
+    }
+
+    template <class T, class H, class P, class A>
+    void unordered_multiset<T,H,P,A>::clear()
+    {
+        table_.clear();
+    }
+
+    template <class T, class H, class P, class A>
+    void unordered_multiset<T,H,P,A>::swap(unordered_multiset& other)
+    {
+        table_.swap(other.table_);
+    }
+
+    // observers
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::hasher
+        unordered_multiset<T,H,P,A>::hash_function() const
+    {
+        return table_.hash_function();
+    }
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::key_equal
+        unordered_multiset<T,H,P,A>::key_eq() const
+    {
+        return table_.key_eq();
+    }
+
+    // lookup
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::const_iterator
+        unordered_multiset<T,H,P,A>::find(const key_type& k) const
+    {
+        return const_iterator(table_.find_node(k));
+    }
+
+    template <class T, class H, class P, class A>
+    template <class CompatibleKey, class CompatibleHash,
+        class CompatiblePredicate>
+    BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::const_iterator
+        unordered_multiset<T,H,P,A>::find(
+            CompatibleKey const& k,
+            CompatibleHash const& hash,
+            CompatiblePredicate const& eq) const
+    {
+        return const_iterator(table_.generic_find_node(k, hash, eq));
+    }
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::size_type
+        unordered_multiset<T,H,P,A>::count(const key_type& k) const
+    {
+        return table_.count(k);
+    }
+
+    template <class T, class H, class P, class A>
+    std::pair<
+            BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::const_iterator,
+            BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::const_iterator>
+        unordered_multiset<T,H,P,A>::equal_range(const key_type& k) const
+    {
+        return BOOST_UNORDERED_PAIR_CAST(const_iterator, const_iterator,
+            table_.equal_range(k));
+    }
+
+    template <class T, class H, class P, class A>
+    BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::size_type
+        unordered_multiset<T,H,P,A>::bucket_size(size_type n) const
+    {
+        return table_.bucket_size(n);
+    }
+
+    // hash policy
+
+    template <class T, class H, class P, class A>
+    float unordered_multiset<T,H,P,A>::load_factor() const
+    {
+        return table_.load_factor();
+    }
+
+    template <class T, class H, class P, class A>
+    void unordered_multiset<T,H,P,A>::max_load_factor(float m)
+    {
+        table_.max_load_factor(m);
+    }
+
+    template <class T, class H, class P, class A>
+    void unordered_multiset<T,H,P,A>::rehash(size_type n)
+    {
+        table_.rehash(n);
+    }
+
     template <class T, class H, class P, class A>
-    inline bool operator==(unordered_multiset<T, H, P, A> const& m1,
-        unordered_multiset<T, H, P, A> const& m2)
+    inline bool operator==(
+            unordered_multiset<T,H,P,A> const& m1,
+            unordered_multiset<T,H,P,A> const& m2)
     {
 #if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
         struct dummy { unordered_multiset<T,H,P,A> x; };
@@ -1031,8 +1449,9 @@
     }
 
     template <class T, class H, class P, class A>
-    inline bool operator!=(unordered_multiset<T, H, P, A> const& m1,
-        unordered_multiset<T, H, P, A> const& m2)
+    inline bool operator!=(
+            unordered_multiset<T,H,P,A> const& m1,
+            unordered_multiset<T,H,P,A> const& m2)
     {
 #if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
         struct dummy { unordered_multiset<T,H,P,A> x; };
@@ -1041,8 +1460,9 @@
     }
 
     template <class T, class H, class P, class A>
-    inline void swap(unordered_multiset<T, H, P, A> &m1,
-            unordered_multiset<T, H, P, A> &m2)
+    inline void swap(
+            unordered_multiset<T,H,P,A> &m1,
+            unordered_multiset<T,H,P,A> &m2)
     {
 #if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
         struct dummy { unordered_multiset<T,H,P,A> x; };
@@ -1050,6 +1470,7 @@
         m1.swap(m2);
     }
 
+} // namespace unordered
 } // namespace boost
 
 #if defined(BOOST_MSVC)
Modified: branches/release/boost/unordered/unordered_set_fwd.hpp
==============================================================================
--- branches/release/boost/unordered/unordered_set_fwd.hpp	(original)
+++ branches/release/boost/unordered/unordered_set_fwd.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -1,5 +1,5 @@
 
-// Copyright (C) 2008-2009 Daniel James.
+// Copyright (C) 2008-2011 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)
 
@@ -10,42 +10,38 @@
 # pragma once
 #endif
 
-#include <boost/config.hpp>
-#include <memory>
-#include <functional>
-#include <boost/functional/hash_fwd.hpp>
+#include <boost/unordered/detail/fwd.hpp>
 
 namespace boost
 {
-    template <class T,
-        class H = hash<T>,
-        class P = std::equal_to<T>,
-        class A = std::allocator<T> >
-    class unordered_set;
-    template <class T, class H, class P, class A>
-    inline bool operator==(unordered_set<T, H, P, A> const&,
-        unordered_set<T, H, P, A> const&);
-    template <class T, class H, class P, class A>
-    inline bool operator!=(unordered_set<T, H, P, A> const&,
-        unordered_set<T, H, P, A> const&);
-    template <class T, class H, class P, class A>
-    inline void swap(unordered_set<T, H, P, A> &m1,
-            unordered_set<T, H, P, A> &m2);
-
-    template <class T,
-        class H = hash<T>,
-        class P = std::equal_to<T>,
-        class A = std::allocator<T> >
-    class unordered_multiset;
-    template <class T, class H, class P, class A>
-    inline bool operator==(unordered_multiset<T, H, P, A> const&,
-        unordered_multiset<T, H, P, A> const&);
-    template <class T, class H, class P, class A>
-    inline bool operator!=(unordered_multiset<T, H, P, A> const&,
-        unordered_multiset<T, H, P, A> const&);
-    template <class T, class H, class P, class A>
-    inline void swap(unordered_multiset<T, H, P, A> &m1,
-            unordered_multiset<T, H, P, A> &m2);
+    namespace unordered
+    {
+        template <class T, class H, class P, class A>
+        inline bool operator==(unordered_set<T, H, P, A> const&,
+            unordered_set<T, H, P, A> const&);
+        template <class T, class H, class P, class A>
+        inline bool operator!=(unordered_set<T, H, P, A> const&,
+            unordered_set<T, H, P, A> const&);
+        template <class T, class H, class P, class A>
+        inline void swap(unordered_set<T, H, P, A> &m1,
+                unordered_set<T, H, P, A> &m2);
+
+        template <class T, class H, class P, class A>
+        inline bool operator==(unordered_multiset<T, H, P, A> const&,
+            unordered_multiset<T, H, P, A> const&);
+        template <class T, class H, class P, class A>
+        inline bool operator!=(unordered_multiset<T, H, P, A> const&,
+            unordered_multiset<T, H, P, A> const&);
+        template <class T, class H, class P, class A>
+        inline void swap(unordered_multiset<T, H, P, A> &m1,
+                unordered_multiset<T, H, P, A> &m2);
+    }
+
+    using ::boost::unordered::unordered_set;
+    using ::boost::unordered::unordered_multiset;
+    using ::boost::unordered::swap;
+    using ::boost::unordered::operator==;
+    using ::boost::unordered::operator!=;
 }
 
 #endif
Modified: branches/release/libs/unordered/doc/changes.qbk
==============================================================================
--- branches/release/libs/unordered/doc/changes.qbk	(original)
+++ branches/release/libs/unordered/doc/changes.qbk	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -134,4 +134,21 @@
 * Fix a bug when inserting into an `unordered_map` or `unordered_set` using
   iterators which returns `value_type` by copy.
 
+[h2 Boost 1.48.0]
+
+This is major change which has been converted to use Boost.Move's move
+emulation, and be more compliant with the C++11 standard. This has resulted
+in some breaking changes:
+
+* Equality comparison has been changed to the C++11 specification.
+  In a container with equivalent keys, elements in a group with equal
+  keys used to have to be in the same order to be considered equal,
+  now they can be a permutation of each other.
+
+* The behaviour of swap is different when the two containers to be
+  swapped has unequal allocators. It used to allocate new nodes using
+  the appropriate allocators, it now swaps the allocators if
+  the allocator has a member structure `propagate_on_container_swap`,
+  such that `propagate_on_container_swap::value` is true.
+
 [endsect]
Modified: branches/release/libs/unordered/doc/rationale.qbk
==============================================================================
--- branches/release/libs/unordered/doc/rationale.qbk	(original)
+++ branches/release/libs/unordered/doc/rationale.qbk	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -126,7 +126,7 @@
 
 It isn't clear how to swap containers when their allocators aren't equal.
 This is 
-[@http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#431
+[@http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#431
 Issue 431: Swapping containers with unequal allocators]. This has been resolved
 with the new allocator specification, so this should be fixed when
 support is added.
Copied: branches/release/libs/unordered/doc/ref.php (from r73582, /trunk/libs/unordered/doc/ref.php)
==============================================================================
--- /trunk/libs/unordered/doc/ref.php	(original)
+++ branches/release/libs/unordered/doc/ref.php	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -792,6 +792,7 @@
                 <para>This is not specified in the draft standard, but that is probably an oversight. The issue has been raised in
                   <ulink url="http://groups.google.com/group/comp.std.c++/browse_thread/thread/ab7c22a868fd370b">comp.std.c++</ulink>.</para>
               </notes>
+            </overloaded-method>
 <?php endif; ?>
           </method-group>
           <method-group name="bucket interface">
Modified: branches/release/libs/unordered/doc/ref.xml
==============================================================================
--- branches/release/libs/unordered/doc/ref.xml	(original)
+++ branches/release/libs/unordered/doc/ref.xml	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -40,8 +40,8 @@
                     <row>
                       <entry><emphasis>Pred</emphasis></entry>
                       <entry>A binary function object that implements an equivalence relation on values of type <code>Value</code>.
-                        A binary function object that induces an equivalence relation on values of type Key.
-                        It takes two arguments of type Key and returns a value of type bool.</entry></row>
+                        A binary function object that induces an equivalence relation on values of type <code>Value</code>.
+                        It takes two arguments of type <code>Value</code> and returns a value of type bool.</entry></row>
                     <row>
                       <entry><emphasis>Alloc</emphasis></entry>
                       <entry>An allocator whose value type is the same as the container's value type.</entry></row></tbody></tgroup></informaltable></para>
@@ -360,7 +360,7 @@
               <type>iterator</type>
               <description>
                 <para>Inserts an object, constructed with the arguments <code>args</code>, in the container if and only if there is no element in the container with an equivalent value.</para>
-                <para>hint is a suggestion to where the element should be inserted.</para>
+                <para><code>hint</code> is a suggestion to where the element should be inserted.</para>
               </description>
               <returns>
                 <para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent value.</para>
@@ -383,7 +383,7 @@
               </parameter>
               <type>std::pair<iterator, bool></type>
               <description>
-                <para>Inserts obj in the container if and only if there is no element in the container with an equivalent value.</para>
+                <para>Inserts <code>obj</code> in the container if and only if there is no element in the container with an equivalent value.</para>
               </description>
               <returns>
                 <para>The bool component of the return type is true if an insert took place.</para>
@@ -406,7 +406,7 @@
               </parameter>
               <type>iterator</type>
               <description>
-                <para>Inserts obj in the container if and only if there is no element in the container with an equivalent value.</para>
+                <para>Inserts <code>obj</code> in the container if and only if there is no element in the container with an equivalent value.</para>
                 <para>hint is a suggestion to where the element should be inserted.</para>
               </description>
               <returns>
@@ -815,8 +815,8 @@
           <free-function-group name="Equality Comparisons">
             <function name="operator==">
               <template>
-                <template-type-parameter name="Value">
-                </template-type-parameter>
+            <template-type-parameter name="Value">
+            </template-type-parameter>
                 <template-type-parameter name="Hash">
                 </template-type-parameter>
                 <template-type-parameter name="Pred">
@@ -839,8 +839,8 @@
             </function>
             <function name="operator!=">
               <template>
-                <template-type-parameter name="Value">
-                </template-type-parameter>
+            <template-type-parameter name="Value">
+            </template-type-parameter>
                 <template-type-parameter name="Hash">
                 </template-type-parameter>
                 <template-type-parameter name="Pred">
@@ -865,8 +865,8 @@
           <free-function-group name="swap">
             <function name="swap">
               <template>
-                <template-type-parameter name="Value">
-                </template-type-parameter>
+            <template-type-parameter name="Value">
+            </template-type-parameter>
                 <template-type-parameter name="Hash">
                 </template-type-parameter>
                 <template-type-parameter name="Pred">
@@ -909,7 +909,7 @@
             </template-type-parameter>
           </template>
           <purpose><simpara>
-            An unordered associative container that stores  values. The same key can be stored multiple times.
+            An unordered associative container that stores values. The same key can be stored multiple times.
           </simpara></purpose>
           <description>
             <para>Based on chapter 23 of
@@ -929,8 +929,8 @@
                     <row>
                       <entry><emphasis>Pred</emphasis></entry>
                       <entry>A binary function object that implements an equivalence relation on values of type <code>Value</code>.
-                        A binary function object that induces an equivalence relation on values of type Key.
-                        It takes two arguments of type Key and returns a value of type bool.</entry></row>
+                        A binary function object that induces an equivalence relation on values of type <code>Value</code>.
+                        It takes two arguments of type <code>Value</code> and returns a value of type bool.</entry></row>
                     <row>
                       <entry><emphasis>Alloc</emphasis></entry>
                       <entry>An allocator whose value type is the same as the container's value type.</entry></row></tbody></tgroup></informaltable></para>
@@ -1248,7 +1248,7 @@
               <type>iterator</type>
               <description>
                 <para>Inserts an object, constructed with the arguments <code>args</code>, in the container.</para>
-                <para>hint is a suggestion to where the element should be inserted.</para>
+                <para><code>hint</code> is a suggestion to where the element should be inserted.</para>
               </description>
               <returns>
                 <para>An iterator pointing to the inserted element.</para>
@@ -1271,7 +1271,7 @@
               </parameter>
               <type>iterator</type>
               <description>
-                <para>Inserts obj in the container.</para>
+                <para>Inserts <code>obj</code> in the container.</para>
               </description>
               <returns>
                 <para>An iterator pointing to the inserted element.</para>
@@ -1293,7 +1293,7 @@
               </parameter>
               <type>iterator</type>
               <description>
-                <para>Inserts obj in the container.</para>
+                <para>Inserts <code>obj</code> in the container.</para>
                 <para>hint is a suggestion to where the element should be inserted.</para>
               </description>
               <returns>
@@ -1321,7 +1321,7 @@
               </parameter>
               <type>void</type>
               <description>
-                <para>Inserts a range of elements into the container.</para>
+                <para>Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent value.</para>
               </description>
               <throws>
                 <para>When inserting a single element, if an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
@@ -1702,8 +1702,8 @@
           <free-function-group name="Equality Comparisons">
             <function name="operator==">
               <template>
-                <template-type-parameter name="Value">
-                </template-type-parameter>
+            <template-type-parameter name="Value">
+            </template-type-parameter>
                 <template-type-parameter name="Hash">
                 </template-type-parameter>
                 <template-type-parameter name="Pred">
@@ -1726,8 +1726,8 @@
             </function>
             <function name="operator!=">
               <template>
-                <template-type-parameter name="Value">
-                </template-type-parameter>
+            <template-type-parameter name="Value">
+            </template-type-parameter>
                 <template-type-parameter name="Hash">
                 </template-type-parameter>
                 <template-type-parameter name="Pred">
@@ -1752,8 +1752,8 @@
           <free-function-group name="swap">
             <function name="swap">
               <template>
-                <template-type-parameter name="Value">
-                </template-type-parameter>
+            <template-type-parameter name="Value">
+            </template-type-parameter>
                 <template-type-parameter name="Hash">
                 </template-type-parameter>
                 <template-type-parameter name="Pred">
@@ -1798,7 +1798,7 @@
               <default><type>std::equal_to<Key></type></default>
             </template-type-parameter>
             <template-type-parameter name="Alloc">
-              <default><type>std::allocator<std::pair<Key const, Mapped> ></type></default>
+              <default><type>std::allocator<std::pair<Key const, Mapped>></type></default>
             </template-type-parameter>
           </template>
           <purpose><simpara>
@@ -1825,8 +1825,8 @@
                     <row>
                       <entry><emphasis>Pred</emphasis></entry>
                       <entry>A binary function object that implements an equivalence relation on values of type <code>Key</code>.
-                        A binary function object that induces an equivalence relation on values of type Key.
-                        It takes two arguments of type Key and returns a value of type bool.</entry></row>
+                        A binary function object that induces an equivalence relation on values of type <code>Key</code>.
+                        It takes two arguments of type <code>Key</code> and returns a value of type bool.</entry></row>
                     <row>
                       <entry><emphasis>Alloc</emphasis></entry>
                       <entry>An allocator whose value type is the same as the container's value type.</entry></row></tbody></tgroup></informaltable></para>
@@ -1882,7 +1882,7 @@
           <typedef name="iterator">
             <type><emphasis>implementation-defined</emphasis></type>
             <description>
-              <para>A iterator whose value type is <type>value_type</type>. </para>
+              <para>An iterator whose value type is <type>value_type</type>. </para>
               <para>The iterator category is at least a forward iterator.</para>
               <para>Convertible to <type>const_iterator</type>.</para>
             </description>
@@ -2148,7 +2148,7 @@
               <type>iterator</type>
               <description>
                 <para>Inserts an object, constructed with the arguments <code>args</code>, in the container if and only if there is no element in the container with an equivalent key.</para>
-                <para>hint is a suggestion to where the element should be inserted.</para>
+                <para><code>hint</code> is a suggestion to where the element should be inserted.</para>
               </description>
               <returns>
                 <para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key.</para>
@@ -2171,7 +2171,7 @@
               </parameter>
               <type>std::pair<iterator, bool></type>
               <description>
-                <para>Inserts obj in the container if and only if there is no element in the container with an equivalent key.</para>
+                <para>Inserts <code>obj</code> in the container if and only if there is no element in the container with an equivalent key.</para>
               </description>
               <returns>
                 <para>The bool component of the return type is true if an insert took place.</para>
@@ -2194,7 +2194,7 @@
               </parameter>
               <type>iterator</type>
               <description>
-                <para>Inserts obj in the container if and only if there is no element in the container with an equivalent key.</para>
+                <para>Inserts <code>obj</code> in the container if and only if there is no element in the container with an equivalent key.</para>
                 <para>hint is a suggestion to where the element should be inserted.</para>
               </description>
               <returns>
@@ -2638,10 +2638,10 @@
           <free-function-group name="Equality Comparisons">
             <function name="operator==">
               <template>
-                <template-type-parameter name="Key">
-                </template-type-parameter>
-                <template-type-parameter name="Mapped">
-                </template-type-parameter>
+            <template-type-parameter name="Key">
+            </template-type-parameter>
+            <template-type-parameter name="Mapped">
+            </template-type-parameter>
                 <template-type-parameter name="Hash">
                 </template-type-parameter>
                 <template-type-parameter name="Pred">
@@ -2664,10 +2664,10 @@
             </function>
             <function name="operator!=">
               <template>
-                <template-type-parameter name="Key">
-                </template-type-parameter>
-                <template-type-parameter name="Mapped">
-                </template-type-parameter>
+            <template-type-parameter name="Key">
+            </template-type-parameter>
+            <template-type-parameter name="Mapped">
+            </template-type-parameter>
                 <template-type-parameter name="Hash">
                 </template-type-parameter>
                 <template-type-parameter name="Pred">
@@ -2692,10 +2692,10 @@
           <free-function-group name="swap">
             <function name="swap">
               <template>
-                <template-type-parameter name="Key">
-                </template-type-parameter>
-                <template-type-parameter name="Mapped">
-                </template-type-parameter>
+            <template-type-parameter name="Key">
+            </template-type-parameter>
+            <template-type-parameter name="Mapped">
+            </template-type-parameter>
                 <template-type-parameter name="Hash">
                 </template-type-parameter>
                 <template-type-parameter name="Pred">
@@ -2736,11 +2736,11 @@
               <default><type>std::equal_to<Key></type></default>
             </template-type-parameter>
             <template-type-parameter name="Alloc">
-              <default><type>std::allocator<std::pair<Key const, Mapped> ></type></default>
+              <default><type>std::allocator<std::pair<Key const, Mapped>></type></default>
             </template-type-parameter>
           </template>
           <purpose><simpara>
-            An unordered associative container that associates  keys with another value. The same key can be stored multiple times.
+            An unordered associative container that associates keys with another value. The same key can be stored multiple times.
           </simpara></purpose>
           <description>
             <para>Based on chapter 23 of
@@ -2763,8 +2763,8 @@
                     <row>
                       <entry><emphasis>Pred</emphasis></entry>
                       <entry>A binary function object that implements an equivalence relation on values of type <code>Key</code>.
-                        A binary function object that induces an equivalence relation on values of type Key.
-                        It takes two arguments of type Key and returns a value of type bool.</entry></row>
+                        A binary function object that induces an equivalence relation on values of type <code>Key</code>.
+                        It takes two arguments of type <code>Key</code> and returns a value of type bool.</entry></row>
                     <row>
                       <entry><emphasis>Alloc</emphasis></entry>
                       <entry>An allocator whose value type is the same as the container's value type.</entry></row></tbody></tgroup></informaltable></para>
@@ -2820,7 +2820,7 @@
           <typedef name="iterator">
             <type><emphasis>implementation-defined</emphasis></type>
             <description>
-              <para>A iterator whose value type is <type>value_type</type>. </para>
+              <para>An iterator whose value type is <type>value_type</type>. </para>
               <para>The iterator category is at least a forward iterator.</para>
               <para>Convertible to <type>const_iterator</type>.</para>
             </description>
@@ -3085,7 +3085,7 @@
               <type>iterator</type>
               <description>
                 <para>Inserts an object, constructed with the arguments <code>args</code>, in the container.</para>
-                <para>hint is a suggestion to where the element should be inserted.</para>
+                <para><code>hint</code> is a suggestion to where the element should be inserted.</para>
               </description>
               <returns>
                 <para>An iterator pointing to the inserted element.</para>
@@ -3108,7 +3108,7 @@
               </parameter>
               <type>iterator</type>
               <description>
-                <para>Inserts obj in the container.</para>
+                <para>Inserts <code>obj</code> in the container.</para>
               </description>
               <returns>
                 <para>An iterator pointing to the inserted element.</para>
@@ -3130,7 +3130,7 @@
               </parameter>
               <type>iterator</type>
               <description>
-                <para>Inserts obj in the container.</para>
+                <para>Inserts <code>obj</code> in the container.</para>
                 <para>hint is a suggestion to where the element should be inserted.</para>
               </description>
               <returns>
@@ -3158,7 +3158,7 @@
               </parameter>
               <type>void</type>
               <description>
-                <para>Inserts a range of elements into the container.</para>
+                <para>Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key.</para>
               </description>
               <throws>
                 <para>When inserting a single element, if an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
@@ -3539,10 +3539,10 @@
           <free-function-group name="Equality Comparisons">
             <function name="operator==">
               <template>
-                <template-type-parameter name="Key">
-                </template-type-parameter>
-                <template-type-parameter name="Mapped">
-                </template-type-parameter>
+            <template-type-parameter name="Key">
+            </template-type-parameter>
+            <template-type-parameter name="Mapped">
+            </template-type-parameter>
                 <template-type-parameter name="Hash">
                 </template-type-parameter>
                 <template-type-parameter name="Pred">
@@ -3565,10 +3565,10 @@
             </function>
             <function name="operator!=">
               <template>
-                <template-type-parameter name="Key">
-                </template-type-parameter>
-                <template-type-parameter name="Mapped">
-                </template-type-parameter>
+            <template-type-parameter name="Key">
+            </template-type-parameter>
+            <template-type-parameter name="Mapped">
+            </template-type-parameter>
                 <template-type-parameter name="Hash">
                 </template-type-parameter>
                 <template-type-parameter name="Pred">
@@ -3593,10 +3593,10 @@
           <free-function-group name="swap">
             <function name="swap">
               <template>
-                <template-type-parameter name="Key">
-                </template-type-parameter>
-                <template-type-parameter name="Mapped">
-                </template-type-parameter>
+            <template-type-parameter name="Key">
+            </template-type-parameter>
+            <template-type-parameter name="Mapped">
+            </template-type-parameter>
                 <template-type-parameter name="Hash">
                 </template-type-parameter>
                 <template-type-parameter name="Pred">
Modified: branches/release/libs/unordered/doc/unordered.qbk
==============================================================================
--- branches/release/libs/unordered/doc/unordered.qbk	(original)
+++ branches/release/libs/unordered/doc/unordered.qbk	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -31,6 +31,7 @@
 [include:unordered buckets.qbk]
 [include:unordered hash_equality.qbk]
 [include:unordered comparison.qbk]
+[include:unordered compliance.qbk]
 [include:unordered rationale.qbk]
 [include:unordered changes.qbk]
 [xinclude ref.xml]
Modified: branches/release/libs/unordered/test/exception/swap_exception_tests.cpp
==============================================================================
--- branches/release/libs/unordered/test/exception/swap_exception_tests.cpp	(original)
+++ branches/release/libs/unordered/test/exception/swap_exception_tests.cpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -27,13 +27,12 @@
     void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const {
         std::string scope(test::scope);
 
-#if BOOST_UNORDERED_SWAP_METHOD != 2
+        // TODO: In C++11 exceptions are only allowed in the swap function.
         BOOST_TEST(
-                scope == "hash::operator(hash)" ||
+                scope == "hash::hash(hash)" ||
                 scope == "hash::operator=(hash)" ||
-                scope == "equal_to::operator(equal_to)" ||
+                scope == "equal_to::equal_to(equal_to)" ||
                 scope == "equal_to::operator=(equal_to)");
-#endif
 
         test::check_equivalent_keys(x);
     }
@@ -82,13 +81,12 @@
     void check BOOST_PREVENT_MACRO_SUBSTITUTION(data_type const& d) const {
         std::string scope(test::scope);
 
-#if BOOST_UNORDERED_SWAP_METHOD != 2
+        // TODO: In C++11 exceptions are only allowed in the swap function.
         BOOST_TEST(
-                scope == "hash::operator(hash)" ||
+                scope == "hash::hash(hash)" ||
                 scope == "hash::operator=(hash)" ||
-                scope == "equal_to::operator(equal_to)" ||
+                scope == "equal_to::equal_to(equal_to)" ||
                 scope == "equal_to::operator=(equal_to)");
-#endif
         
         test::check_equivalent_keys(d.x);
         test::check_equivalent_keys(d.y);
Modified: branches/release/libs/unordered/test/helpers/count.hpp
==============================================================================
--- branches/release/libs/unordered/test/helpers/count.hpp	(original)
+++ branches/release/libs/unordered/test/helpers/count.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -75,6 +75,13 @@
     namespace {
         object_count& global_object_count = globally_counted_object::count_;
     }
+    
+    struct check_instances {
+        int instances;
+        
+        check_instances() : instances(global_object_count.instances) {}
+        ~check_instances() { BOOST_TEST(global_object_count.instances == instances); }
+    };
 }
 
 #endif
Modified: branches/release/libs/unordered/test/helpers/invariants.hpp
==============================================================================
--- branches/release/libs/unordered/test/helpers/invariants.hpp	(original)
+++ branches/release/libs/unordered/test/helpers/invariants.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -65,37 +65,32 @@
                 std::cerr<<x1.count(key)<<","<<count<<"\n";
             }
 
-            // I'm not bothering with the following test for now, as the
-            // previous test is probably more enough to catch the kind of
-            // errors that this would catch (if an element was in the wrong
-            // bucket it not be found by the call to count, if elements are not
-            // adjacent then they would be caught when checking against
-            // found_.
-
-            // // Check that the keys are in the correct bucket and are
-            // // adjacent in the bucket.
-            // BOOST_DEDUCED_TYPENAME X::size_type bucket = x1.bucket(key);
-            // BOOST_DEDUCED_TYPENAME X::const_local_iterator
-            //     lit = x1.begin(bucket), lend = x1.end(bucket);
-            // for(; lit != lend && !eq(get_key<X>(*lit), key); ++lit) continue;
-            // if(lit == lend)
-            //     BOOST_ERROR("Unable to find element with a local_iterator");
-            // unsigned int count2 = 0;
-            // for(; lit != lend && eq(get_key<X>(*lit), key); ++lit) ++count2;
-            // if(count != count2)
-            //     BOOST_ERROR("Element count doesn't match local_iterator.");
-            // for(; lit != lend; ++lit) {
-            //     if(eq(get_key<X>(*lit), key)) {
-            //         BOOST_ERROR("Non-adjacent element with equivalent key "
-            //             "in bucket.");
-            //         break;
-            //     }
-            // }
+            // Check that the keys are in the correct bucket and are
+            // adjacent in the bucket.
+            BOOST_DEDUCED_TYPENAME X::size_type bucket = x1.bucket(key);
+            BOOST_DEDUCED_TYPENAME X::const_local_iterator
+                lit = x1.begin(bucket), lend = x1.end(bucket);
+            for(; lit != lend && !eq(get_key<X>(*lit), key); ++lit) continue;
+            if(lit == lend)
+                BOOST_ERROR("Unable to find element with a local_iterator");
+            unsigned int count2 = 0;
+            for(; lit != lend && eq(get_key<X>(*lit), key); ++lit) ++count2;
+            if(count != count2)
+                BOOST_ERROR("Element count doesn't match local_iterator.");
+            for(; lit != lend; ++lit) {
+                if(eq(get_key<X>(*lit), key)) {
+                    BOOST_ERROR("Non-adjacent element with equivalent key "
+                        "in bucket.");
+                    break;
+                }
+            }
         };
 
         // Finally, check that size matches up.
-        if(x1.size() != size)
+        if(x1.size() != size) {
             BOOST_ERROR("x1.size() doesn't match actual size.");
+            std::cout<<x1.size()<<"/"<<size<<std::endl;
+        }
         float load_factor =
             static_cast<float>(size) / static_cast<float>(x1.bucket_count());
         using namespace std;
Modified: branches/release/libs/unordered/test/helpers/memory.hpp
==============================================================================
--- branches/release/libs/unordered/test/helpers/memory.hpp	(original)
+++ branches/release/libs/unordered/test/helpers/memory.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -70,7 +70,7 @@
         template <class Alloc = std::allocator<int> >
         struct memory_tracker {
             typedef BOOST_DEDUCED_TYPENAME
-                boost::unordered_detail::rebind_wrap<Alloc,
+                ::boost::unordered::detail::rebind_wrap<Alloc,
                     std::pair<memory_area const, memory_track> >::type
                 allocator_type;
 
@@ -137,7 +137,7 @@
             }
 
             void track_deallocate(void* ptr, std::size_t n, std::size_t size,
-                int tag)
+                int tag, bool check_tag_ = true)
             {
                 BOOST_DEDUCED_TYPENAME allocated_memory_type::iterator pos =
                     allocated_memory.find(
@@ -147,7 +147,7 @@
                 } else {
                     BOOST_TEST(pos->first.start == ptr);
                     BOOST_TEST(pos->first.end == (char*) ptr + n * size);
-                    BOOST_TEST(pos->second.tag_ == tag);
+                    if (check_tag_) BOOST_TEST(pos->second.tag_ == tag);
                     allocated_memory.erase(pos);
                 }
                 BOOST_TEST(count_allocations > 0);
@@ -168,6 +168,37 @@
             }
         };
     }
+
+    namespace detail
+    {
+        // This won't be a problem as I'm only using a single compile unit
+        // in each test (this is actually required by the minimal test
+        // framework).
+        // 
+        // boostinspect:nounnamed
+        namespace {
+            test::detail::memory_tracker<std::allocator<int> > tracker;
+        }
+    }
+    
+    template <int Value>
+    struct bool_type {
+        enum { value = (Value ? true : false) };
+    };
+
+    struct true_type {
+        enum { value = true };
+    };
+
+    struct false_type {
+        enum { value = false };
+    };
+
+    template <typename Alloc>
+    int selected_count(Alloc const&)
+    {
+        return 0;
+    }
 }
 
 #endif
Modified: branches/release/libs/unordered/test/objects/exception.hpp
==============================================================================
--- branches/release/libs/unordered/test/objects/exception.hpp	(original)
+++ branches/release/libs/unordered/test/objects/exception.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -34,6 +34,16 @@
     template <class T> class allocator;
     object generate(object const*);
 
+    struct true_type
+    {
+        enum { value = true };
+    };
+
+    struct false_type
+    {
+        enum { value = false };
+    };
+
     class object
     {
     public:
@@ -340,15 +350,15 @@
         }
 
         void construct(pointer p, T const& t) {
-            UNORDERED_SCOPE(allocator::construct(pointer, T)) {
+            UNORDERED_SCOPE(allocator::construct(T*, T)) {
                 UNORDERED_EPOINT("Mock allocator construct function.");
                 new(p) T(t);
             }
             detail::tracker.track_construct((void*) p, sizeof(T), tag_);
         }
 
-#if defined(BOOST_UNORDERED_STD_FORWARD)
-        template<class... Args> void construct(pointer p, Args&&... args) {
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+        template<class... Args> void construct(T* p, Args&&... args) {
             UNORDERED_SCOPE(allocator::construct(pointer, Args&&...)) {
                 UNORDERED_EPOINT("Mock allocator construct function.");
                 new(p) T(std::forward<Args>(args)...);
@@ -357,7 +367,7 @@
         }
 #endif
 
-        void destroy(pointer p) {
+        void destroy(T* p) {
             detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
             p->~T();
         }
@@ -368,6 +378,10 @@
             }
             return (std::numeric_limits<std::size_t>::max)();
         }
+
+        typedef true_type propagate_on_container_copy_assignment;
+        typedef true_type propagate_on_container_move_assignment;
+        typedef true_type propagate_on_container_swap;
     };
 
     template <class T>
Modified: branches/release/libs/unordered/test/objects/minimal.hpp
==============================================================================
--- branches/release/libs/unordered/test/objects/minimal.hpp	(original)
+++ branches/release/libs/unordered/test/objects/minimal.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -11,6 +11,8 @@
 #define BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER
 
 #include <cstddef>
+#include <boost/move/move.hpp>
+#include <utility>
 
 #if defined(BOOST_MSVC)
 #pragma warning(push)
@@ -21,6 +23,7 @@
 {
 namespace minimal
 {
+    class destructible;
     class copy_constructible;
     class copy_constructible_equality_comparable;
     class default_copy_constructible;
@@ -33,11 +36,27 @@
     template <class T> class ptr;
     template <class T> class const_ptr;
     template <class T> class allocator;
+    template <class T> class cxx11_allocator;
+
+    struct constructor_param
+    {
+        operator int() const { return 0; }
+    };
+
+    class destructible
+    {
+    public:
+        destructible(constructor_param const&) {}
+        ~destructible() {}
+    private:
+        destructible(destructible const&);
+        destructible& operator=(destructible const&);
+    };
 
     class copy_constructible
     {
     public:
-        static copy_constructible create() { return copy_constructible(); }
+        copy_constructible(constructor_param const&) {}
         copy_constructible(copy_constructible const&) {}
         ~copy_constructible() {}
     private:
@@ -48,9 +67,7 @@
     class copy_constructible_equality_comparable
     {
     public:
-        static copy_constructible_equality_comparable create() {
-            return copy_constructible_equality_comparable();
-        }
+        copy_constructible_equality_comparable(constructor_param const&) {}
 
         copy_constructible_equality_comparable(
             copy_constructible_equality_comparable const&)
@@ -85,10 +102,7 @@
     class default_copy_constructible
     {
     public:
-        static default_copy_constructible create()
-        {
-            return default_copy_constructible();
-        }
+        default_copy_constructible(constructor_param const&) {}
 
         default_copy_constructible()
         {
@@ -105,13 +119,14 @@
     private:
         default_copy_constructible& operator=(
             default_copy_constructible const&);
-        ampersand_operator_used operator&() const { return ampersand_operator_used(); }
+        ampersand_operator_used operator&() const {
+            return ampersand_operator_used(); }
     };
 
     class assignable
     {
     public:
-        static assignable create() { return assignable(); }
+        assignable(constructor_param const&) {}
         assignable(assignable const&) {}
         assignable& operator=(assignable const&) { return *this; }
         ~assignable() {}
@@ -122,11 +137,43 @@
         //ampersand_operator_used operator&() const { return ampersand_operator_used(); }
     };
 
+    struct movable_init {};
+
+    class movable1
+    {
+        BOOST_MOVABLE_BUT_NOT_COPYABLE(movable1)
+
+    public:
+        movable1(constructor_param const&) {}
+        movable1() {}
+        explicit movable1(movable_init) {}
+        movable1(BOOST_RV_REF(movable1)) {}
+        movable1& operator=(BOOST_RV_REF(movable1));
+        ~movable1() {}
+    };
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES)
+    class movable2
+    {
+    public:
+        movable2(constructor_param const&) {}
+        explicit movable2(movable_init) {}
+        movable2(movable2&&) {}
+        ~movable2() {}
+    private:
+        movable2() {}
+        movable2(movable2 const&);
+        movable2& operator=(movable2 const&);
+    };
+#else
+    typedef movable1 movable2;
+#endif
+
     template <class T>
     class hash
     {
     public:
-        static hash create() { return hash<T>(); }
+        hash(constructor_param const&) {}
         hash() {}
         hash(hash const&) {}
         hash& operator=(hash const&) { return *this; }
@@ -141,7 +188,7 @@
     class equal_to
     {
     public:
-        static equal_to create() { return equal_to<T>(); }
+        equal_to(constructor_param const&) {}
         equal_to() {}
         equal_to(equal_to const&) {}
         equal_to& operator=(equal_to const&) { return *this; }
@@ -278,15 +325,15 @@
             ::operator delete((void*) p.ptr_);
         }
 
-        void construct(pointer p, T const& t) { new((void*)p.ptr_) T(t); }
+        void construct(T* p, T const& t) { new((void*)p) T(t); }
 
-#if defined(BOOST_UNORDERED_STD_FORWARD)
-        template<class... Args> void construct(pointer p, Args&&... args) {
-            new((void*)p.ptr_) T(std::forward<Args>(args)...);
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+        template<class... Args> void construct(T* p, Args&&... args) {
+            new((void*)p) T(std::forward<Args>(args)...);
         }
 #endif
 
-        void destroy(pointer p) { ((T*)p.ptr_)->~T(); }
+        void destroy(T* p) { p->~T(); }
 
         size_type max_size() const { return 1000; }
 
@@ -316,6 +363,69 @@
     void swap(allocator<T>&, allocator<T>&)
     {
     }
+
+    // C++11 allocator
+    //
+    // Not a fully minimal C++11 allocator, just what I support. Hopefully will
+    // cut down further in the future.
+
+    template <class T>
+    class cxx11_allocator
+    {
+    public:
+        typedef T value_type;
+        template <class U> struct rebind { typedef cxx11_allocator<U> other; };
+
+        cxx11_allocator() {}
+        template <class Y> cxx11_allocator(cxx11_allocator<Y> const&) {}
+        cxx11_allocator(cxx11_allocator const&) {}
+        ~cxx11_allocator() {}
+
+        T* address(T& r) { return &r; }
+        T const* address(T const& r) { return &r; }
+
+        T* allocate(std::size_t n) {
+            return static_cast<T*>(::operator new(n * sizeof(T)));
+        }
+
+        template <class Y>
+        T* allocate(std::size_t n, const_ptr<Y> u) {
+            return static_cast<T*>(::operator new(n * sizeof(T)));
+        }
+
+        void deallocate(T* p, std::size_t) {
+            ::operator delete((void*) p);
+        }
+
+        void construct(T* p, T const& t) { new((void*)p) T(t); }
+
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+        template<class... Args> void construct(T* p, Args&&... args) {
+            new((void*)p) T(std::forward<Args>(args)...);
+        }
+#endif
+
+        void destroy(T* p) { p->~T(); }
+
+        std::size_t max_size() const { return 1000u; }
+    };
+
+    template <class T>
+    inline bool operator==(cxx11_allocator<T> const&, cxx11_allocator<T> const&)
+    {
+        return true;
+    }
+
+    template <class T>
+    inline bool operator!=(cxx11_allocator<T> const&, cxx11_allocator<T> const&)
+    {
+        return false;
+    }
+
+    template <class T>
+    void swap(cxx11_allocator<T>&, cxx11_allocator<T>&)
+    {
+    }
 }
 }
 
Modified: branches/release/libs/unordered/test/objects/test.hpp
==============================================================================
--- branches/release/libs/unordered/test/objects/test.hpp	(original)
+++ branches/release/libs/unordered/test/objects/test.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -9,11 +9,9 @@
 #include <boost/config.hpp>
 #include <boost/limits.hpp>
 #include <cstddef>
-#include <iostream>
 #include "../helpers/fwd.hpp"
 #include "../helpers/count.hpp"
 #include "../helpers/memory.hpp"
-#include <map>
 
 namespace test
 {
@@ -27,7 +25,7 @@
     template <class T> class allocator;
     object generate(object const*);
     implicitly_convertible generate(implicitly_convertible const*);
-
+    
     class object : globally_counted_object
     {
         friend class hash;
@@ -185,18 +183,6 @@
         }
     };
 
-    namespace detail
-    {
-        // This won't be a problem as I'm only using a single compile unit
-        // in each test (this is actually require by the minimal test
-        // framework).
-        // 
-        // boostinspect:nounnamed
-        namespace {
-            test::detail::memory_tracker<std::allocator<int> > tracker;
-        }
-    }
-
     template <class T>
     class allocator
     {
@@ -268,19 +254,19 @@
             ::operator delete((void*) p);
         }
 
-        void construct(pointer p, T const& t) {
+        void construct(T* p, T const& t) {
             detail::tracker.track_construct((void*) p, sizeof(T), tag_);
             new(p) T(t);
         }
 
-#if defined(BOOST_UNORDERED_STD_FORWARD)
-        template<class... Args> void construct(pointer p, Args&&... args) {
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+        template<class... Args> void construct(T* p, Args&&... args) {
             detail::tracker.track_construct((void*) p, sizeof(T), tag_);
             new(p) T(std::forward<Args>(args)...);
         }
 #endif
 
-        void destroy(pointer p) {
+        void destroy(T* p) {
             detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
             p->~T();
         }
@@ -298,6 +284,13 @@
         {
             return tag_ != x.tag_;
         }
+
+        enum {
+            is_select_on_copy = false,
+            is_propagate_on_swap = false,
+            is_propagate_on_assign = false,
+            is_propagate_on_move = false
+        };
     };
 
     template <class T>
Modified: branches/release/libs/unordered/test/unordered/Jamfile.v2
==============================================================================
--- branches/release/libs/unordered/test/unordered/Jamfile.v2	(original)
+++ branches/release/libs/unordered/test/unordered/Jamfile.v2	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -43,5 +43,5 @@
         [ run load_factor_tests.cpp ]
         [ run rehash_tests.cpp ]
         [ run equality_tests.cpp ]
-        [ run swap_tests.cpp : : : <define>BOOST_UNORDERED_SWAP_METHOD=2 ]
+        [ run swap_tests.cpp ]
     ;
Modified: branches/release/libs/unordered/test/unordered/assign_tests.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/assign_tests.cpp	(original)
+++ branches/release/libs/unordered/test/unordered/assign_tests.cpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -9,12 +9,17 @@
 #include <boost/unordered_map.hpp>
 #include "../helpers/test.hpp"
 #include "../objects/test.hpp"
+#include "../objects/cxx11_allocator.hpp"
 #include "../helpers/random_values.hpp"
 #include "../helpers/tracker.hpp"
 #include "../helpers/equivalent.hpp"
 
 #include <iostream>
 
+#if defined(BOOST_MSVC)
+#pragma warning(disable:4127) // conditional expression is constant
+#endif
+
 namespace assign_tests {
 
 test::seed_t seed(96785);
@@ -28,6 +33,8 @@
 
     std::cerr<<"assign_tests1.1\n";
     {
+        test::check_instances check_;
+
         T x;
         x = x;
         BOOST_TEST(x.empty());
@@ -37,6 +44,8 @@
 
     std::cerr<<"assign_tests1.2\n";
     {
+        test::check_instances check_;
+
         test::random_values<T> v(1000, generator);
         T x(v.begin(), v.end());
 
@@ -64,9 +73,13 @@
     BOOST_DEDUCED_TYPENAME T::key_equal eq2(2);
     BOOST_DEDUCED_TYPENAME T::allocator_type al1(1);
     BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
-
+    
+    typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
+    
     std::cerr<<"assign_tests2.1\n";
     {
+        test::check_instances check_;
+
         test::random_values<T> v(1000, generator);
         T x1(v.begin(), v.end(), 0, hf1, eq1);
         T x2(0, hf2, eq2);
@@ -78,13 +91,22 @@
 
     std::cerr<<"assign_tests2.2\n";
     {
+        test::check_instances check_;
+
         test::random_values<T> v1(100, generator), v2(100, generator);
         T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
         T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
         x2 = x1;
         BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
         BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
-        BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
+        if (allocator_type::is_propagate_on_assign) {
+            BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
+            BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
+        }
+        else {
+            BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
+            BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
+        }
         test::check_container(x2, v1);
     }
 }
@@ -102,16 +124,69 @@
     test::hash, test::equal_to,
     test::allocator<test::object> >* test_multimap;
 
+boost::unordered_set<test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::propagate_assign> >*
+    test_set_prop_assign;
+boost::unordered_multiset<test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::propagate_assign> >*
+    test_multiset_prop_assign;
+boost::unordered_map<test::object, test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::propagate_assign> >*
+    test_map_prop_assign;
+boost::unordered_multimap<test::object, test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::propagate_assign> >*
+    test_multimap_prop_assign;
+
+boost::unordered_set<test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::no_propagate_assign> >*
+    test_set_no_prop_assign;
+boost::unordered_multiset<test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::no_propagate_assign> >*
+    test_multiset_no_prop_assign;
+boost::unordered_map<test::object, test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::no_propagate_assign> >*
+    test_map_no_prop_assign;
+boost::unordered_multimap<test::object, test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::no_propagate_assign> >*
+    test_multimap_no_prop_assign;
+
 using test::default_generator;
 using test::generate_collisions;
 
-UNORDERED_TEST(assign_tests1,
-    ((test_set)(test_multiset)(test_map)(test_multimap))
+template <typename T>
+bool is_propagate(T*)
+{
+    return T::allocator_type::is_propagate_on_assign;
+}
+
+UNORDERED_AUTO_TEST(check_traits)
+{
+    BOOST_TEST(!is_propagate(test_set));
+    BOOST_TEST(is_propagate(test_set_prop_assign));
+    BOOST_TEST(!is_propagate(test_set_no_prop_assign));
+}
+
+UNORDERED_TEST(assign_tests1, (
+        (test_set)(test_multiset)(test_map)(test_multimap)
+        (test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(test_multimap_prop_assign)
+        (test_set_no_prop_assign)(test_multiset_no_prop_assign)(test_map_no_prop_assign)(test_multimap_no_prop_assign)
+    )
     ((default_generator)(generate_collisions))
 )
 
-UNORDERED_TEST(assign_tests2,
-    ((test_set)(test_multiset)(test_map)(test_multimap))
+UNORDERED_TEST(assign_tests2, (
+        (test_set)(test_multiset)(test_map)(test_multimap)
+        (test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(test_multimap_prop_assign)
+        (test_set_no_prop_assign)(test_multiset_no_prop_assign)(test_map_no_prop_assign)(test_multimap_no_prop_assign)
+    )
     ((default_generator)(generate_collisions))
 )
 
Modified: branches/release/libs/unordered/test/unordered/bucket_tests.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/bucket_tests.cpp	(original)
+++ branches/release/libs/unordered/test/unordered/bucket_tests.cpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -25,6 +25,8 @@
 template <class X>
 void tests(X* = 0, test::random_generator generator = test::default_generator)
 {
+    test::check_instances check_;
+
     typedef BOOST_DEDUCED_TYPENAME X::size_type size_type;
     typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
     test::random_values<X> v(1000, generator);
Modified: branches/release/libs/unordered/test/unordered/compile_map.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/compile_map.cpp	(original)
+++ branches/release/libs/unordered/test/unordered/compile_map.cpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -18,6 +18,19 @@
 // Explicit instantiation to catch compile-time errors
 
 template class boost::unordered_map<
+    int,
+    int,
+    boost::hash<int>,
+    std::equal_to<int>,
+    test::minimal::allocator<std::pair<int const, int> > >;
+template class boost::unordered_multimap<
+    int,
+    int,
+    boost::hash<int>,
+    std::equal_to<int>,
+    test::minimal::allocator<std::pair<int const, int> > >;
+
+template class boost::unordered_map<
     test::minimal::assignable,
     test::minimal::default_copy_constructible,
     test::minimal::hash<test::minimal::assignable>,
@@ -32,16 +45,21 @@
 
 UNORDERED_AUTO_TEST(test0)
 {
+    test::minimal::constructor_param x;
+
     typedef std::pair<test::minimal::assignable const,
             test::minimal::copy_constructible> value_type;
-    value_type value(
-            test::minimal::assignable::create(),
-            test::minimal::copy_constructible::create());
+    value_type value(x, x);
 
     std::cout<<"Test unordered_map.\n";
 
     boost::unordered_map<int, int> int_map;
 
+    boost::unordered_map<int, int,
+        boost::hash<int>, std::equal_to<int>,
+        test::minimal::cxx11_allocator<std::pair<int const, int> >
+        > int_map2;
+
     boost::unordered_map<
         test::minimal::assignable,
         test::minimal::copy_constructible,
@@ -50,12 +68,18 @@
         test::minimal::allocator<value_type> > map;
 
     container_test(int_map, std::pair<int const, int>(0, 0));
+    container_test(int_map2, std::pair<int const, int>(0, 0));
     container_test(map, value);
 
     std::cout<<"Test unordered_multimap.\n";
 
     boost::unordered_multimap<int, int> int_multimap;
 
+    boost::unordered_multimap<int, int,
+        boost::hash<int>, std::equal_to<int>,
+        test::minimal::cxx11_allocator<std::pair<int const, int> >
+        > int_multimap2;
+
     boost::unordered_multimap<
         test::minimal::assignable,
         test::minimal::copy_constructible,
@@ -64,35 +88,49 @@
         test::minimal::allocator<value_type> > multimap;
 
     container_test(int_multimap, std::pair<int const, int>(0, 0));
+    container_test(int_multimap2, std::pair<int const, int>(0, 0));
     container_test(multimap, value);
 }
 
 UNORDERED_AUTO_TEST(equality_tests) {
-    typedef std::pair<test::minimal::assignable const,
+    typedef std::pair<
+            test::minimal::copy_constructible_equality_comparable const,
             test::minimal::copy_constructible> value_type;
 
     boost::unordered_map<int, int> int_map;
 
+    boost::unordered_map<int, int,
+        boost::hash<int>, std::equal_to<int>,
+        test::minimal::cxx11_allocator<std::pair<int const, int> >
+        > int_map2;
+
     boost::unordered_map<
-        test::minimal::assignable,
         test::minimal::copy_constructible_equality_comparable,
-        test::minimal::hash<test::minimal::assignable>,
-        test::minimal::equal_to<test::minimal::assignable>,
+        test::minimal::copy_constructible_equality_comparable,
+        test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
+        test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
         test::minimal::allocator<value_type> > map;
 
     equality_test(int_map);
+    equality_test(int_map2);
     equality_test(map);
 
     boost::unordered_multimap<int, int> int_multimap;
 
+    boost::unordered_multimap<int, int,
+        boost::hash<int>, std::equal_to<int>,
+        test::minimal::cxx11_allocator<std::pair<int const, int> >
+        > int_multimap2;
+
     boost::unordered_multimap<
-        test::minimal::assignable,
         test::minimal::copy_constructible_equality_comparable,
-        test::minimal::hash<test::minimal::assignable>,
-        test::minimal::equal_to<test::minimal::assignable>,
+        test::minimal::copy_constructible_equality_comparable,
+        test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
+        test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
         test::minimal::allocator<value_type> > multimap;
 
     equality_test(int_multimap);
+    equality_test(int_multimap2);
     equality_test(multimap);
 }
 
@@ -106,30 +144,47 @@
 
     boost::unordered_map<int, int> map;
 
+    boost::unordered_map<int, int,
+        boost::hash<int>, std::equal_to<int>,
+        test::minimal::cxx11_allocator<std::pair<int const, int> >
+        > map2;
+
     unordered_unique_test(map, map_value);
     unordered_map_test(map, value, value);
-    unordered_test(map, value, map_value, hash, equal_to);
+    unordered_copyable_test(map, value, map_value, hash, equal_to);
     unordered_map_functions(map, value, value);
 
+    unordered_unique_test(map2, map_value);
+    unordered_map_test(map2, value, value);
+    unordered_copyable_test(map2, value, map_value, hash, equal_to);
+    unordered_map_functions(map2, value, value);
+
     std::cout<<"Test unordered_multimap.\n";
 
     boost::unordered_multimap<int, int> multimap;
 
+    boost::unordered_multimap<int, int,
+        boost::hash<int>, std::equal_to<int>,
+        test::minimal::cxx11_allocator<std::pair<int const, int> >
+        > multimap2;
+
     unordered_equivalent_test(multimap, map_value);
     unordered_map_test(multimap, value, value);
-    unordered_test(multimap, value, map_value, hash, equal_to);
+    unordered_copyable_test(multimap, value, map_value, hash, equal_to);
+
+    unordered_equivalent_test(multimap2, map_value);
+    unordered_map_test(multimap2, value, value);
+    unordered_copyable_test(multimap2, value, map_value, hash, equal_to);
 }
 
 UNORDERED_AUTO_TEST(test2)
 {
-    test::minimal::assignable assignable
-        = test::minimal::assignable::create();
-    test::minimal::copy_constructible copy_constructible
-        = test::minimal::copy_constructible::create();
-    test::minimal::hash<test::minimal::assignable> hash
-        = test::minimal::hash<test::minimal::assignable>::create();
-    test::minimal::equal_to<test::minimal::assignable> equal_to
-        = test::minimal::equal_to<test::minimal::assignable>::create();
+    test::minimal::constructor_param x;
+
+    test::minimal::assignable assignable(x);
+    test::minimal::copy_constructible copy_constructible(x);
+    test::minimal::hash<test::minimal::assignable> hash(x);
+    test::minimal::equal_to<test::minimal::assignable> equal_to(x);
 
     typedef std::pair<test::minimal::assignable const,
             test::minimal::copy_constructible> map_value_type;
@@ -146,8 +201,7 @@
 
     unordered_unique_test(map, map_value);
     unordered_map_test(map, assignable, copy_constructible);
-    unordered_test(map, assignable, map_value, hash, equal_to);
-
+    unordered_copyable_test(map, assignable, map_value, hash, equal_to);
 
     boost::unordered_map<
         test::minimal::assignable,
@@ -171,7 +225,7 @@
 
     unordered_equivalent_test(multimap, map_value);
     unordered_map_test(multimap, assignable, copy_constructible);
-    unordered_test(multimap, assignable, map_value, hash, equal_to);
+    unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
 }
 
 RUN_TESTS()
Modified: branches/release/libs/unordered/test/unordered/compile_set.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/compile_set.cpp	(original)
+++ branches/release/libs/unordered/test/unordered/compile_set.cpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -16,7 +16,18 @@
 #include "./compile_tests.hpp"
 
 // Explicit instantiation to catch compile-time errors
-
+/*
+template class boost::unordered_set<
+    int,
+    boost::hash<int>,
+    std::equal_to<int>,
+    test::minimal::allocator<int> >;
+template class boost::unordered_multiset<
+    int,
+    boost::hash<int>,
+    std::equal_to<int>,
+    test::minimal::allocator<int> >;
+*/
 template class boost::unordered_set<
     test::minimal::assignable,
     test::minimal::hash<test::minimal::assignable>,
@@ -30,10 +41,19 @@
 
 UNORDERED_AUTO_TEST(test0)
 {
-    test::minimal::assignable assignable = test::minimal::assignable::create();
+    test::minimal::constructor_param x;
+
+    test::minimal::assignable assignable(x);
 
     std::cout<<"Test unordered_set.\n";
+
     boost::unordered_set<int> int_set;
+
+    boost::unordered_set<int,
+        boost::hash<int>, std::equal_to<int>,
+        test::minimal::cxx11_allocator<int>
+        > int_set2;
+
     boost::unordered_set<
         test::minimal::assignable,
         test::minimal::hash<test::minimal::assignable>,
@@ -41,10 +61,18 @@
         test::minimal::allocator<test::minimal::assignable> > set;
 
     container_test(int_set, 0);
+    container_test(int_set2, 0);
     container_test(set, assignable);
 
     std::cout<<"Test unordered_multiset.\n";
+
     boost::unordered_multiset<int> int_multiset;
+
+    boost::unordered_multiset<int,
+        boost::hash<int>, std::equal_to<int>,
+        test::minimal::cxx11_allocator<int>
+        > int_multiset2;
+
     boost::unordered_multiset<
         test::minimal::assignable,
         test::minimal::hash<test::minimal::assignable>,
@@ -52,32 +80,45 @@
         test::minimal::allocator<test::minimal::assignable> > multiset;
 
     container_test(int_multiset, 0);
+    container_test(int_multiset2, 0);
     container_test(multiset, assignable);
 }
 
 UNORDERED_AUTO_TEST(equality_tests) {
-    typedef test::minimal::assignable value_type;
+    typedef test::minimal::copy_constructible_equality_comparable value_type;
 
     boost::unordered_set<int> int_set;
 
+    boost::unordered_set<int,
+        boost::hash<int>, std::equal_to<int>,
+        test::minimal::cxx11_allocator<int>
+        > int_set2;
+
     boost::unordered_set<
-        test::minimal::assignable,
-        test::minimal::hash<test::minimal::assignable>,
-        test::minimal::equal_to<test::minimal::assignable>,
+        test::minimal::copy_constructible_equality_comparable,
+        test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
+        test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
         test::minimal::allocator<value_type> > set;
 
     equality_test(int_set);
+    equality_test(int_set2);
     equality_test(set);
 
     boost::unordered_multiset<int> int_multiset;
 
+    boost::unordered_multiset<int,
+        boost::hash<int>, std::equal_to<int>,
+        test::minimal::cxx11_allocator<int>
+        > int_multiset2;
+
     boost::unordered_multiset<
-        test::minimal::assignable,
-        test::minimal::hash<test::minimal::assignable>,
-        test::minimal::equal_to<test::minimal::assignable>,
+        test::minimal::copy_constructible_equality_comparable,
+        test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
+        test::minimal::equal_to<test::minimal::copy_constructible_equality_comparable>,
         test::minimal::allocator<value_type> > multiset;
 
     equality_test(int_multiset);
+    equality_test(int_multiset2);
     equality_test(multiset);
 }
 
@@ -91,29 +132,45 @@
 
     boost::unordered_set<int> set;
     
+    boost::unordered_set<int,
+        boost::hash<int>, std::equal_to<int>,
+        test::minimal::cxx11_allocator<int>
+        > set2;
+
     unordered_unique_test(set, value);
     unordered_set_test(set, value);
-    unordered_test(set, value, value, hash, equal_to);
+    unordered_copyable_test(set, value, value, hash, equal_to);
+
+    unordered_unique_test(set2, value);
+    unordered_set_test(set2, value);
+    unordered_copyable_test(set2, value, value, hash, equal_to);
 
     std::cout<<"Test unordered_multiset.\n";
 
     boost::unordered_multiset<int> multiset;
     
+    boost::unordered_multiset<int,
+        boost::hash<int>, std::equal_to<int>,
+        test::minimal::cxx11_allocator<int>
+        > multiset2;
+
     unordered_equivalent_test(multiset, value);
     unordered_set_test(multiset, value);
-    unordered_test(multiset, value, value, hash, equal_to);
+    unordered_copyable_test(multiset, value, value, hash, equal_to);
+
+    unordered_equivalent_test(multiset2, value);
+    unordered_set_test(multiset2, value);
+    unordered_copyable_test(multiset2, value, value, hash, equal_to);
 }
 
 UNORDERED_AUTO_TEST(test2)
 {
-    test::minimal::assignable assignable
-        = test::minimal::assignable::create();
-    test::minimal::copy_constructible copy_constructible
-        = test::minimal::copy_constructible::create();
-    test::minimal::hash<test::minimal::assignable> hash
-        = test::minimal::hash<test::minimal::assignable>::create();
-    test::minimal::equal_to<test::minimal::assignable> equal_to
-        = test::minimal::equal_to<test::minimal::assignable>::create();
+    test::minimal::constructor_param x;
+ 
+    test::minimal::assignable assignable(x);
+    test::minimal::copy_constructible copy_constructible(x);
+    test::minimal::hash<test::minimal::assignable> hash(x);
+    test::minimal::equal_to<test::minimal::assignable> equal_to(x);
 
     std::cout<<"Test unordered_set.\n";
 
@@ -125,7 +182,7 @@
 
     unordered_unique_test(set, assignable);
     unordered_set_test(set, assignable);
-    unordered_test(set, assignable, assignable, hash, equal_to);
+    unordered_copyable_test(set, assignable, assignable, hash, equal_to);
 
     std::cout<<"Test unordered_multiset.\n";
 
@@ -137,7 +194,100 @@
 
     unordered_equivalent_test(multiset, assignable);
     unordered_set_test(multiset, assignable);
-    unordered_test(multiset, assignable, assignable, hash, equal_to);
+    unordered_copyable_test(multiset, assignable, assignable, hash, equal_to);
+}
+
+UNORDERED_AUTO_TEST(movable1_tests)
+{
+    test::minimal::constructor_param x;
+
+    test::minimal::movable1 movable1(x);
+    test::minimal::hash<test::minimal::movable1> hash(x);
+    test::minimal::equal_to<test::minimal::movable1> equal_to(x);
+
+    std::cout<<"Test unordered_set.\n";
+
+    boost::unordered_set<
+        test::minimal::movable1,
+        test::minimal::hash<test::minimal::movable1>,
+        test::minimal::equal_to<test::minimal::movable1>,
+        test::minimal::allocator<test::minimal::movable1> > set;
+
+    //unordered_unique_test(set, movable1);
+    unordered_set_test(set, movable1);
+    unordered_movable_test(set, movable1, movable1, hash, equal_to);
+
+    std::cout<<"Test unordered_multiset.\n";
+
+    boost::unordered_multiset<
+        test::minimal::movable1,
+        test::minimal::hash<test::minimal::movable1>,
+        test::minimal::equal_to<test::minimal::movable1>,
+        test::minimal::allocator<test::minimal::movable1> > multiset;
+
+    //unordered_equivalent_test(multiset, movable1);
+    unordered_set_test(multiset, movable1);
+    unordered_movable_test(multiset, movable1, movable1, hash, equal_to);
+}
+
+UNORDERED_AUTO_TEST(movable2_tests)
+{
+    test::minimal::constructor_param x;
+
+    test::minimal::movable2 movable2(x);
+    test::minimal::hash<test::minimal::movable2> hash(x);
+    test::minimal::equal_to<test::minimal::movable2> equal_to(x);
+
+    std::cout<<"Test unordered_set.\n";
+
+    boost::unordered_set<
+        test::minimal::movable2,
+        test::minimal::hash<test::minimal::movable2>,
+        test::minimal::equal_to<test::minimal::movable2>,
+        test::minimal::allocator<test::minimal::movable2> > set;
+
+    //unordered_unique_test(set, movable2);
+    unordered_set_test(set, movable2);
+    unordered_movable_test(set, movable2, movable2, hash, equal_to);
+
+    std::cout<<"Test unordered_multiset.\n";
+
+    boost::unordered_multiset<
+        test::minimal::movable2,
+        test::minimal::hash<test::minimal::movable2>,
+        test::minimal::equal_to<test::minimal::movable2>,
+        test::minimal::allocator<test::minimal::movable2> > multiset;
+
+    //unordered_equivalent_test(multiset, movable2);
+    unordered_set_test(multiset, movable2);
+    unordered_movable_test(multiset, movable2, movable2, hash, equal_to);
+}
+
+UNORDERED_AUTO_TEST(destructible_tests)
+{
+    test::minimal::constructor_param x;
+
+    test::minimal::destructible destructible(x);
+    test::minimal::hash<test::minimal::destructible> hash(x);
+    test::minimal::equal_to<test::minimal::destructible> equal_to(x);
+
+    std::cout<<"Test unordered_set.\n";
+
+    boost::unordered_set<
+        test::minimal::destructible,
+        test::minimal::hash<test::minimal::destructible>,
+        test::minimal::equal_to<test::minimal::destructible> > set;
+
+    unordered_destructible_test(set);
+
+    std::cout<<"Test unordered_multiset.\n";
+
+    boost::unordered_multiset<
+        test::minimal::destructible,
+        test::minimal::hash<test::minimal::destructible>,
+        test::minimal::equal_to<test::minimal::destructible> > multiset;
+
+    unordered_destructible_test(multiset);
 }
 
 RUN_TESTS()
Modified: branches/release/libs/unordered/test/unordered/compile_tests.hpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/compile_tests.hpp	(original)
+++ branches/release/libs/unordered/test/unordered/compile_tests.hpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -28,6 +28,7 @@
 
 template <class T> void sink(T const&) {}
 template <class T> T rvalue(T const& v) { return v; }
+template <class T> T rvalue_default() { return T(); }
 
 template <class X, class T>
 void container_test(X& r, T const&)
@@ -109,15 +110,50 @@
     BOOST_TEST(X().size() == 0);
 
     X a,b;
+    X a_const;
 
     sink(X(a));
     X u2(a);
     X u3 = a;
 
+    a.swap(b);
+    boost::swap(a, b);
+    test::check_return_type<X>::equals_ref(r = a);
+
+    // Allocator
+
+    typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
+    test::check_return_type<allocator_type>::equals(a_const.get_allocator());
+    
+    // Avoid unused variable warnings:
+
+    sink(u);
+    sink(u2);
+    sink(u3);
+}
+
+template <class X>
+void unordered_destructible_test(X&)
+{
+    typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
+    typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
+    typedef BOOST_DEDUCED_TYPENAME X::size_type size_type;
+
+    X x1;
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES)
+    X x2(rvalue_default<X>());
+    X x3 = rvalue_default<X>();
+    // This can only be done if propagate_on_container_move_assignment::value
+    // is true.
+    // x2 = rvalue_default<X>();
+#endif
+
     X* ptr = new X();
     X& a1 = *ptr;
     (&a1)->~X();
 
+    X a,b;
     X const a_const;
     test::check_return_type<iterator>::equals(a.begin());
     test::check_return_type<const_iterator>::equals(a_const.begin());
@@ -129,7 +165,8 @@
     test::check_return_type<const_iterator>::equals(a_const.cend());
 
     a.swap(b);
-    test::check_return_type<X>::equals_ref(r = a);
+    boost::swap(a, b);
+ 
     test::check_return_type<size_type>::equals(a.size());
     test::check_return_type<size_type>::equals(a.max_size());
     test::check_return_type<bool>::convertible(a.empty());
@@ -138,12 +175,6 @@
 
     typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
     test::check_return_type<allocator_type>::equals(a_const.get_allocator());
-    
-    // Avoid unused variable warnings:
-
-    sink(u);
-    sink(u2);
-    sink(u3);
 }
 
 template <class X, class Key>
@@ -160,6 +191,7 @@
 {
     typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
     typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
+
     BOOST_MPL_ASSERT((
         boost::is_same<value_type, std::pair<key_type const, T> >));
 
@@ -180,6 +212,8 @@
 
     test::check_return_type<bool>::equals(a == b);
     test::check_return_type<bool>::equals(a != b);
+    test::check_return_type<bool>::equals(boost::operator==(a, b));
+    test::check_return_type<bool>::equals(boost::operator!=(a, b));
 }
 
 template <class X, class T>
@@ -211,9 +245,11 @@
     test::check_return_type<mapped_type const>::equals_ref(b.at(k));
 }
 
-template <class X, class Key, class T, class Hash, class Pred>
-void unordered_test(X&, Key& k, T& t, Hash& hf, Pred& eq)
+template <class X, class Key, class Hash, class Pred>
+void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
 {
+    unordered_destructible_test(x);
+
     typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
     typedef BOOST_DEDUCED_TYPENAME X::hasher hasher;
     typedef BOOST_DEDUCED_TYPENAME X::key_equal key_equal;
@@ -277,8 +313,8 @@
         const_local_iterator_reference;
 
     BOOST_MPL_ASSERT((boost::is_same<Key, key_type>));
-    boost::function_requires<boost::CopyConstructibleConcept<key_type> >();
-    boost::function_requires<boost::AssignableConcept<key_type> >();
+    //boost::function_requires<boost::CopyConstructibleConcept<key_type> >();
+    //boost::function_requires<boost::AssignableConcept<key_type> >();
 
     BOOST_MPL_ASSERT((boost::is_same<Hash, hasher>));
     test::check_return_type<std::size_t>::equals(hf(k));
@@ -316,45 +352,18 @@
     X();
     X a4;
 
-    BOOST_DEDUCED_TYPENAME X::value_type* i = 0;
-    BOOST_DEDUCED_TYPENAME X::value_type* j = 0;
-
-    X(i, j, 10, hf, eq);
-    X a5(i, j, 10, hf, eq);
-    X(i, j, 10, hf);
-    X a6(i, j, 10, hf);
-    X(i, j, 10);
-    X a7(i, j, 10);
-    X(i, j);
-    X a8(i, j);
-
-    X const b;
-    sink(X(b));
-    X a9(b);
-    a = b;
-
-    test::check_return_type<hasher>::equals(b.hash_function());
-    test::check_return_type<key_equal>::equals(b.key_eq());
-
-    const_iterator q = a.cbegin();
-    test::check_return_type<iterator>::equals(a.insert(q, t));
-    test::check_return_type<iterator>::equals(a.emplace_hint(q, t));
-
-    a.insert(i, j);
     test::check_return_type<size_type>::equals(a.erase(k));
 
-    BOOST_TEST(a.empty());
-    if(a.empty()) {
-        a.insert(t);
-        q = a.cbegin();
-        test::check_return_type<iterator>::equals(a.erase(q));
-    }
-
     const_iterator q1 = a.cbegin(), q2 = a.cend();
     test::check_return_type<iterator>::equals(a.erase(q1, q2));
 
     a.clear();
 
+    X const b;
+
+    test::check_return_type<hasher>::equals(b.hash_function());
+    test::check_return_type<key_equal>::equals(b.key_eq());
+
     test::check_return_type<iterator>::equals(a.find(k));
     test::check_return_type<const_iterator>::equals(b.find(k));
     test::check_return_type<size_type>::equals(b.count(k));
@@ -388,9 +397,117 @@
     sink(a2);
     sink(a3);
     sink(a4);
+}
+
+template <class X, class Key, class T, class Hash, class Pred>
+void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
+{
+    unordered_test(x, k, hf, eq);
+
+    typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
+    typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
+
+    X a;
+
+    BOOST_DEDUCED_TYPENAME X::value_type* i = 0;
+    BOOST_DEDUCED_TYPENAME X::value_type* j = 0;
+
+    X(i, j, 10, hf, eq);
+    X a5(i, j, 10, hf, eq);
+    X(i, j, 10, hf);
+    X a6(i, j, 10, hf);
+    X(i, j, 10);
+    X a7(i, j, 10);
+    X(i, j);
+    X a8(i, j);
+
+    X const b;
+    sink(X(b));
+    X a9(b);
+    a = b;
+
+    const_iterator q = a.cbegin();
+
+    test::check_return_type<iterator>::equals(a.insert(q, t));
+    test::check_return_type<iterator>::equals(a.emplace_hint(q, t));
+
+    a.insert(i, j);
+
+    X a10;
+    a10.insert(t);
+    q = a10.cbegin();
+    test::check_return_type<iterator>::equals(a10.erase(q));
+
+    // Avoid unused variable warnings:
+
+    sink(a);
     sink(a5);
     sink(a6);
     sink(a7);
     sink(a8);
     sink(a9);
 }
+
+template <class X, class Key, class T, class Hash, class Pred>
+void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
+{
+    unordered_test(x, k, hf, eq);
+
+    typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
+    typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES)
+    X x1(rvalue_default<X>());
+    X x2(boost::move(x1));
+    x1 = rvalue_default<X>();
+    x2 = boost::move(x1);
+#endif
+
+    test::minimal::constructor_param* i = 0; 
+    test::minimal::constructor_param* j = 0;
+
+    X(i, j, 10, hf, eq);
+    X a5(i, j, 10, hf, eq);
+    X(i, j, 10, hf);
+    X a6(i, j, 10, hf);
+    X(i, j, 10);
+    X a7(i, j, 10);
+    X(i, j);
+    X a8(i, j);
+
+    X a;
+
+    const_iterator q = a.cbegin();
+
+    test::minimal::constructor_param v;
+    a.emplace(v);
+    test::check_return_type<iterator>::equals(a.emplace_hint(q, v));
+
+    T v1(v);
+    a.emplace(boost::move(v1));
+    T v2(v);
+    a.insert(boost::move(v2));
+    T v3(v);
+    test::check_return_type<iterator>::equals(
+            a.emplace_hint(q, boost::move(v3)));
+    T v4(v);
+    test::check_return_type<iterator>::equals(
+            a.insert(q, boost::move(v4)));
+
+    a.insert(i, j);
+
+    X a10;
+    T v5(v);
+    a10.insert(boost::move(v5));
+    q = a10.cbegin();
+    test::check_return_type<iterator>::equals(a10.erase(q));
+
+    // Avoid unused variable warnings:
+
+    sink(a);
+    sink(a5);
+    sink(a6);
+    sink(a7);
+    sink(a8);
+    sink(a10);
+}
Modified: branches/release/libs/unordered/test/unordered/constructor_tests.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/constructor_tests.cpp	(original)
+++ branches/release/libs/unordered/test/unordered/constructor_tests.cpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -31,6 +31,8 @@
 
     std::cerr<<"Construct 1\n";
     {
+        test::check_instances check_;
+
         T x(0, hf, eq);
         BOOST_TEST(x.empty());
         BOOST_TEST(test::equivalent(x.hash_function(), hf));
@@ -41,6 +43,8 @@
 
     std::cerr<<"Construct 2\n";
     {
+        test::check_instances check_;
+
         T x(100, hf);
         BOOST_TEST(x.empty());
         BOOST_TEST(x.bucket_count() >= 100);
@@ -52,6 +56,8 @@
 
     std::cerr<<"Construct 3\n";
     {
+        test::check_instances check_;
+
         T x(2000);
         BOOST_TEST(x.empty());
         BOOST_TEST(x.bucket_count() >= 2000);
@@ -63,6 +69,8 @@
 
     std::cerr<<"Construct 4\n";
     {
+        test::check_instances check_;
+
         T x;
         BOOST_TEST(x.empty());
         BOOST_TEST(test::equivalent(x.hash_function(), hf));
@@ -73,6 +81,8 @@
 
     std::cerr<<"Construct 5\n";
     {
+        test::check_instances check_;
+
         test::random_values<T> v(1000, generator);
         T x(v.begin(), v.end(), 10000, hf, eq);
         BOOST_TEST(x.bucket_count() >= 10000);
@@ -85,6 +95,8 @@
 
     std::cerr<<"Construct 6\n";
     {
+        test::check_instances check_;
+
         test::random_values<T> v(10, generator);
         T x(v.begin(), v.end(), 10000, hf);
         BOOST_TEST(x.bucket_count() >= 10000);
@@ -97,6 +109,8 @@
 
     std::cerr<<"Construct 7\n";
     {
+        test::check_instances check_;
+
         test::random_values<T> v(100, generator);
         T x(v.begin(), v.end(), 100);
         BOOST_TEST(x.bucket_count() >= 100);
@@ -109,6 +123,8 @@
 
     std::cerr<<"Construct 8\n";
     {
+        test::check_instances check_;
+
         test::random_values<T> v(1, generator);
         T x(v.begin(), v.end());
         BOOST_TEST(test::equivalent(x.hash_function(), hf));
@@ -120,6 +136,8 @@
 
     std::cerr<<"Construct 9\n";
     {
+        test::check_instances check_;
+
         T x(0, hf, eq, al);
         BOOST_TEST(x.empty());
         BOOST_TEST(test::equivalent(x.hash_function(), hf));
@@ -130,6 +148,8 @@
 
     std::cerr<<"Construct 10\n";
     {
+        test::check_instances check_;
+
         test::random_values<T> v(1000, generator);
         T x(v.begin(), v.end(), 10000, hf, eq, al);
         BOOST_TEST(x.bucket_count() >= 10000);
@@ -142,6 +162,8 @@
 
     std::cerr<<"Construct 11\n";
     {
+        test::check_instances check_;
+
         T x(al);
         BOOST_TEST(x.empty());
         BOOST_TEST(test::equivalent(x.hash_function(), hf));
@@ -167,6 +189,7 @@
 
     std::cerr<<"Construct 1\n";
     {
+        test::check_instances check_;
         T x(10000, hf1, eq1);
         BOOST_TEST(x.bucket_count() >= 10000);
         BOOST_TEST(test::equivalent(x.hash_function(), hf1));
@@ -177,6 +200,7 @@
 
     std::cerr<<"Construct 2\n";
     {
+        test::check_instances check_;
         T x(100, hf1);
         BOOST_TEST(x.empty());
         BOOST_TEST(x.bucket_count() >= 100);
@@ -188,6 +212,7 @@
 
     std::cerr<<"Construct 3\n";
     {
+        test::check_instances check_;
         test::random_values<T> v(100, generator);
         T x(v.begin(), v.end(), 0, hf1, eq1);
         BOOST_TEST(test::equivalent(x.hash_function(), hf1));
@@ -199,6 +224,7 @@
 
     std::cerr<<"Construct 4\n";
     {
+        test::check_instances check_;
         test::random_values<T> v(5, generator);
         T x(v.begin(), v.end(), 1000, hf1);
         BOOST_TEST(x.bucket_count() >= 1000);
@@ -212,6 +238,7 @@
 
     std::cerr<<"Construct 5\n";
     {
+        test::check_instances check_;
         test::random_values<T> v(100, generator);
         T x(v.begin(), v.end(), 0, hf, eq, al1);
         T y(x.begin(), x.end(), 0, hf1, eq1, al2);
@@ -223,6 +250,7 @@
 
     std::cerr<<"Construct 6\n";
     {
+        test::check_instances check_;
         test::random_values<T> v(100, generator);
         T x(v.begin(), v.end(), 0, hf1, eq1);
         T y(x.begin(), x.end(), 0, hf, eq);
@@ -234,6 +262,7 @@
 
     std::cerr<<"Construct 7\n";
     {
+        test::check_instances check_;
         test::random_values<T> v(100, generator);
         T x(v.begin(), v.end(), 0, hf1, eq1);
         T y(x.begin(), x.end(), 0, hf2, eq2);
@@ -245,6 +274,7 @@
 
     std::cerr<<"Construct 8 - from input iterator\n";
     {
+        test::check_instances check_;
         test::random_values<T> v(100, generator);
         BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
             v_begin = v.begin(), v_end = v.end();
@@ -262,6 +292,7 @@
     
     std::cerr<<"Construct 8.5 - from copy iterator\n";
     {
+        test::check_instances check_;
         test::random_values<T> v(100, generator);
         T x(test::copy_iterator(v.begin()),
             test::copy_iterator(v.end()), 0, hf1, eq1);
@@ -275,6 +306,8 @@
     
     std::cerr<<"Construct 9\n";
     {
+        test::check_instances check_;
+
         test::random_values<T> v(100, generator);
         T x(50);
         BOOST_TEST(x.bucket_count() >= 50);
@@ -291,6 +324,8 @@
     
     std::cerr<<"Initializer list construct 1\n";
     {
+        test::check_instances check_;
+
         T x(list);
         BOOST_TEST(x.empty());
         BOOST_TEST(test::equivalent(x.hash_function(), hf));
@@ -300,6 +335,8 @@
 
     std::cerr<<"Initializer list construct 2\n";
     {
+        test::check_instances check_;
+
         T x(list, 1000);
         BOOST_TEST(x.empty());
         BOOST_TEST(x.bucket_count() >= 1000);
@@ -310,6 +347,8 @@
 
     std::cerr<<"Initializer list construct 3\n";
     {
+        test::check_instances check_;
+
         T x(list, 10, hf1);
         BOOST_TEST(x.empty());
         BOOST_TEST(x.bucket_count() >= 10);
@@ -320,6 +359,8 @@
 
     std::cerr<<"Initializer list construct 4\n";
     {
+        test::check_instances check_;
+
         T x(list, 10, hf1, eq1);
         BOOST_TEST(x.empty());
         BOOST_TEST(x.bucket_count() >= 10);
@@ -330,6 +371,8 @@
 
     std::cerr<<"Initializer list construct 5\n";
     {
+        test::check_instances check_;
+
         T x(list, 10, hf1, eq1, al1);
         BOOST_TEST(x.empty());
         BOOST_TEST(x.bucket_count() >= 10);
Modified: branches/release/libs/unordered/test/unordered/copy_tests.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/copy_tests.cpp	(original)
+++ branches/release/libs/unordered/test/unordered/copy_tests.cpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -9,6 +9,7 @@
 #include <boost/unordered_map.hpp>
 #include "../helpers/test.hpp"
 #include "../objects/test.hpp"
+#include "../objects/cxx11_allocator.hpp"
 #include "../helpers/random_values.hpp"
 #include "../helpers/tracker.hpp"
 #include "../helpers/equivalent.hpp"
@@ -23,11 +24,15 @@
 void copy_construct_tests1(T*,
     test::random_generator const& generator = test::default_generator)
 {
+    typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
+
     BOOST_DEDUCED_TYPENAME T::hasher hf;
     BOOST_DEDUCED_TYPENAME T::key_equal eq;
-    BOOST_DEDUCED_TYPENAME T::allocator_type al;
+    BOOST_DEDUCED_TYPENAME T::allocator_type al;    
 
     {
+        test::check_instances check_;
+
         T x;
         T y(x);
         BOOST_TEST(y.empty());
@@ -35,20 +40,28 @@
         BOOST_TEST(test::equivalent(y.key_eq(), eq));
         BOOST_TEST(test::equivalent(y.get_allocator(), al));
         BOOST_TEST(x.max_load_factor() == y.max_load_factor());
+        BOOST_TEST(test::selected_count(y.get_allocator()) ==
+            (allocator_type::is_select_on_copy));
         test::check_equivalent_keys(y);
     }
 
     {
+        test::check_instances check_;
+
         test::random_values<T> v(1000, generator);
 
         T x(v.begin(), v.end());
         T y(x);
         test::unordered_equivalence_tester<T> equivalent(x);
         BOOST_TEST(equivalent(y));
+        BOOST_TEST(test::selected_count(y.get_allocator()) ==
+            (allocator_type::is_select_on_copy));
         test::check_equivalent_keys(y);
     }
 
     {
+        test::check_instances check_;
+
         // In this test I drop the original containers max load factor, so it
         // is much lower than the load factor. The hash table is not allowed
         // to rehash, but the destination container should probably allocate
@@ -61,6 +74,8 @@
         BOOST_TEST(equivalent(y));
         // This isn't guaranteed:
         BOOST_TEST(y.load_factor() < y.max_load_factor());
+        BOOST_TEST(test::selected_count(y.get_allocator()) ==
+            (allocator_type::is_select_on_copy));
         test::check_equivalent_keys(y);
     }
 }
@@ -75,8 +90,12 @@
     BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
     BOOST_DEDUCED_TYPENAME T::allocator_type al(1);
     BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
+    
+    typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
 
     {
+        test::check_instances check_;
+
         T x(10000, hf, eq, al);
         T y(x);
         BOOST_TEST(y.empty());
@@ -84,10 +103,14 @@
         BOOST_TEST(test::equivalent(y.key_eq(), eq));
         BOOST_TEST(test::equivalent(y.get_allocator(), al));
         BOOST_TEST(x.max_load_factor() == y.max_load_factor());
+        BOOST_TEST(test::selected_count(y.get_allocator()) ==
+            (allocator_type::is_select_on_copy));
         test::check_equivalent_keys(y);
     }
 
     {
+        test::check_instances check_;
+
         T x(1000, hf, eq, al);
         T y(x, al2);
         BOOST_TEST(y.empty());
@@ -95,10 +118,13 @@
         BOOST_TEST(test::equivalent(y.key_eq(), eq));
         BOOST_TEST(test::equivalent(y.get_allocator(), al2));
         BOOST_TEST(x.max_load_factor() == y.max_load_factor());
+        BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
         test::check_equivalent_keys(y);
     }
 
     {
+        test::check_instances check_;
+
         test::random_values<T> v(1000, generator);
 
         T x(v.begin(), v.end(), 0, hf, eq, al);
@@ -106,10 +132,14 @@
         test::unordered_equivalence_tester<T> equivalent(x);
         BOOST_TEST(equivalent(y));
         test::check_equivalent_keys(y);
+        BOOST_TEST(test::selected_count(y.get_allocator()) ==
+            (allocator_type::is_select_on_copy));
         BOOST_TEST(test::equivalent(y.get_allocator(), al));
     }
 
     {
+        test::check_instances check_;
+
         test::random_values<T> v(500, generator);
 
         T x(v.begin(), v.end(), 0, hf, eq, al);
@@ -117,6 +147,7 @@
         test::unordered_equivalence_tester<T> equivalent(x);
         BOOST_TEST(equivalent(y));
         test::check_equivalent_keys(y);
+        BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
         BOOST_TEST(test::equivalent(y.get_allocator(), al2));
     }
 }
@@ -134,15 +165,55 @@
     test::hash, test::equal_to,
     test::allocator<test::object> >* test_multimap;
 
+boost::unordered_set<test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::select_copy> >*
+    test_set_select_copy;
+boost::unordered_multiset<test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::select_copy> >*
+    test_multiset_select_copy;
+boost::unordered_map<test::object, test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::select_copy> >*
+    test_map_select_copy;
+boost::unordered_multimap<test::object, test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::select_copy> >*
+    test_multimap_select_copy;
+
+boost::unordered_set<test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::no_select_copy> >*
+    test_set_no_select_copy;
+boost::unordered_multiset<test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::no_select_copy> >*
+    test_multiset_no_select_copy;
+boost::unordered_map<test::object, test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::no_select_copy> >*
+    test_map_no_select_copy;
+boost::unordered_multimap<test::object, test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::no_select_copy> >*
+    test_multimap_no_select_copy;
+
 using test::default_generator;
 using test::generate_collisions;
 
-UNORDERED_TEST(copy_construct_tests1,
-    ((test_set)(test_multiset)(test_map)(test_multimap))
+UNORDERED_TEST(copy_construct_tests1, (
+        (test_set)(test_multiset)(test_map)(test_multimap)
+        (test_set_select_copy)(test_multiset_select_copy)(test_map_select_copy)(test_multimap_select_copy)
+        (test_set_no_select_copy)(test_multiset_no_select_copy)(test_map_no_select_copy)(test_multimap_no_select_copy)
+    )
 )
 
-UNORDERED_TEST(copy_construct_tests2,
-    ((test_set)(test_multiset)(test_map)(test_multimap))
+UNORDERED_TEST(copy_construct_tests2, (
+        (test_set)(test_multiset)(test_map)(test_multimap)
+        (test_set_select_copy)(test_multiset_select_copy)(test_map_select_copy)(test_multimap_select_copy)
+        (test_set_no_select_copy)(test_multiset_no_select_copy)(test_map_no_select_copy)(test_multimap_no_select_copy)
+    )
     ((default_generator)(generate_collisions))
 )
 
Modified: branches/release/libs/unordered/test/unordered/equality_tests.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/equality_tests.cpp	(original)
+++ branches/release/libs/unordered/test/unordered/equality_tests.cpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -136,15 +136,17 @@
         UNORDERED_EQUALITY_MULTIMAP_TEST(
             ((1)(1))((1)(1)), !=, ((1)(1))((1)(2)))
         UNORDERED_EQUALITY_MULTIMAP_TEST(
-            ((1)(2))((1)(1)), !=, ((1)(1))((1)(2)))
+            ((1)(2))((1)(1)), ==, ((1)(1))((1)(2)))
+        UNORDERED_EQUALITY_MULTIMAP_TEST(
+            ((1)(2))((1)(1)), !=, ((1)(1))((1)(3)))
     }
 
     UNORDERED_AUTO_TEST(equality_predicate_test)
     {
         UNORDERED_EQUALITY_SET_TEST(
-            (1), ==, (1001))
+            (1), !=, (1001))
         UNORDERED_EQUALITY_MAP_TEST(
-            ((1)(2))((1001)(1)), ==, ((1001)(2))((1)(1)))
+            ((1)(2))((1001)(1)), !=, ((1001)(2))((1)(1)))
     }
 
     // Test that equality still works when the two containers have
Modified: branches/release/libs/unordered/test/unordered/erase_tests.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/erase_tests.cpp	(original)
+++ branches/release/libs/unordered/test/unordered/erase_tests.cpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -28,6 +28,8 @@
 {
     std::cerr<<"Erase by key.\n";
     {
+        test::check_instances check_;
+
         test::random_values<Container> v(1000, generator);
         Container x(v.begin(), v.end());
         for(BOOST_DEDUCED_TYPENAME test::random_values<Container>::iterator
@@ -44,6 +46,8 @@
 
     std::cerr<<"erase(begin()).\n";
     {
+        test::check_instances check_;
+
         test::random_values<Container> v(1000, generator);
         Container x(v.begin(), v.end());
         std::size_t size = x.size();
@@ -64,6 +68,8 @@
 
     std::cerr<<"erase(random position).\n";
     {
+        test::check_instances check_;
+
         test::random_values<Container> v(1000, generator);
         Container x(v.begin(), v.end());
         std::size_t size = x.size();
@@ -96,6 +102,8 @@
 
     std::cerr<<"erase(ranges).\n";
     {
+        test::check_instances check_;
+
         test::random_values<Container> v(500, generator);
         Container x(v.begin(), v.end());
 
@@ -118,6 +126,8 @@
 
     std::cerr<<"quick_erase(begin()).\n";
     {
+        test::check_instances check_;
+
         test::random_values<Container> v(1000, generator);
         Container x(v.begin(), v.end());
         std::size_t size = x.size();
@@ -136,6 +146,8 @@
 
     std::cerr<<"quick_erase(random position).\n";
     {
+        test::check_instances check_;
+
         test::random_values<Container> v(1000, generator);
         Container x(v.begin(), v.end());
         std::size_t size = x.size();
@@ -169,6 +181,8 @@
 
     std::cerr<<"clear().\n";
     {
+        test::check_instances check_;
+
         test::random_values<Container> v(500, generator);
         Container x(v.begin(), v.end());
         x.clear();
Modified: branches/release/libs/unordered/test/unordered/find_tests.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/find_tests.cpp	(original)
+++ branches/release/libs/unordered/test/unordered/find_tests.cpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -24,6 +24,8 @@
     typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
 
     {
+        test::check_instances check_;
+
         test::random_values<X> v(500, generator);
         X x(v.begin(), v.end());
         X const& x_const = x;
@@ -69,6 +71,8 @@
     }
 
     {
+        test::check_instances check_;
+
         X x;
 
         test::random_values<X> v2(5, generator);
Modified: branches/release/libs/unordered/test/unordered/insert_tests.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/insert_tests.cpp	(original)
+++ branches/release/libs/unordered/test/unordered/insert_tests.cpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -26,6 +26,8 @@
 void unique_insert_tests1(X*,
     test::random_generator generator = test::default_generator)
 {
+    test::check_instances check_;
+
     typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
     typedef test::ordered<X> ordered;
 
@@ -65,6 +67,9 @@
 {
     std::cerr<<"insert(value) tests for containers with equivalent keys.\n";
 
+    test::check_instances check_;
+
+
     X x;
     test::ordered<X> tracker = test::create_ordered(x);
 
@@ -102,6 +107,8 @@
     std::cerr<<"insert(begin(), value) tests.\n";
 
     {
+        test::check_instances check_;
+
         X x;
         tracker_type tracker = test::create_ordered(x);
 
@@ -128,6 +135,8 @@
     std::cerr<<"insert(end(), value) tests.\n";
 
     {
+        test::check_instances check_;
+
         X x;
         X const& x_const = x;
         tracker_type tracker = test::create_ordered(x);
@@ -155,6 +164,8 @@
     std::cerr<<"insert(pos, value) tests.\n";
 
     {
+        test::check_instances check_;
+
         X x;
         const_iterator pos = x.begin();
         tracker_type tracker = test::create_ordered(x);
@@ -182,6 +193,8 @@
     std::cerr<<"insert single item range tests.\n";
 
     {
+        test::check_instances check_;
+
         X x;
         tracker_type tracker = test::create_ordered(x);
 
@@ -207,6 +220,8 @@
     std::cerr<<"insert range tests.\n";
 
     {
+        test::check_instances check_;
+
         X x;
 
         test::random_values<X> v(1000, generator);
@@ -219,6 +234,8 @@
     std::cerr<<"insert input iterator range tests.\n";
 
     {
+        test::check_instances check_;
+
         X x;
 
         test::random_values<X> v(1000, generator);
@@ -233,6 +250,8 @@
     std::cerr<<"insert copy iterator range tests.\n";
 
     {
+        test::check_instances check_;
+
         X x;
 
         test::random_values<X> v(1000, generator);
@@ -351,6 +370,8 @@
 {
     std::cerr<<"map_insert_range_test1\n";
 
+    test::check_instances check_;
+
     typedef test::list<
         std::pair<
             BOOST_DEDUCED_TYPENAME X::key_type,
@@ -371,6 +392,8 @@
 {
     std::cerr<<"map_insert_range_test2\n";
 
+    test::check_instances check_;
+
     typedef test::list<
         std::pair<BOOST_DEDUCED_TYPENAME X::key_type const, test::implicitly_convertible>
     > list;
Modified: branches/release/libs/unordered/test/unordered/move_tests.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/move_tests.cpp	(original)
+++ branches/release/libs/unordered/test/unordered/move_tests.cpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -9,11 +9,16 @@
 #include <boost/unordered_map.hpp>
 #include "../helpers/test.hpp"
 #include "../objects/test.hpp"
+#include "../objects/cxx11_allocator.hpp"
 #include "../helpers/random_values.hpp"
 #include "../helpers/tracker.hpp"
 #include "../helpers/equivalent.hpp"
 #include "../helpers/invariants.hpp"
 
+#if defined(BOOST_MSVC)
+#pragma warning(disable:4127) // conditional expression is constant
+#endif
+
 namespace move_tests
 {
     test::seed_t seed(98624);
@@ -54,6 +59,8 @@
         BOOST_DEDUCED_TYPENAME T::allocator_type al;
 
         {
+            test::check_instances check_;
+
             T y(empty(ptr));
             BOOST_TEST(y.empty());
             BOOST_TEST(test::equivalent(y.hash_function(), hf));
@@ -64,6 +71,8 @@
         }
 
         {
+            test::check_instances check_;
+
             test::random_values<T> v(1000, generator);
             test::object_count count;
             T y(create(v, count));
@@ -80,6 +89,8 @@
         test::random_generator const& generator = test::default_generator)
     {
         {
+            test::check_instances check_;
+
             test::random_values<T> v(500, generator);
             test::object_count count;
             T y;
@@ -104,6 +115,8 @@
         test::object_count count;
 
         {
+            test::check_instances check_;
+
             test::random_values<T> v(500, generator);
             T y(create(v, count, hf, eq, al, 0.5));
 #if defined(BOOST_HAS_NRVO)
@@ -118,6 +131,8 @@
         }
 
         {
+            test::check_instances check_;
+
             // TODO: To do this correctly requires the fancy new allocator
             // stuff.
             test::random_values<T> v(500, generator);
@@ -130,17 +145,24 @@
             BOOST_TEST(y.max_load_factor() == 2.0); // Not necessarily required.
             test::check_equivalent_keys(y);
         }
-/*
+
         {
+            test::check_instances check_;
+
             test::random_values<T> v(25, generator);
             T y(create(v, count, hf, eq, al, 1.0), al);
 #if !defined(BOOST_NO_RVALUE_REFERENCES)
             BOOST_TEST(count == test::global_object_count);
-#else
+#elif defined(BOOST_HAS_NRVO)
             BOOST_TEST(
                 test::global_object_count.constructions - count.constructions <=
                 (test::is_map<T>::value ? 50 : 25));
             BOOST_TEST(count.instances == test::global_object_count.instances);
+#else
+            BOOST_TEST(
+                test::global_object_count.constructions - count.constructions <=
+                (test::is_map<T>::value ? 100 : 50));
+            BOOST_TEST(count.instances == test::global_object_count.instances);
 #endif
             test::check_container(y, v);
             BOOST_TEST(test::equivalent(y.hash_function(), hf));
@@ -149,7 +171,57 @@
             BOOST_TEST(y.max_load_factor() == 1.0); // Not necessarily required.
             test::check_equivalent_keys(y);
         }
-*/    }
+    }
+
+    template <class T>
+    void move_assign_tests2(T*,
+        test::random_generator const& generator = test::default_generator)
+    {
+        BOOST_DEDUCED_TYPENAME T::hasher hf(1);
+        BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
+        BOOST_DEDUCED_TYPENAME T::allocator_type al1(1);
+        BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
+        typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
+
+        {
+            test::random_values<T> v(500, generator);
+            test::random_values<T> v2(0, generator);
+            T y(v.begin(), v.end(), 0, hf, eq, al1);
+            test::object_count count;
+            y = create(v2, count, hf, eq, al2, 2.0);
+            BOOST_TEST(y.empty());
+            test::check_container(y, v2);
+            test::check_equivalent_keys(y);
+            BOOST_TEST(y.max_load_factor() == 2.0);
+            if (allocator_type::is_propagate_on_move) {
+                BOOST_TEST(test::equivalent(y.get_allocator(), al2));
+            }
+            else {
+                BOOST_TEST(test::equivalent(y.get_allocator(), al1));
+            }
+        }
+
+        {
+            test::random_values<T> v(500, generator);
+            test::object_count count;
+            T y(0, hf, eq, al1);
+            y = create(v, count, hf, eq, al2, 0.5);
+#if defined(BOOST_HAS_NRVO)
+            if (allocator_type::is_propagate_on_move) {
+                BOOST_TEST(count == test::global_object_count);
+            }
+#endif
+            test::check_container(y, v);
+            test::check_equivalent_keys(y);
+            BOOST_TEST(y.max_load_factor() == 0.5);
+            if (allocator_type::is_propagate_on_move) {
+                BOOST_TEST(test::equivalent(y.get_allocator(), al2));
+            }
+            else {
+                BOOST_TEST(test::equivalent(y.get_allocator(), al1));
+            }
+        }
+    }
 
     boost::unordered_set<test::object,
         test::hash, test::equal_to,
@@ -164,19 +236,68 @@
         test::hash, test::equal_to,
         test::allocator<test::object> >* test_multimap;
 
+boost::unordered_set<test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::propagate_move> >*
+    test_set_prop_move;
+boost::unordered_multiset<test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::propagate_move> >*
+    test_multiset_prop_move;
+boost::unordered_map<test::object, test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::propagate_move> >*
+    test_map_prop_move;
+boost::unordered_multimap<test::object, test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::propagate_move> >*
+    test_multimap_prop_move;
+
+boost::unordered_set<test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::no_propagate_move> >*
+    test_set_no_prop_move;
+boost::unordered_multiset<test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::no_propagate_move> >*
+    test_multiset_no_prop_move;
+boost::unordered_map<test::object, test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::no_propagate_move> >*
+    test_map_no_prop_move;
+boost::unordered_multimap<test::object, test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::no_propagate_move> >*
+    test_multimap_no_prop_move;
+
     using test::default_generator;
     using test::generate_collisions;
 
-    UNORDERED_TEST(move_construct_tests1,
-        ((test_set)(test_multiset)(test_map)(test_multimap))
+    UNORDERED_TEST(move_construct_tests1, (
+            (test_set)(test_multiset)(test_map)(test_multimap)
+            (test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
+            (test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
+        )
     )
-    UNORDERED_TEST(move_assign_tests1,
-        ((test_set)(test_multiset)(test_map)(test_multimap))
+    UNORDERED_TEST(move_assign_tests1, (
+            (test_set)(test_multiset)(test_map)(test_multimap)
+            (test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
+            (test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
+        )
     )
-    UNORDERED_TEST(move_construct_tests2,
-        ((test_set)(test_multiset)(test_map)(test_multimap))
+    UNORDERED_TEST(move_construct_tests2, (
+            (test_set)(test_multiset)(test_map)(test_multimap)
+            (test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
+            (test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
+        )
         ((default_generator)(generate_collisions))
     )
+    UNORDERED_TEST(move_assign_tests2, (
+            (test_set)(test_multiset)(test_map)(test_multimap)
+            (test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)
+            (test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(test_multimap_no_prop_move)
+        )
+    )
 }
 
 RUN_TESTS()
Modified: branches/release/libs/unordered/test/unordered/swap_tests.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/swap_tests.cpp	(original)
+++ branches/release/libs/unordered/test/unordered/swap_tests.cpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -12,10 +12,15 @@
 #include <boost/unordered_map.hpp>
 #include "../helpers/test.hpp"
 #include "../objects/test.hpp"
+#include "../objects/cxx11_allocator.hpp"
 #include "../helpers/random_values.hpp"
 #include "../helpers/tracker.hpp"
 #include "../helpers/invariants.hpp"
 
+#if defined(BOOST_MSVC)
+#pragma warning(disable:4127) // conditional expression is constant
+#endif
+
 namespace swap_tests
 {
 
@@ -37,16 +42,22 @@
 void swap_tests1(X*, test::random_generator generator = test::default_generator)
 {
     {
+        test::check_instances check_;
+
         X x;
         swap_test_impl(x, x);
     }
 
     {
+        test::check_instances check_;
+
         X x,y;
         swap_test_impl(x, y);
     }
 
     {
+        test::check_instances check_;
+
         test::random_values<X> v(1000, generator);
         X x, y(v.begin(), v.end());
         swap_test_impl(x, y);
@@ -54,6 +65,8 @@
     }
 
     {
+        test::check_instances check_;
+
         test::random_values<X> vx(1000, generator), vy(1000, generator);
         X x(vx.begin(), vx.end()), y(vy.begin(), vy.end());
         swap_test_impl(x, y);
@@ -72,12 +85,16 @@
     typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
 
     {
+        test::check_instances check_;
+
         X x(0, hasher(1), key_equal(1));
         X y(0, hasher(2), key_equal(2));
         swap_test_impl(x, y);
     }
 
     {
+        test::check_instances check_;
+
         test::random_values<X> v(1000, generator);
         X x(v.begin(), v.end(), 0, hasher(1), key_equal(1));
         X y(0, hasher(2), key_equal(2));
@@ -85,6 +102,8 @@
     }
 
     {
+        test::check_instances check_;
+
         test::random_values<X> vx(100, generator), vy(50, generator);
         X x(vx.begin(), vx.end(), 0, hasher(1), key_equal(1));
         X y(vy.begin(), vy.end(), 0, hasher(2), key_equal(2));
@@ -92,57 +111,113 @@
         swap_test_impl(x, y);
     }
 
-#if BOOST_UNORDERED_SWAP_METHOD == 1
-    {
-        test::random_values<X> vx(100, generator), vy(50, generator);
-        X x(vx.begin(), vx.end(), 0, hasher(), key_equal(), allocator_type(1));
-        X y(vy.begin(), vy.end(), 0, hasher(), key_equal(), allocator_type(2));
-        try {
-            swap_test_impl(x, y);
-            BOOST_ERROR("Using swap method 1, "
-                "swapping with unequal allocators didn't throw.");
-        } catch (std::runtime_error) {}
-    }
-#else
     {
+        test::force_equal_allocator force_(
+            !allocator_type::is_propagate_on_swap);
+        test::check_instances check_;
+
         test::random_values<X> vx(50, generator), vy(100, generator);
         X x(vx.begin(), vx.end(), 0, hasher(), key_equal(), allocator_type(1));
         X y(vy.begin(), vy.end(), 0, hasher(), key_equal(), allocator_type(2));
-        swap_test_impl(x, y);
+
+        if (allocator_type::is_propagate_on_swap ||
+            x.get_allocator() == y.get_allocator())
+        {
+            swap_test_impl(x, y);
+        }
     }
 
     {
+        test::force_equal_allocator force_(
+            !allocator_type::is_propagate_on_swap);
+        test::check_instances check_;
+
         test::random_values<X> vx(100, generator), vy(100, generator);
         X x(vx.begin(), vx.end(), 0, hasher(1), key_equal(1),
             allocator_type(1));
         X y(vy.begin(), vy.end(), 0, hasher(2), key_equal(2),
             allocator_type(2));
-        swap_test_impl(x, y);
-        swap_test_impl(x, y);
+
+        if (allocator_type::is_propagate_on_swap ||
+            x.get_allocator() == y.get_allocator())
+        {
+            swap_test_impl(x, y);
+            swap_test_impl(x, y);
+        }
     }
-#endif
 }
 
 boost::unordered_set<test::object,
-    test::hash, test::equal_to,
-    test::allocator<test::object> >* test_set;
+        test::hash, test::equal_to,
+        test::allocator<test::object> >* test_set;
 boost::unordered_multiset<test::object,
-    test::hash, test::equal_to,
-    test::allocator<test::object> >* test_multiset;
+        test::hash, test::equal_to,
+        test::allocator<test::object> >* test_multiset;
 boost::unordered_map<test::object, test::object,
-    test::hash, test::equal_to,
-    test::allocator<test::object> >* test_map;
+        test::hash, test::equal_to,
+        test::allocator<test::object> >* test_map;
 boost::unordered_multimap<test::object, test::object,
-    test::hash, test::equal_to,
-    test::allocator<test::object> >* test_multimap;
+        test::hash, test::equal_to,
+        test::allocator<test::object> >* test_multimap;
+
+boost::unordered_set<test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::propagate_swap> >*
+    test_set_prop_swap;
+boost::unordered_multiset<test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::propagate_swap> >*
+    test_multiset_prop_swap;
+boost::unordered_map<test::object, test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::propagate_swap> >*
+    test_map_prop_swap;
+boost::unordered_multimap<test::object, test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::propagate_swap> >*
+    test_multimap_prop_swap;
+
+boost::unordered_set<test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::no_propagate_swap> >*
+    test_set_no_prop_swap;
+boost::unordered_multiset<test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::no_propagate_swap> >*
+    test_multiset_no_prop_swap;
+boost::unordered_map<test::object, test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::no_propagate_swap> >*
+    test_map_no_prop_swap;
+boost::unordered_multimap<test::object, test::object,
+        test::hash, test::equal_to,
+        test::cxx11_allocator<test::object, test::no_propagate_swap> >*
+    test_multimap_no_prop_swap;
+
+template <typename T>
+bool is_propagate(T*)
+{
+    return T::allocator_type::is_propagate_on_swap;
+}
+
+UNORDERED_AUTO_TEST(check_traits)
+{
+    BOOST_TEST(!is_propagate(test_set));
+    BOOST_TEST(is_propagate(test_set_prop_swap));
+    BOOST_TEST(!is_propagate(test_set_no_prop_swap));
+}
 
-UNORDERED_TEST(swap_tests1,
-    ((test_set)(test_multiset)(test_map)(test_multimap))
-)
-
-UNORDERED_TEST(swap_tests2,
-    ((test_set)(test_multiset)(test_map)(test_multimap))
-)
+UNORDERED_TEST(swap_tests1, (
+    (test_set)(test_multiset)(test_map)(test_multimap)
+    (test_set_prop_swap)(test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)
+    (test_set_no_prop_swap)(test_multiset_no_prop_swap)(test_map_no_prop_swap)(test_multimap_no_prop_swap)
+))
+
+UNORDERED_TEST(swap_tests2, (
+    (test_set)(test_multiset)(test_map)(test_multimap)
+    (test_set_prop_swap)(test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)
+    (test_set_no_prop_swap)(test_multiset_no_prop_swap)(test_map_no_prop_swap)(test_multimap_no_prop_swap)
+))
 
 }
 RUN_TESTS()
Modified: branches/release/libs/unordered/test/unordered/unnecessary_copy_tests.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/unnecessary_copy_tests.cpp	(original)
+++ branches/release/libs/unordered/test/unordered/unnecessary_copy_tests.cpp	2011-08-21 15:19:12 EDT (Sun, 21 Aug 2011)
@@ -13,6 +13,9 @@
 {
     struct count_copies
     {
+    private:
+        BOOST_COPYABLE_AND_MOVABLE(count_copies)
+    public:
         static int copies;
         static int moves;
         count_copies() : tag_(0) { ++copies; }
@@ -31,14 +34,25 @@
             : tag_(x.tag_) { ++copies; }
 
         count_copies(count_copies const& x) : tag_(x.tag_) { ++copies; }
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
-        count_copies(count_copies&& x) : tag_(x.tag_) {
+        count_copies(BOOST_RV_REF(count_copies) x) : tag_(x.tag_) {
             x.tag_ = -1; ++moves;
         }
-#endif
-       int tag_;
-    private:
-       count_copies& operator=(count_copies const&);
+
+        count_copies& operator=(BOOST_COPY_ASSIGN_REF(count_copies) p) // Copy assignment
+        {
+            tag_ = p.tag_;
+            ++copies;
+            return *this;
+        }
+
+        count_copies& operator=(BOOST_RV_REF(count_copies) p) //Move assignment
+        {
+            tag_ = p.tag_;
+            ++moves;
+            return *this;
+        }
+
+        int tag_;
     };
 
     bool operator==(count_copies const& x, count_copies const& y) {
@@ -68,31 +82,37 @@
 }
 
 #define COPY_COUNT(n)                                                       \
-    if(count_copies::copies != n) {                                         \
+    if(::unnecessary_copy_tests::count_copies::copies != n) {               \
         BOOST_ERROR("Wrong number of copies.");                             \
         std::cerr                                                           \
-            << "Number of copies: " << count_copies::copies                 \
+            << "Number of copies: "                                         \
+            << ::unnecessary_copy_tests::count_copies::copies               \
             << " expecting: " << n << std::endl;                            \
     }
 #define MOVE_COUNT(n)                                                       \
-    if(count_copies::moves != n) {                                          \
+    if(::unnecessary_copy_tests::count_copies::moves != n) {                \
         BOOST_ERROR("Wrong number of moves.");                              \
         std::cerr                                                           \
-            << "Number of moves: " << count_copies::moves                   \
+            << "Number of moves: "                                          \
+            << ::unnecessary_copy_tests::count_copies::moves                \
             << " expecting: " <<n << std::endl;                             \
     }
 #define COPY_COUNT_RANGE(a, b)                                              \
-    if(count_copies::copies < a || count_copies::copies > b) {              \
+    if(::unnecessary_copy_tests::count_copies::copies < a ||                \
+            ::unnecessary_copy_tests::count_copies::copies > b) {           \
         BOOST_ERROR("Wrong number of copies.");                             \
         std::cerr                                                           \
-            << "Number of copies: " << count_copies::copies                 \
+            << "Number of copies: "                                         \
+            << ::unnecessary_copy_tests::count_copies::copies               \
             << " expecting: [" << a << ", " << b << "]" << std::endl;       \
     }
 #define MOVE_COUNT_RANGE(a, b)                                              \
-    if(count_copies::moves < a || count_copies::moves > b) {                \
+    if(::unnecessary_copy_tests::count_copies::moves < a ||                 \
+            ::unnecessary_copy_tests::count_copies::moves > b) {            \
         BOOST_ERROR("Wrong number of moves.");                              \
         std::cerr                                                           \
-            << "Number of moves: " << count_copies::copies                  \
+            << "Number of moves: "                                          \
+            << ::unnecessary_copy_tests::count_copies::copies               \
             << " expecting: [" << a << ", " << b << "]" << std::endl;       \
     }
 
@@ -136,7 +156,7 @@
         reset();
         T x;
         x.emplace(source<BOOST_DEDUCED_TYPENAME T::value_type>());
-#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_RVALUE_REFERENCES)
         COPY_COUNT(1);
 #else
         COPY_COUNT(2);
@@ -148,7 +168,7 @@
     UNORDERED_TEST(unnecessary_copy_emplace_rvalue_test,
             ((set)(multiset)(map)(multimap)))
 
-#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
     template <class T>
     void unnecessary_copy_emplace_move_test(T*)
     {
@@ -162,11 +182,51 @@
 
     UNORDERED_TEST(unnecessary_copy_emplace_move_test,
             ((set)(multiset)(map)(multimap)))
+#endif
 
+    template <class T>
+    void unnecessary_copy_emplace_boost_move_set_test(T*)
+    {
+        reset();
+        T x;
+        BOOST_DEDUCED_TYPENAME T::value_type a;
+        COPY_COUNT(1); MOVE_COUNT(0);
+        x.emplace(boost::move(a));
+        COPY_COUNT(1); MOVE_COUNT(1);
+    }
+
+    UNORDERED_TEST(unnecessary_copy_emplace_boost_move_set_test,
+            ((set)(multiset)))
+
+    template <class T>
+    void unnecessary_copy_emplace_boost_move_map_test(T*)
+    {
+        reset();
+        T x;
+        BOOST_DEDUCED_TYPENAME T::value_type a;
+        COPY_COUNT(1); MOVE_COUNT(0);
+        x.emplace(boost::move(a));
+#if defined(BOOST_NO_RVALUE_REFERENCES)
+        COPY_COUNT(2); MOVE_COUNT(0);
+#else
+        COPY_COUNT(1); MOVE_COUNT(1);
 #endif
+    }
+
+    UNORDERED_TEST(unnecessary_copy_emplace_boost_move_map_test,
+            ((map)(multimap)))
 
     UNORDERED_AUTO_TEST(unnecessary_copy_emplace_set_test)
     {
+        // When calling 'source' the object is moved on some compilers, but not
+        // others. So count that here to adjust later.
+
+        reset();
+        source<count_copies>();
+        int source_cost = ::unnecessary_copy_tests::count_copies::moves;
+
+        //
+
         reset();
         boost::unordered_set<count_copies> x;
         count_copies a;
@@ -181,7 +241,12 @@
         // the existing element.
         reset();
         x.emplace();
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
         COPY_COUNT(1); MOVE_COUNT(0);
+#else
+        // source_cost doesn't make much sense here, but it seems to fit.
+        COPY_COUNT(1); MOVE_COUNT(source_cost);
+#endif
 
         //
         // 1 argument
@@ -197,9 +262,9 @@
         // copied.
         reset();
         x.emplace(source<count_copies>());
-        COPY_COUNT(1); MOVE_COUNT(0);
+        COPY_COUNT(1); MOVE_COUNT(source_cost);
 
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
         // No move should take place.
         reset();
         x.emplace(std::move(a));
@@ -233,6 +298,19 @@
 
     UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test)
     {
+        // When calling 'source' the object is moved on some compilers, but not
+        // others. So count that here to adjust later.
+
+        reset();
+        source<count_copies>();
+        int source_cost = ::unnecessary_copy_tests::count_copies::moves;
+
+        reset();
+        source<std::pair<count_copies, count_copies> >();
+        int source_pair_cost = ::unnecessary_copy_tests::count_copies::moves;
+
+        //
+
         reset();
         boost::unordered_map<count_copies, count_copies> x;
         // TODO: Run tests for pairs without const etc.
@@ -261,17 +339,17 @@
         // copied.
         reset();
         x.emplace(source<std::pair<count_copies, count_copies> >());
-        COPY_COUNT(2); MOVE_COUNT_RANGE(0,2);
+        COPY_COUNT(2); MOVE_COUNT(source_pair_cost);
 
-        // TODO: This doesn't work on older versions of gcc.
-        //count_copies part;
-        std::pair<count_copies const, count_copies> b;
-        //reset();
-        //std::pair<count_copies const&, count_copies const&> a_ref(part, part);
-        //x.emplace(a_ref);
-        //COPY_COUNT(0); MOVE_COUNT(0);
+#if !defined(__GNUC__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)
+        count_copies part;
+        reset();
+        std::pair<count_copies const&, count_copies const&> a_ref(part, part);
+        x.emplace(a_ref);
+        COPY_COUNT(2); MOVE_COUNT(0);
+#endif
 
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
         // No move should take place.
         // (since a is already in the container)
         reset();
@@ -279,23 +357,24 @@
         COPY_COUNT(0); MOVE_COUNT(0);
 #endif
 
-
         //
         // 2 arguments
         //
 
+        std::pair<count_copies const, count_copies> b;
+
         reset();
         x.emplace(b.first, b.second);
         COPY_COUNT(0); MOVE_COUNT(0);
 
         reset();
         x.emplace(source<count_copies>(), source<count_copies>());
-        COPY_COUNT(2); MOVE_COUNT(0);
+        COPY_COUNT(2); MOVE_COUNT(source_cost * 2);
 
         // source<count_copies> creates a single copy.
         reset();
         x.emplace(b.first, source<count_copies>());
-        COPY_COUNT(1); MOVE_COUNT(0);
+        COPY_COUNT(1); MOVE_COUNT(source_cost);
 
         reset();
         x.emplace(count_copies(b.first.tag_), count_copies(b.second.tag_));