$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r80350 - in branches/release: . boost boost/unordered boost/unordered/detail libs libs/unordered libs/unordered/test/exception libs/unordered/test/helpers libs/unordered/test/objects libs/unordered/test/unordered
From: dnljms_at_[hidden]
Date: 2012-09-01 11:50:38
Author: danieljames
Date: 2012-09-01 11:50:36 EDT (Sat, 01 Sep 2012)
New Revision: 80350
URL: http://svn.boost.org/trac/boost/changeset/80350
Log:
Unordered: Merge from trunk.
- Some changes to the internals, including reverting some of the
  recent changes to constructing values which turned out to be
  more bother than it was worth.
- On C++11 compilers, better use of `construct` and `destroy`.
- Better testing.
Properties modified: 
   branches/release/   (props changed)
   branches/release/boost/   (props changed)
   branches/release/boost/unordered/   (props changed)
   branches/release/libs/   (props changed)
   branches/release/libs/unordered/   (props changed)
Text files modified: 
   branches/release/boost/unordered/detail/allocate.hpp                      |   903 +++++++++++++++++++-------------------- 
   branches/release/boost/unordered/detail/buckets.hpp                       |   121 +++--                                   
   branches/release/boost/unordered/detail/equivalent.hpp                    |    49 --                                      
   branches/release/boost/unordered/detail/table.hpp                         |     5                                         
   branches/release/boost/unordered/detail/unique.hpp                        |    47 -                                       
   branches/release/libs/unordered/test/exception/assign_exception_tests.cpp |    30 +                                       
   branches/release/libs/unordered/test/exception/containers.hpp             |     4                                         
   branches/release/libs/unordered/test/exception/swap_exception_tests.cpp   |     5                                         
   branches/release/libs/unordered/test/helpers/invariants.hpp               |    25 +                                       
   branches/release/libs/unordered/test/objects/exception.hpp                |   180 +++++++                                 
   branches/release/libs/unordered/test/objects/minimal.hpp                  |    22                                         
   branches/release/libs/unordered/test/unordered/assign_tests.cpp           |    71 +++                                     
   branches/release/libs/unordered/test/unordered/compile_map.cpp            |    30                                         
   branches/release/libs/unordered/test/unordered/unnecessary_copy_tests.cpp |    23                                         
   14 files changed, 876 insertions(+), 639 deletions(-)
Modified: branches/release/boost/unordered/detail/allocate.hpp
==============================================================================
--- branches/release/boost/unordered/detail/allocate.hpp	(original)
+++ branches/release/boost/unordered/detail/allocate.hpp	2012-09-01 11:50:36 EDT (Sat, 01 Sep 2012)
@@ -167,347 +167,6 @@
 
 #endif
 
-    ////////////////////////////////////////////////////////////////////////////
-    // rvalue parameters when type can't be a BOOST_RV_REF(T) parameter
-    // e.g. for int
-
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
-#   define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T)
-#else
-    struct please_ignore_this_overload {
-        typedef please_ignore_this_overload type;
-    };
-
-    template <typename T>
-    struct rv_ref_impl {
-        typedef BOOST_RV_REF(T) type;
-    };
-
-    template <typename T>
-    struct rv_ref :
-        boost::detail::if_true<
-            boost::is_class<T>::value
-        >::BOOST_NESTED_TEMPLATE then <
-            boost::unordered::detail::rv_ref_impl<T>,
-            please_ignore_this_overload
-        >::type
-    {};
-
-#   define BOOST_UNORDERED_RV_REF(T) \
-        typename boost::unordered::detail::rv_ref<T>::type
-#endif
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Construct from tuple
-    //
-    // Used for piecewise construction.
-
-#if !defined(__SUNPRO_CC)
-
-#   define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_)              \
-    template<typename T>                                                    \
-    void construct_from_tuple(T* ptr, namespace_ tuple<>)                   \
-    {                                                                       \
-        new ((void*) ptr) T();                                              \
-    }                                                                       \
-                                                                            \
-    BOOST_PP_REPEAT_FROM_TO(1, n,                                           \
-        BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
-
-#   define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_)      \
-    template<typename T, BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>          \
-    void construct_from_tuple(T* ptr,                                       \
-            namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x)     \
-    {                                                                       \
-        new ((void*) ptr) T(                                                \
-            BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
-        );                                                                  \
-    }
-
-#   define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_)                  \
-    namespace_ get<n>(x)
-
-#else
-
-    template <int N> struct length {};
-
-#   define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_)              \
-    template<typename T>                                                    \
-    void construct_from_tuple_impl(                                         \
-            boost::unordered::detail::length<0>, T* ptr,                    \
-            namespace_ tuple<>)                                             \
-    {                                                                       \
-        new ((void*) ptr) T();                                              \
-    }                                                                       \
-                                                                            \
-    BOOST_PP_REPEAT_FROM_TO(1, n,                                           \
-        BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
-
-#   define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_)      \
-    template<typename T, BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>          \
-    void construct_from_tuple_impl(                                         \
-            boost::unordered::detail::length<n>, T* ptr,                    \
-            namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x)     \
-    {                                                                       \
-        new ((void*) ptr) T(                                                \
-            BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
-        );                                                                  \
-    }
-
-#   define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_)                  \
-    namespace_ get<n>(x)
-
-#endif
-
-BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
-
-#if !defined(__SUNPRO_CC) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
-   BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::)
-#endif
-
-#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
-#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL
-#undef BOOST_UNORDERED_GET_TUPLE_ARG
-
-#if defined(__SUNPRO_CC)
-
-    template <typename T, typename Tuple>
-    void construct_from_tuple(T* ptr, Tuple const& x)
-    {
-        construct_from_tuple_impl(
-            boost::unordered::detail::length<
-                boost::tuples::length<Tuple>::value>(),
-            ptr, x);
-    }
-
-#endif
-
-    ////////////////////////////////////////////////////////////////////////////
-    // SFINAE traits for construction.
-
-    // Decide which construction method to use for a three argument
-    // call. Note that this is difficult to do using overloads because
-    // the arguments are packed into 'emplace_args3'.
-    //
-    // The decision is made on the first argument.
-
-
-#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
-    template <typename A, typename B, typename A0>
-    struct emulation1 {
-        static choice1::type test(choice1, std::pair<A, B> const&);
-        static choice2::type test(choice2, A const&);
-        static choice3::type test(choice3, convert_from_anything const&);
-
-        enum { value =
-            sizeof(test(choose(), boost::unordered::detail::make<A0>())) ==
-                sizeof(choice2::type) };
-    };
-#endif
-
-    template <typename A, typename B, typename A0>
-    struct check3_base {
-        static choice1::type test(choice1,
-            boost::unordered::piecewise_construct_t);
-
-#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
-        static choice2::type test(choice2, A const&);
-#endif
-
-        static choice3::type test(choice3, ...);
-
-        enum { value =
-            sizeof(test(choose(), boost::unordered::detail::make<A0>())) };
-    };
-
-    template <typename A, typename B, typename A0>
-    struct piecewise3 {
-        enum { value = check3_base<A,B,A0>::value == sizeof(choice1::type) };
-    };
-
-#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
-    template <typename A, typename B, typename A0>
-    struct emulation3 {
-        enum { value = check3_base<A,B,A0>::value == sizeof(choice2::type) };
-    };
-
-#endif
-
-#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Construct from variadic parameters
-
-    template <typename T, typename... Args>
-    inline void construct_impl(T* address, BOOST_FWD_REF(Args)... args)
-    {
-        new((void*) address) T(boost::forward<Args>(args)...);
-    }
-
-    template <typename A, typename B, typename A0, typename A1, typename A2>
-    inline typename enable_if<piecewise3<A, B, A0>, void>::type
-        construct_impl(std::pair<A, B>* address,
-            BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
-    {
-        boost::unordered::detail::construct_from_tuple(
-            boost::addressof(address->first), boost::forward<A1>(a1));
-        boost::unordered::detail::construct_from_tuple(
-            boost::addressof(address->second), boost::forward<A2>(a2));
-    }
-
-#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
-
-    template <typename A, typename B, typename A0>
-    inline typename enable_if<emulation1<A, B, A0>, void>::type
-        construct_impl(std::pair<A, B>* address, BOOST_FWD_REF(A0) a0)
-    {
-        new((void*) boost::addressof(address->first)) A(boost::forward<A0>(a0));
-        new((void*) boost::addressof(address->second)) B();
-   }
-
-    template <typename A, typename B, typename A0, typename A1, typename A2>
-    inline typename enable_if<emulation3<A, B, A0>, void>::type
-        construct_impl(std::pair<A, B>* address,
-            BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
-    {
-        new((void*) boost::addressof(address->first)) A(boost::forward<A0>(a0));
-        new((void*) boost::addressof(address->second)) B(
-            boost::forward<A1>(a1),
-            boost::forward<A2>(a2));
-    }
-
-    template <typename A, typename B,
-            typename A0, typename A1, typename A2, typename A3,
-            typename... Args>
-    inline void construct_impl(std::pair<A, B>* address,
-            BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2,
-            BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(Args)... args)
-    {
-        new((void*) boost::addressof(address->first)) A(boost::forward<A0>(a0));
-
-        new((void*) boost::addressof(address->second)) B(
-            boost::forward<A1>(a1),
-            boost::forward<A2>(a2),
-            boost::forward<A3>(a3),
-            boost::forward<Args>(args)...);
-    }
-
-#endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
-
-#else // BOOST_NO_VARIADIC_TEMPLATES
-
-////////////////////////////////////////////////////////////////////////////////
-// Construct from emplace_args
-
-#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _)                    \
-    template <                                                              \
-        typename T,                                                         \
-        BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A)                   \
-    >                                                                       \
-    inline void construct_impl(T* address,                                  \
-        boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) <   \
-            BOOST_PP_ENUM_PARAMS_Z(z, num_params, A)                        \
-        > const& args)                                                      \
-    {                                                                       \
-        new((void*) address) T(                                             \
-            BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD,     \
-                args.a));                                                   \
-    }
-
-    template <typename T, typename A0>
-    inline void construct_impl(T* address, emplace_args1<A0> const& args)
-    {
-        new((void*) address) T(boost::forward<A0>(args.a0));
-    }
-
-    template <typename T, typename A0, typename A1>
-    inline void construct_impl(T* address, emplace_args2<A0, A1> const& args)
-    {
-        new((void*) address) T(
-            boost::forward<A0>(args.a0),
-            boost::forward<A1>(args.a1)
-        );
-    }
-
-    template <typename T, typename A0, typename A1, typename A2>
-    inline void construct_impl(T* address, emplace_args3<A0, A1, A2> const& args)
-    {
-        new((void*) address) T(
-            boost::forward<A0>(args.a0),
-            boost::forward<A1>(args.a1),
-            boost::forward<A2>(args.a2)
-        );
-    }
-
-    BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
-        BOOST_UNORDERED_CONSTRUCT_IMPL, _)
-
-#undef BOOST_UNORDERED_CONSTRUCT_IMPL
-
-    template <typename A, typename B, typename A0, typename A1, typename A2>
-    inline void construct_impl(std::pair<A, B>* address,
-            boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
-            typename enable_if<piecewise3<A, B, A0>, void*>::type = 0)
-    {
-        boost::unordered::detail::construct_from_tuple(
-            boost::addressof(address->first), args.a1);
-        boost::unordered::detail::construct_from_tuple(
-            boost::addressof(address->second), args.a2);
-    }
-
-#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
-
-    template <typename A, typename B, typename A0>
-    inline void construct_impl(std::pair<A, B>* address,
-            boost::unordered::detail::emplace_args1<A0> const& args,
-            typename enable_if<emulation1<A, B, A0>, void*>::type = 0)
-    {
-        new((void*) boost::addressof(address->first)) A(
-            boost::forward<A0>(args.a0));
-        new((void*) boost::addressof(address->second)) B();
-    }
-
-    template <typename A, typename B, typename A0, typename A1, typename A2>
-    inline void construct_impl(std::pair<A, B>* address,
-            boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
-            typename enable_if<emulation3<A, B, A0>, void*>::type = 0)
-    {
-        new((void*) boost::addressof(address->first)) A(
-            boost::forward<A0>(args.a0));
-        new((void*) boost::addressof(address->second)) B(
-            boost::forward<A1>(args.a1),
-            boost::forward<A2>(args.a2));
-    }
-
-#define BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(z, num_params, _)               \
-    template <typename A, typename B,                                       \
-        BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A)                   \
-    >                                                                       \
-    inline void construct_impl(std::pair<A, B>* address,                    \
-        boost::unordered::detail::BOOST_PP_CAT(emplace_args, num_params) <  \
-                BOOST_PP_ENUM_PARAMS_Z(z, num_params, A)                    \
-            > const& args)                                                  \
-    {                                                                       \
-        new((void*) boost::addressof(address->first)) A(                    \
-            boost::forward<A0>(args.a0));                                   \
-        new((void*) boost::addressof(address->second)) B(                   \
-            BOOST_PP_ENUM_##z(BOOST_PP_DEC(num_params),                     \
-                BOOST_UNORDERED_CALL_FORWARD2, args.a));                    \
-    }
-
-#define BOOST_UNORDERED_CALL_FORWARD2(z, i, a) \
-    BOOST_UNORDERED_CALL_FORWARD(z, BOOST_PP_INC(i), a)
-
-    BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(1, 2, _)
-    BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
-        BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL, _)
-
-#undef BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL
-#undef BOOST_UNORDERED_CALL_FORWARD2
-
-#endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
-#endif // BOOST_NO_VARIADIC_TEMPLATES
-
 }}}
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1013,166 +672,502 @@
             boost::unordered::detail::destroy(p);
         }
 
-#   endif
+#   endif
+
+        static size_type max_size(const Alloc& a)
+        {
+            return boost::unordered::detail::call_max_size<size_type>(a);
+        }
+
+        // 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_UNORDERED_DEFAULT_TYPE(
+            Alloc, propagate_on_container_copy_assignment, false_type)
+            propagate_on_container_copy_assignment;
+        typedef BOOST_UNORDERED_DEFAULT_TYPE(
+            Alloc,propagate_on_container_move_assignment, false_type)
+            propagate_on_container_move_assignment;
+        typedef BOOST_UNORDERED_DEFAULT_TYPE(
+            Alloc,propagate_on_container_swap,false_type)
+            propagate_on_container_swap;
+    };
+}}}
+
+#   undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
+#   undef BOOST_UNORDERED_DEFAULT_TYPE
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// std::allocator_traits
+
+#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
+
+#   include <memory>
+
+#   define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
+
+namespace boost { namespace unordered { namespace detail {
+
+    template <typename Alloc>
+    struct allocator_traits : std::allocator_traits<Alloc> {};
+
+    template <typename Alloc, typename T>
+    struct rebind_wrap
+    {
+        typedef typename std::allocator_traits<Alloc>::
+            template rebind_alloc<T> type;
+    };
+}}}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// boost::container::allocator_traits
+
+#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
+
+#   include <boost/container/allocator_traits.hpp>
+
+#   define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
+
+namespace boost { namespace unordered { namespace detail {
+
+    template <typename Alloc>
+    struct allocator_traits :
+        boost::container::allocator_traits<Alloc> {};
+
+    template <typename Alloc, typename T>
+    struct rebind_wrap :
+        boost::container::allocator_traits<Alloc>::
+            template portable_rebind_alloc<T>
+    {};
+
+}}}
+
+#else
+
+#error "Invalid BOOST_UNORDERED_USE_ALLOCATOR_TRAITS value."
+
+#endif
+
+
+namespace boost { namespace unordered { namespace detail {
+
+    ////////////////////////////////////////////////////////////////////////////
+    // call_construct
+
+#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+
+#   if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+
+    template <typename Alloc, typename T, typename... Args>
+    inline void call_construct(Alloc& alloc, T* address,
+        BOOST_FWD_REF(Args)... args)
+    {
+        boost::unordered::detail::allocator_traits<Alloc>::construct(alloc,
+            address, boost::forward<Args>(args)...);
+    }
+
+    template <typename Alloc, typename T>
+    inline void destroy_value_impl(Alloc& alloc, T* x) {
+        boost::unordered::detail::allocator_traits<Alloc>::destroy(alloc, x);
+    }
+
+
+#   else
+
+    template <typename Alloc, typename T, typename... Args>
+    inline void call_construct(Alloc&, T* address,
+        BOOST_FWD_REF(Args)... args)
+    {
+        new((void*) address) T(boost::forward<Args>(args)...);
+    }
+
+    template <typename Alloc, typename T>
+    inline void destroy_value_impl(Alloc&, T* x) {
+        boost::unordered::detail::destroy(x);
+    }
+
+
+#   endif
+
+#else
+
+    template <typename Alloc, typename T>
+    inline void destroy_value_impl(Alloc&, T* x) {
+        boost::unordered::detail::destroy(x);
+    }
+
+#endif
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Construct from tuple
+    //
+    // Used for piecewise construction.
+
+#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+
+#   define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_)              \
+    template<typename Alloc, typename T>                                    \
+    void construct_from_tuple(Alloc& alloc, T* ptr, namespace_ tuple<>)     \
+    {                                                                       \
+        boost::unordered::detail::call_construct(alloc, ptr);               \
+    }                                                                       \
+                                                                            \
+    BOOST_PP_REPEAT_FROM_TO(1, n,                                           \
+        BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
+
+#   define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_)      \
+    template<typename Alloc, typename T,                                    \
+        BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>                           \
+    void construct_from_tuple(Alloc& alloc, T* ptr,                         \
+            namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x)     \
+    {                                                                       \
+        boost::unordered::detail::call_construct(alloc, ptr,                \
+            BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
+        );                                                                  \
+    }
+
+#   define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_)                  \
+    namespace_ get<n>(x)
+
+#elif !defined(__SUNPRO_CC)
+
+#   define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_)              \
+    template<typename Alloc, typename T>                                    \
+    void construct_from_tuple(Alloc&, T* ptr, namespace_ tuple<>)           \
+    {                                                                       \
+        new ((void*) ptr) T();                                              \
+    }                                                                       \
+                                                                            \
+    BOOST_PP_REPEAT_FROM_TO(1, n,                                           \
+        BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
+
+#   define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_)      \
+    template<typename Alloc, typename T,                                    \
+        BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>                           \
+    void construct_from_tuple(Alloc&, T* ptr,                               \
+            namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x)     \
+    {                                                                       \
+        new ((void*) ptr) T(                                                \
+            BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
+        );                                                                  \
+    }
+
+#   define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_)                  \
+    namespace_ get<n>(x)
+
+#else
+
+    template <int N> struct length {};
+
+#   define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_)              \
+    template<typename Alloc, typename T>                                    \
+    void construct_from_tuple_impl(                                         \
+            boost::unordered::detail::length<0>, Alloc&, T* ptr,            \
+            namespace_ tuple<>)                                             \
+    {                                                                       \
+        new ((void*) ptr) T();                                              \
+    }                                                                       \
+                                                                            \
+    BOOST_PP_REPEAT_FROM_TO(1, n,                                           \
+        BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
+
+#   define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_)      \
+    template<typename Alloc, typename T,                                    \
+        BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>                           \
+    void construct_from_tuple_impl(                                         \
+            boost::unordered::detail::length<n>, Alloc&, T* ptr,            \
+            namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x)     \
+    {                                                                       \
+        new ((void*) ptr) T(                                                \
+            BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
+        );                                                                  \
+    }
+
+#   define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_)                  \
+    namespace_ get<n>(x)
 
-        static size_type max_size(const Alloc& a)
-        {
-            return boost::unordered::detail::call_max_size<size_type>(a);
-        }
+#endif
 
-        // Allocator propagation on construction
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
 
-        static Alloc select_on_container_copy_construction(Alloc const& rhs)
-        {
-            return boost::unordered::detail::
-                call_select_on_container_copy_construction(rhs);
-        }
+#if !defined(__SUNPRO_CC) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
+   BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::)
+#endif
 
-        // Allocator propagation on assignment and swap.
-        // Return true if lhs is modified.
-        typedef BOOST_UNORDERED_DEFAULT_TYPE(
-            Alloc, propagate_on_container_copy_assignment, false_type)
-            propagate_on_container_copy_assignment;
-        typedef BOOST_UNORDERED_DEFAULT_TYPE(
-            Alloc,propagate_on_container_move_assignment, false_type)
-            propagate_on_container_move_assignment;
-        typedef BOOST_UNORDERED_DEFAULT_TYPE(
-            Alloc,propagate_on_container_swap,false_type)
-            propagate_on_container_swap;
-    };
-}}}
+#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
+#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL
+#undef BOOST_UNORDERED_GET_TUPLE_ARG
 
-#   undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
-#   undef BOOST_UNORDERED_DEFAULT_TYPE
+#if defined(__SUNPRO_CC)
 
-////////////////////////////////////////////////////////////////////////////////
-//
-// std::allocator_traits
+    template <typename Alloc, typename T, typename Tuple>
+    void construct_from_tuple(Alloc& alloc, T* ptr, Tuple const& x)
+    {
+        construct_from_tuple_impl(
+            boost::unordered::detail::length<
+                boost::tuples::length<Tuple>::value>(),
+            alloc, ptr, x);
+    }
 
-#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
+#endif
 
-#   include <memory>
+    ////////////////////////////////////////////////////////////////////////////
+    // SFINAE traits for construction.
 
-#   define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
+    // Decide which construction method to use for a three argument
+    // call. Note that this is difficult to do using overloads because
+    // the arguments are packed into 'emplace_args3'.
+    //
+    // The decision is made on the first argument.
 
-namespace boost { namespace unordered { namespace detail {
 
-    template <typename Alloc>
-    struct allocator_traits : std::allocator_traits<Alloc> {};
+#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
+    template <typename A, typename B, typename A0>
+    struct emulation1 {
+        static choice1::type test(choice1, std::pair<A, B> const&);
+        static choice2::type test(choice2, A const&);
+        static choice3::type test(choice3, convert_from_anything const&);
 
-    template <typename Alloc, typename T>
-    struct rebind_wrap
-    {
-        typedef typename std::allocator_traits<Alloc>::
-            template rebind_alloc<T> type;
+        enum { value =
+            sizeof(test(choose(), boost::unordered::detail::make<A0>())) ==
+                sizeof(choice2::type) };
     };
-}}}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// boost::container::allocator_traits
-
-#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
+#endif
 
-#   include <boost/container/allocator_traits.hpp>
+    template <typename A, typename B, typename A0>
+    struct check3_base {
+        static choice1::type test(choice1,
+            boost::unordered::piecewise_construct_t);
 
-#   define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
+#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
+        static choice2::type test(choice2, A const&);
+#endif
 
-namespace boost { namespace unordered { namespace detail {
+        static choice3::type test(choice3, ...);
 
-    template <typename Alloc>
-    struct allocator_traits :
-        boost::container::allocator_traits<Alloc> {};
+        enum { value =
+            sizeof(test(choose(), boost::unordered::detail::make<A0>())) };
+    };
 
-    template <typename Alloc, typename T>
-    struct rebind_wrap :
-        boost::container::allocator_traits<Alloc>::
-            template portable_rebind_alloc<T>
-    {};
+    template <typename A, typename B, typename A0>
+    struct piecewise3 {
+        enum { value = check3_base<A,B,A0>::value == sizeof(choice1::type) };
+    };
 
-}}}
+#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
+    template <typename A, typename B, typename A0>
+    struct emulation3 {
+        enum { value = check3_base<A,B,A0>::value == sizeof(choice2::type) };
+    };
 
-#else
+#endif
 
-#error "Invalid BOOST_UNORDERED_USE_ALLOCATOR_TRAITS value."
+// TODO: Full construct?
+#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
 
-#endif
+    ////////////////////////////////////////////////////////////////////////////
+    // Construct from variadic parameters
 
-////////////////////////////////////////////////////////////////////////////////
-//
-// Some helper functions for allocating & constructing
+    template <typename Alloc, typename T, typename... Args>
+    inline void construct_value_impl(Alloc& alloc, T* address,
+        BOOST_FWD_REF(Args)... args)
+    {
+        boost::unordered::detail::call_construct(alloc,
+            address, boost::forward<Args>(args)...);
+    }
 
-namespace boost { namespace unordered { namespace detail {
+    template <typename Alloc, typename A, typename B,
+        typename A0, typename A1, typename A2>
+    inline typename enable_if<piecewise3<A, B, A0>, void>::type
+        construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
+            BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
+    {
+        boost::unordered::detail::construct_from_tuple(alloc,
+            boost::addressof(address->first), boost::forward<A1>(a1));
+        boost::unordered::detail::construct_from_tuple(alloc,
+            boost::addressof(address->second), boost::forward<A2>(a2));
+    }
 
-    ////////////////////////////////////////////////////////////////////////////
-    //
-    // construct_node/destroy_node
-    //
-    // Construct a node using the best available method.
+#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
 
-#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+    template <typename Alloc, typename A, typename B, typename A0>
+    inline typename enable_if<emulation1<A, B, A0>, void>::type
+        construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
+            BOOST_FWD_REF(A0) a0)
+    {
+        boost::unordered::detail::call_construct(alloc,
+            boost::addressof(address->first),boost::forward<A0>(a0));
+        boost::unordered::detail::call_construct(alloc,
+            boost::addressof(address->second));
+   }
 
-    template <typename Alloc, typename T, BOOST_UNORDERED_EMPLACE_TEMPLATE>
-    inline void construct_node(Alloc& a, T* p, BOOST_UNORDERED_EMPLACE_ARGS)
+    template <typename Alloc, typename A, typename B,
+        typename A0, typename A1, typename A2>
+    inline typename enable_if<emulation3<A, B, A0>, void>::type
+        construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
+            BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
     {
-        boost::unordered::detail::allocator_traits<Alloc>::construct(
-            a, p, BOOST_UNORDERED_EMPLACE_FORWARD);
+        boost::unordered::detail::call_construct(alloc,
+            boost::addressof(address->first),boost::forward<A0>(a0));
+        boost::unordered::detail::call_construct(alloc,
+            boost::addressof(address->second),
+            boost::forward<A1>(a1),
+            boost::forward<A2>(a2));
     }
 
-    template <typename Alloc, typename T>
-    inline void destroy_node(Alloc& a, T* p)
+    template <typename Alloc, typename A, typename B,
+            typename A0, typename A1, typename A2, typename A3,
+            typename... Args>
+    inline void construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
+            BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2,
+            BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(Args)... args)
     {
-        boost::unordered::detail::allocator_traits<Alloc>::destroy(a, p);
+        boost::unordered::detail::call_construct(alloc,
+            boost::addressof(address->first),boost::forward<A0>(a0));
+        boost::unordered::detail::call_construct(alloc,
+            boost::addressof(address->second),
+            boost::forward<A1>(a1),
+            boost::forward<A2>(a2),
+            boost::forward<A3>(a3),
+            boost::forward<Args>(args)...);
     }
 
-#else
+#endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
+#else // BOOST_NO_VARIADIC_TEMPLATES
+
+////////////////////////////////////////////////////////////////////////////////
+// Construct from emplace_args
+
+#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _)                    \
+    template <                                                              \
+        typename Alloc, typename T,                                         \
+        BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A)                   \
+    >                                                                       \
+    inline void construct_value_impl(Alloc&, T* address,                    \
+        boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) <   \
+            BOOST_PP_ENUM_PARAMS_Z(z, num_params, A)                        \
+        > const& args)                                                      \
+    {                                                                       \
+        new((void*) address) T(                                             \
+            BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD,     \
+                args.a));                                                   \
+    }
 
-    template <typename AllocTraits, typename T>
-    struct value_construct
+    template <typename Alloc, typename T, typename A0>
+    inline void construct_value_impl(Alloc&, T* address,
+            emplace_args1<A0> const& args)
     {
-        typedef BOOST_DEDUCED_TYPENAME AllocTraits::allocator_type allocator;
+        new((void*) address) T(boost::forward<A0>(args.a0));
+    }
 
-        allocator& alloc;
-        T* ptr;
+    template <typename Alloc, typename T, typename A0, typename A1>
+    inline void construct_value_impl(Alloc&, T* address,
+            emplace_args2<A0, A1> const& args)
+    {
+        new((void*) address) T(
+            boost::forward<A0>(args.a0),
+            boost::forward<A1>(args.a1)
+        );
+    }
 
-        value_construct(allocator& a, T* p) : alloc(a), ptr(p)
-        {
-            AllocTraits::construct(alloc, ptr, T());
-        }
+    template <typename Alloc, typename T, typename A0, typename A1, typename A2>
+    inline void construct_value_impl(Alloc&, T* address,
+            emplace_args3<A0, A1, A2> const& args)
+    {
+        new((void*) address) T(
+            boost::forward<A0>(args.a0),
+            boost::forward<A1>(args.a1),
+            boost::forward<A2>(args.a2)
+        );
+    }
 
-        void release()
-        {
-            ptr = 0;
-        }
+    BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
+        BOOST_UNORDERED_CONSTRUCT_IMPL, _)
 
-        ~value_construct()
-        {
-            if (ptr) AllocTraits::destroy(alloc, ptr);
-        }
+#undef BOOST_UNORDERED_CONSTRUCT_IMPL
 
-    private:
-        value_construct(value_construct const&);
-        value_construct& operator=(value_construct const&);
-    };
+    template <typename Alloc, typename A, typename B,
+        typename A0, typename A1, typename A2>
+    inline void construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
+            boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
+            typename enable_if<piecewise3<A, B, A0>, void*>::type = 0)
+    {
+        boost::unordered::detail::construct_from_tuple(alloc,
+            boost::addressof(address->first), args.a1);
+        boost::unordered::detail::construct_from_tuple(alloc,
+            boost::addressof(address->second), args.a2);
+    }
+
+#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
 
-    template <typename Alloc, typename T, BOOST_UNORDERED_EMPLACE_TEMPLATE>
-    inline void construct_node(Alloc& a, T* p, BOOST_UNORDERED_EMPLACE_ARGS)
+    template <typename Alloc, typename A, typename B, typename A0>
+    inline void construct_value_impl(Alloc&, std::pair<A, B>* address,
+            boost::unordered::detail::emplace_args1<A0> const& args,
+            typename enable_if<emulation1<A, B, A0>, void*>::type = 0)
     {
-        value_construct<boost::unordered::detail::allocator_traits<Alloc>, T>
-            construct_guard(a, p);
-        boost::unordered::detail::construct_impl(
-            p->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
-        construct_guard.release();
+        new((void*) boost::addressof(address->first)) A(
+            boost::forward<A0>(args.a0));
+        new((void*) boost::addressof(address->second)) B();
     }
 
-    template <typename Alloc, typename T>
-    inline void destroy_node(Alloc& a, T* p)
+    template <typename Alloc, typename A, typename B,
+        typename A0, typename A1, typename A2>
+    inline void construct_value_impl(Alloc&, std::pair<A, B>* address,
+            boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
+            typename enable_if<emulation3<A, B, A0>, void*>::type = 0)
     {
-        boost::unordered::detail::destroy(p->value_ptr());
-        boost::unordered::detail::allocator_traits<Alloc>::destroy(a, p);
+        new((void*) boost::addressof(address->first)) A(
+            boost::forward<A0>(args.a0));
+        new((void*) boost::addressof(address->second)) B(
+            boost::forward<A1>(args.a1),
+            boost::forward<A2>(args.a2));
     }
 
-#endif
+#define BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(z, num_params, _)               \
+    template <typename Alloc, typename A, typename B,                       \
+        BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A)                   \
+    >                                                                       \
+    inline void construct_value_impl(Alloc&, std::pair<A, B>* address,      \
+        boost::unordered::detail::BOOST_PP_CAT(emplace_args, num_params) <  \
+                BOOST_PP_ENUM_PARAMS_Z(z, num_params, A)                    \
+            > const& args)                                                  \
+    {                                                                       \
+        new((void*) boost::addressof(address->first)) A(                    \
+            boost::forward<A0>(args.a0));                                   \
+        new((void*) boost::addressof(address->second)) B(                   \
+            BOOST_PP_ENUM_##z(BOOST_PP_DEC(num_params),                     \
+                BOOST_UNORDERED_CALL_FORWARD2, args.a));                    \
+    }
+
+#define BOOST_UNORDERED_CALL_FORWARD2(z, i, a) \
+    BOOST_UNORDERED_CALL_FORWARD(z, BOOST_PP_INC(i), a)
+
+    BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(1, 2, _)
+    BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
+        BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL, _)
+
+#undef BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL
+#undef BOOST_UNORDERED_CALL_FORWARD2
+
+#endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
+#endif // BOOST_NO_VARIADIC_TEMPLATES
+
+}}}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Some helper functions for allocating & constructing
+
+namespace boost { namespace unordered { namespace detail {
 
     ////////////////////////////////////////////////////////////////////////////
     //
Modified: branches/release/boost/unordered/detail/buckets.hpp
==============================================================================
--- branches/release/boost/unordered/detail/buckets.hpp	(original)
+++ branches/release/boost/unordered/detail/buckets.hpp	2012-09-01 11:50:36 EDT (Sat, 01 Sep 2012)
@@ -53,14 +53,16 @@
 
         node_allocator& alloc_;
         node_pointer node_;
-        bool constructed_;
+        bool node_constructed_;
+        bool value_constructed_;
 
     public:
 
         node_constructor(node_allocator& n) :
             alloc_(n),
             node_(),
-            constructed_(false)
+            node_constructed_(false),
+            value_constructed_(false)
         {
         }
 
@@ -71,36 +73,27 @@
         template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
         void construct_value(BOOST_UNORDERED_EMPLACE_ARGS)
         {
-            BOOST_ASSERT(node_ && !constructed_);
-            boost::unordered::detail::construct_node(alloc_,
-                boost::addressof(*node_), BOOST_UNORDERED_EMPLACE_FORWARD);
-            node_->init(static_cast<typename node::link_pointer>(node_));
-            constructed_ = true;
+            BOOST_ASSERT(node_ && node_constructed_ && !value_constructed_);
+            boost::unordered::detail::construct_value_impl(
+                alloc_, node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
+            value_constructed_ = true;
         }
 
         template <typename A0>
         void construct_value2(BOOST_FWD_REF(A0) a0)
         {
-            BOOST_ASSERT(node_ && !constructed_);
-
-            boost::unordered::detail::construct_node(alloc_,
-                boost::addressof(*node_),
+            BOOST_ASSERT(node_ && node_constructed_ && !value_constructed_);
+            boost::unordered::detail::construct_value_impl(
+                alloc_, node_->value_ptr(),
                 BOOST_UNORDERED_EMPLACE_ARGS1(boost::forward<A0>(a0)));
-
-            constructed_ = true;
-            node_->init(static_cast<typename node::link_pointer>(node_));
+            value_constructed_ = true;
         }
 
         value_type const& value() const {
-            BOOST_ASSERT(node_ && constructed_);
+            BOOST_ASSERT(node_ && node_constructed_ && value_constructed_);
             return node_->value();
         }
 
-        node_pointer get()
-        {
-            return node_;
-        }
-
         // no throw
         node_pointer release()
         {
@@ -118,8 +111,13 @@
     node_constructor<Alloc>::~node_constructor()
     {
         if (node_) {
-            if (constructed_) {
-                boost::unordered::detail::destroy_node(alloc_,
+            if (value_constructed_) {
+                boost::unordered::detail::destroy_value_impl(alloc_,
+                    node_->value_ptr());
+            }
+
+            if (node_constructed_) {
+                node_allocator_traits::destroy(alloc_,
                     boost::addressof(*node_));
             }
 
@@ -131,13 +129,25 @@
     void node_constructor<Alloc>::construct_node()
     {
         if(!node_) {
-            constructed_ = false;
+            node_constructed_ = false;
+            value_constructed_ = false;
+
             node_ = node_allocator_traits::allocate(alloc_, 1);
+
+            node_allocator_traits::construct(alloc_,
+                boost::addressof(*node_), node());
+            node_->init(static_cast<typename node::link_pointer>(node_));
+            node_constructed_ = true;
         }
-        else if (constructed_) {
-            boost::unordered::detail::destroy_node(alloc_,
-                boost::addressof(*node_));
-            constructed_ = false;
+        else {
+            BOOST_ASSERT(node_constructed_);
+
+            if (value_constructed_)
+            {
+                boost::unordered::detail::destroy_value_impl(alloc_,
+                    node_->value_ptr());
+                value_constructed_ = false;
+            }
         }
     }
 
@@ -175,16 +185,6 @@
 
         enum { extra_node = false };
     };
-
-    template <typename LinkPointer>
-    struct node_base
-    {
-        typedef LinkPointer link_pointer;
-        link_pointer next_;
-
-        node_base() : next_() {}
-    };
-
 }}}
 
 namespace boost { namespace unordered { namespace iterator_detail {
@@ -720,14 +720,6 @@
                 node_constructor a(this->node_alloc());
                 a.construct_node();
 
-                // Since this node is just to mark the beginning it doesn't
-                // contain a value, so just construct node::node_base
-                // which containers the pointer to the next element.
-                node_allocator_traits::construct(node_alloc(),
-                    static_cast<typename node::node_base*>(
-                        boost::addressof(*a.get())),
-                    typename node::node_base());
-
                 (constructor.get() +
                     static_cast<std::ptrdiff_t>(this->bucket_count_))->next_ =
                         a.release();
@@ -772,8 +764,10 @@
 
         inline void delete_node(c_iterator n)
         {
-            boost::unordered::detail::destroy_node(
-                node_alloc(), boost::addressof(*n.node_));
+            boost::unordered::detail::destroy_value_impl(node_alloc(),
+                n.node_->value_ptr());
+            node_allocator_traits::destroy(node_alloc(),
+                    boost::addressof(*n.node_));
             node_allocator_traits::deallocate(node_alloc(), n.node_, 1);
             --size_;
         }
@@ -795,8 +789,7 @@
         inline void delete_extra_node(bucket_pointer) {}
 
         inline void delete_extra_node(node_pointer n) {
-            node_allocator_traits::destroy(node_alloc(),
-                static_cast<typename node::node_base*>(boost::addressof(*n)));
+            node_allocator_traits::destroy(node_alloc(), boost::addressof(*n));
             node_allocator_traits::deallocate(node_alloc(), n, 1);
         }
 
@@ -1041,6 +1034,36 @@
             tmp_functions_ = !tmp_functions_;
         }
     };
+
+    ////////////////////////////////////////////////////////////////////////////
+    // rvalue parameters when type can't be a BOOST_RV_REF(T) parameter
+    // e.g. for int
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES)
+#   define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T)
+#else
+    struct please_ignore_this_overload {
+        typedef please_ignore_this_overload type;
+    };
+
+    template <typename T>
+    struct rv_ref_impl {
+        typedef BOOST_RV_REF(T) type;
+    };
+
+    template <typename T>
+    struct rv_ref :
+        boost::detail::if_true<
+            boost::is_class<T>::value
+        >::BOOST_NESTED_TEMPLATE then <
+            boost::unordered::detail::rv_ref_impl<T>,
+            please_ignore_this_overload
+        >::type
+    {};
+
+#   define BOOST_UNORDERED_RV_REF(T) \
+        typename boost::unordered::detail::rv_ref<T>::type
+#endif
 }}}
 
 #if defined(BOOST_MSVC)
Modified: branches/release/boost/unordered/detail/equivalent.hpp
==============================================================================
--- branches/release/boost/unordered/detail/equivalent.hpp	(original)
+++ branches/release/boost/unordered/detail/equivalent.hpp	2012-09-01 11:50:36 EDT (Sat, 01 Sep 2012)
@@ -22,44 +22,20 @@
 
     template <typename A, typename T>
     struct grouped_node :
-        boost::unordered::detail::node_base<
-            typename ::boost::unordered::detail::rebind_wrap<
-                A, grouped_node<A, T> >::type::pointer
-        >,
         boost::unordered::detail::value_base<T>
     {
         typedef typename ::boost::unordered::detail::rebind_wrap<
             A, grouped_node<A, T> >::type::pointer link_pointer;
-        typedef boost::unordered::detail::node_base<link_pointer> node_base;
 
+        link_pointer next_;
         link_pointer group_prev_;
         std::size_t hash_;
 
-#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
-        template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
-        explicit grouped_node(BOOST_UNORDERED_EMPLACE_ARGS) :
-            node_base(),
-            group_prev_(),
-            hash_(0)
-        {
-            boost::unordered::detail::construct_impl(
-                this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
-        }
-
-        ~grouped_node() {
-            boost::unordered::detail::destroy(this->value_ptr());
-        }
-
-        grouped_node(grouped_node const&) {
-            assert(false);
-        }
-#else
         grouped_node() :
-            node_base(),
+            next_(),
             group_prev_(),
             hash_(0)
         {}
-#endif
 
         void init(link_pointer self)
         {
@@ -76,37 +52,16 @@
         boost::unordered::detail::ptr_bucket
     {
         typedef boost::unordered::detail::ptr_bucket bucket_base;
-        typedef bucket_base node_base;
         typedef ptr_bucket* link_pointer;
 
         link_pointer group_prev_;
         std::size_t hash_;
 
-#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
-        template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
-        explicit grouped_ptr_node(BOOST_UNORDERED_EMPLACE_ARGS) :
-            bucket_base(),
-            group_prev_(0),
-            hash_(0)
-        {
-            boost::unordered::detail::construct_impl(
-                this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
-        }
-
-        ~grouped_ptr_node() {
-            boost::unordered::detail::destroy(this->value_ptr());
-        }
-
-        grouped_ptr_node(grouped_ptr_node const&) {
-            assert(false);
-        }
-#else
         grouped_ptr_node() :
             bucket_base(),
             group_prev_(0),
             hash_(0)
         {}
-#endif
 
         void init(link_pointer self)
         {
Modified: branches/release/boost/unordered/detail/table.hpp
==============================================================================
--- branches/release/boost/unordered/detail/table.hpp	(original)
+++ branches/release/boost/unordered/detail/table.hpp	2012-09-01 11:50:36 EDT (Sat, 01 Sep 2012)
@@ -310,6 +310,11 @@
         template <typename Propagate>
         void swap(table& x, Propagate p)
         {
+            // According to 23.2.1.8, if propagate_on_container_swap is
+            // false the behaviour is undefined unless the allocators
+            // are equal.
+            BOOST_ASSERT(p.value || this->node_alloc() == x.node_alloc());
+
             boost::unordered::detail::set_hash_functions<hasher, key_equal>
                 op1(*this, x);
             boost::unordered::detail::set_hash_functions<hasher, key_equal>
Modified: branches/release/boost/unordered/detail/unique.hpp
==============================================================================
--- branches/release/boost/unordered/detail/unique.hpp	(original)
+++ branches/release/boost/unordered/detail/unique.hpp	2012-09-01 11:50:36 EDT (Sat, 01 Sep 2012)
@@ -24,41 +24,18 @@
 
     template <typename A, typename T>
     struct unique_node :
-        boost::unordered::detail::node_base<
-            typename ::boost::unordered::detail::rebind_wrap<
-                A, unique_node<A, T> >::type::pointer
-        >,
         boost::unordered::detail::value_base<T>
     {
         typedef typename ::boost::unordered::detail::rebind_wrap<
             A, unique_node<A, T> >::type::pointer link_pointer;
-        typedef boost::unordered::detail::node_base<link_pointer> node_base;
 
+        link_pointer next_;
         std::size_t hash_;
 
-#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
-        template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
-        explicit unique_node(BOOST_UNORDERED_EMPLACE_ARGS) :
-            node_base(),
-            hash_(0)
-        {
-            boost::unordered::detail::construct_impl(
-                this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
-        }
-
-        ~unique_node() {
-            boost::unordered::detail::destroy(this->value_ptr());
-        }
-
-        unique_node(unique_node const&) {
-            BOOST_ASSERT(false);
-        }
-#else
         unique_node() :
-            node_base(),
+            next_(),
             hash_(0)
         {}
-#endif
 
         void init(link_pointer)
         {
@@ -74,34 +51,14 @@
         boost::unordered::detail::ptr_bucket
     {
         typedef boost::unordered::detail::ptr_bucket bucket_base;
-        typedef bucket_base node_base;
         typedef ptr_bucket* link_pointer;
 
         std::size_t hash_;
 
-#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
-        template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
-        explicit ptr_node(BOOST_UNORDERED_EMPLACE_ARGS) :
-            bucket_base(),
-            hash_(0)
-        {
-            boost::unordered::detail::construct_impl(
-                this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
-        }
-
-        ~ptr_node() {
-            boost::unordered::detail::destroy(this->value_ptr());
-        }
-
-        ptr_node(ptr_node const&) {
-            BOOST_ASSERT(false);
-        }
-#else
         ptr_node() :
             bucket_base(),
             hash_(0)
         {}
-#endif
 
         void init(link_pointer)
         {
Modified: branches/release/libs/unordered/test/exception/assign_exception_tests.cpp
==============================================================================
--- branches/release/libs/unordered/test/exception/assign_exception_tests.cpp	(original)
+++ branches/release/libs/unordered/test/exception/assign_exception_tests.cpp	2012-09-01 11:50:36 EDT (Sat, 01 Sep 2012)
@@ -39,26 +39,40 @@
 struct assign_base : public test::exception_base
 {
     const test::random_values<T> x_values, y_values;
-    const T x,y;
+    T x,y;
 
     typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
     typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
     typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
 
-    assign_base(unsigned int count1, unsigned int count2, int tag1, int tag2) :
+    assign_base(unsigned int count1, unsigned int count2, int tag1, int tag2,
+        float mlf1 = 1.0, float mlf2 = 1.0) :
         x_values(count1),
         y_values(count2),
         x(x_values.begin(), x_values.end(), 0, hasher(tag1), key_equal(tag1),
             allocator_type(tag1)),
         y(y_values.begin(), y_values.end(), 0, hasher(tag2), key_equal(tag2),
             allocator_type(tag2))
-    {}
+    {
+        x.max_load_factor(mlf1);
+        y.max_load_factor(mlf2);
+    }
 
     typedef T data_type;
     T init() const { return T(x); }
     void run(T& x1) const { x1 = y; }
     void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
-        { test::check_equivalent_keys(x1); }
+    {
+        test::check_equivalent_keys(x1);
+
+        // If the container is empty at the point of the exception, the
+        // internal structure is hidden, this exposes it.
+        T& y = const_cast<T&>(x1);
+        if (x_values.size()) {
+            y.emplace(*x_values.begin());
+            test::check_equivalent_keys(y);
+        }
+    }
 };
 
 template <class T>
@@ -85,7 +99,13 @@
     assign_test4() : assign_base<T>(10, 10, 1, 2) {}
 };
 
+template <class T>
+struct assign_test5 : assign_base<T>
+{
+    assign_test5() : assign_base<T>(5, 60, 0, 0, 1.0, 0.1) {}
+};
+
 RUN_EXCEPTION_TESTS(
     (self_assign_test1)(self_assign_test2)
-    (assign_test1)(assign_test2)(assign_test3)(assign_test4),
+    (assign_test1)(assign_test2)(assign_test3)(assign_test4)(assign_test5),
     CONTAINER_SEQ)
Modified: branches/release/libs/unordered/test/exception/containers.hpp
==============================================================================
--- branches/release/libs/unordered/test/exception/containers.hpp	(original)
+++ branches/release/libs/unordered/test/exception/containers.hpp	2012-09-01 11:50:36 EDT (Sat, 01 Sep 2012)
@@ -18,13 +18,13 @@
     test::exception::object,
     test::exception::hash,
     test::exception::equal_to,
-    test::exception::allocator<test::exception::object> > test_multiset;
+    test::exception::allocator2<test::exception::object> > test_multiset;
 typedef boost::unordered_map<
     test::exception::object,
     test::exception::object,
     test::exception::hash,
     test::exception::equal_to,
-    test::exception::allocator<test::exception::object> > test_map;
+    test::exception::allocator2<test::exception::object> > test_map;
 typedef boost::unordered_multimap<
     test::exception::object,
     test::exception::object,
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	2012-09-01 11:50:36 EDT (Sat, 01 Sep 2012)
@@ -60,7 +60,9 @@
         initial_x(x_values.begin(), x_values.end(), 0, hasher(tag1),
                 key_equal(tag1), allocator_type(tag1)),
         initial_y(y_values.begin(), y_values.end(), 0, hasher(tag2),
-                key_equal(tag2), allocator_type(tag2))
+                key_equal(tag2), allocator_type(
+                    T::allocator_type::propagate_on_container_swap::value ?
+                        tag2 : tag1))
     {}
 
     struct data_type {
@@ -71,6 +73,7 @@
     };
 
     data_type init() const { return data_type(initial_x, initial_y); }
+
     void run(data_type& d) const {
         try {
             d.x.swap(d.y);
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	2012-09-01 11:50:36 EDT (Sat, 01 Sep 2012)
@@ -82,16 +82,39 @@
             }
         };
 
-        // Finally, check that size matches up.
+        // Check that size matches up.
+
         if(x1.size() != size) {
             BOOST_ERROR("x1.size() doesn't match actual size.");
             std::cout<<x1.size()<<"/"<<size<<std::endl;
         }
+
+        // Check the load factor.
+
         float load_factor =
             static_cast<float>(size) / static_cast<float>(x1.bucket_count());
         using namespace std;
         if(fabs(x1.load_factor() - load_factor) > x1.load_factor() / 64)
             BOOST_ERROR("x1.load_factor() doesn't match actual load_factor.");
+
+        // Check that size in the buckets matches up.
+
+        BOOST_DEDUCED_TYPENAME X::size_type bucket_size = 0;
+
+        for (BOOST_DEDUCED_TYPENAME X::size_type
+                i = 0; i < x1.bucket_count(); ++i)
+        {
+            for (BOOST_DEDUCED_TYPENAME X::const_local_iterator
+                    begin = x1.begin(i), end = x1.end(i); begin != end; ++begin)
+            {
+                ++bucket_size;
+            }
+        }
+
+        if(x1.size() != bucket_size) {
+            BOOST_ERROR("x1.size() doesn't match bucket size.");
+            std::cout<<x1.size()<<"/"<<bucket_size<<std::endl;
+        }
     }
 }
 
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	2012-09-01 11:50:36 EDT (Sat, 01 Sep 2012)
@@ -401,6 +401,186 @@
         //}
         return x.tag_ != y.tag_;
     }
+
+    template <class T>
+    class allocator2
+    {
+    public:
+        int tag_;
+        typedef std::size_t size_type;
+        typedef std::ptrdiff_t difference_type;
+        typedef T* pointer;
+        typedef T const* const_pointer;
+        typedef T& reference;
+        typedef T const& const_reference;
+        typedef T value_type;
+
+        template <class U> struct rebind { typedef allocator2<U> other; };
+
+        explicit allocator2(int t = 0) : tag_(t)
+        {
+            UNORDERED_SCOPE(allocator2::allocator2()) {
+                UNORDERED_EPOINT("Mock allocator2 default constructor.");
+            }
+            test::detail::tracker.allocator_ref();
+        }
+
+        allocator2(allocator<T> const& x) : tag_(x.tag_)
+        {
+            UNORDERED_SCOPE(allocator2::allocator2()) {
+                UNORDERED_EPOINT("Mock allocator2 constructor from allocator.");
+            }
+            test::detail::tracker.allocator_ref();
+        }
+
+        template <class Y> allocator2(allocator2<Y> const& x) : tag_(x.tag_)
+        {
+            UNORDERED_SCOPE(allocator2::allocator2()) {
+                UNORDERED_EPOINT("Mock allocator2 template copy constructor.");
+            }
+            test::detail::tracker.allocator_ref();
+        }
+
+        allocator2(allocator2 const& x) : tag_(x.tag_)
+        {
+            UNORDERED_SCOPE(allocator2::allocator2()) {
+                UNORDERED_EPOINT("Mock allocator2 copy constructor.");
+            }
+            test::detail::tracker.allocator_ref();
+        }
+
+        ~allocator2() {
+            test::detail::tracker.allocator_unref();
+        }
+
+        allocator2& operator=(allocator2 const& x) {
+            UNORDERED_SCOPE(allocator2::allocator2()) {
+                UNORDERED_EPOINT("Mock allocator2 assignment operator.");
+                tag_ = x.tag_;
+            }
+            return *this;
+        }
+
+        // If address throws, then it can't be used in erase or the
+        // destructor, which is very limiting. I need to check up on
+        // this.
+
+        pointer address(reference r) {
+            //UNORDERED_SCOPE(allocator2::address(reference)) {
+            //    UNORDERED_EPOINT("Mock allocator2 address function.");
+            //}
+            return pointer(&r);
+        }
+
+        const_pointer address(const_reference r)  {
+            //UNORDERED_SCOPE(allocator2::address(const_reference)) {
+            //    UNORDERED_EPOINT("Mock allocator2 const address function.");
+            //}
+            return const_pointer(&r);
+        }
+
+        pointer allocate(size_type n) {
+            T* ptr = 0;
+            UNORDERED_SCOPE(allocator2::allocate(size_type)) {
+                UNORDERED_EPOINT("Mock allocator2 allocate function.");
+
+                using namespace std;
+                ptr = (T*) malloc(n * sizeof(T));
+                if(!ptr) throw std::bad_alloc();
+            }
+            test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
+            return pointer(ptr);
+
+            //return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
+        }
+
+        pointer allocate(size_type n, void const* u)
+        {
+            T* ptr = 0;
+            UNORDERED_SCOPE(allocator2::allocate(size_type, const_pointer)) {
+                UNORDERED_EPOINT("Mock allocator2 allocate function.");
+
+                using namespace std;
+                ptr = (T*) malloc(n * sizeof(T));
+                if(!ptr) throw std::bad_alloc();
+            }
+            test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
+            return pointer(ptr);
+
+            //return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
+        }
+
+        void deallocate(pointer p, size_type n)
+        {
+            //::operator delete((void*) p);
+            if(p) {
+                test::detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
+                using namespace std;
+                free(p);
+            }
+        }
+
+        void construct(pointer p, T const& t) {
+            UNORDERED_SCOPE(allocator2::construct(T*, T)) {
+                UNORDERED_EPOINT("Mock allocator2 construct function.");
+                new(p) T(t);
+            }
+            test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
+        }
+
+#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+        template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
+            UNORDERED_SCOPE(allocator2::construct(pointer, BOOST_FWD_REF(Args)...)) {
+                UNORDERED_EPOINT("Mock allocator2 construct function.");
+                new(p) T(boost::forward<Args>(args)...);
+            }
+            test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
+        }
+#endif
+
+        void destroy(T* p) {
+            test::detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
+            p->~T();
+        }
+
+        size_type max_size() const {
+            UNORDERED_SCOPE(allocator2::construct(pointer, T)) {
+                UNORDERED_EPOINT("Mock allocator2 max_size function.");
+            }
+            return (std::numeric_limits<std::size_t>::max)();
+        }
+
+        typedef false_type propagate_on_container_copy_assignment;
+        typedef false_type propagate_on_container_move_assignment;
+        typedef false_type propagate_on_container_swap;
+    };
+
+    template <class T>
+    void swap(allocator2<T>& x, allocator2<T>& y)
+    {
+        std::swap(x.tag_, y.tag_);
+    }
+
+    // It's pretty much impossible to write a compliant swap when these
+    // two can throw. So they don't.
+
+    template <class T>
+    inline bool operator==(allocator2<T> const& x, allocator2<T> const& y)
+    {
+        //UNORDERED_SCOPE(operator==(allocator2, allocator2)) {
+        //    UNORDERED_EPOINT("Mock allocator2 equality operator.");
+        //}
+        return x.tag_ == y.tag_;
+    }
+
+    template <class T>
+    inline bool operator!=(allocator2<T> const& x, allocator2<T> const& y)
+    {
+        //UNORDERED_SCOPE(operator!=(allocator2, allocator2)) {
+        //    UNORDERED_EPOINT("Mock allocator2 inequality operator.");
+        //}
+        return x.tag_ != y.tag_;
+    }
 }
 }
 
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	2012-09-01 11:50:36 EDT (Sat, 01 Sep 2012)
@@ -26,7 +26,7 @@
     class destructible;
     class copy_constructible;
     class copy_constructible_equality_comparable;
-    class default_copy_constructible;
+    class default_assignable;
     class assignable;
 
     struct ampersand_operator_used {};
@@ -99,26 +99,29 @@
         return false;
     }
 
-    class default_copy_constructible
+    class default_assignable
     {
     public:
-        default_copy_constructible(constructor_param const&) {}
+        default_assignable(constructor_param const&) {}
 
-        default_copy_constructible()
+        default_assignable()
         {
         }
 
-        default_copy_constructible(default_copy_constructible const&)
+        default_assignable(default_assignable const&)
         {
         }
 
-        ~default_copy_constructible()
+        default_assignable& operator=(default_assignable const&)
+        {
+            return *this;
+        }
+
+        ~default_assignable()
         {
         }
 
     private:
-        default_copy_constructible& operator=(
-            default_copy_constructible const&);
         ampersand_operator_used operator&() const {
             return ampersand_operator_used(); }
     };
@@ -148,7 +151,7 @@
         movable1() {}
         explicit movable1(movable_init) {}
         movable1(BOOST_RV_REF(movable1)) {}
-        movable1& operator=(BOOST_RV_REF(movable1));
+        movable1& operator=(BOOST_RV_REF(movable1)) { return *this; }
         ~movable1() {}
     };
 
@@ -160,6 +163,7 @@
         explicit movable2(movable_init) {}
         movable2(movable2&&) {}
         ~movable2() {}
+        movable2& operator=(movable2&&) { return *this; }
     private:
         movable2() {}
         movable2(movable2 const&);
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	2012-09-01 11:50:36 EDT (Sat, 01 Sep 2012)
@@ -63,6 +63,7 @@
         tracker.compare(y);
         BOOST_TEST(x.max_load_factor() == mlf);
         BOOST_TEST(y.max_load_factor() == mlf);
+        BOOST_TEST(y.load_factor() <= y.max_load_factor());
     }
 }
 
@@ -87,9 +88,31 @@
         T x1(v.begin(), v.end(), 0, hf1, eq1);
         T x2(0, hf2, eq2);
         x2 = x1;
+        BOOST_TEST(test::equivalent(x1.hash_function(), hf1));
+        BOOST_TEST(test::equivalent(x1.key_eq(), eq1));
         BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
         BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
+        test::check_container(x1, v);
         test::check_container(x2, v);
+        BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
+    }
+
+    std::cerr<<"assign_tests2.1a\n";
+    {
+        test::check_instances check_;
+
+        test::random_values<T> v1(0, generator);
+        test::random_values<T> v2(1000, generator);
+        T x1(0, hf2, eq2);
+        T x2(v2.begin(), v2.end(), 0, hf1, eq1);
+        x2 = x1;
+        BOOST_TEST(test::equivalent(x1.hash_function(), hf2));
+        BOOST_TEST(test::equivalent(x1.key_eq(), eq2));
+        BOOST_TEST(test::equivalent(x2.hash_function(), hf2));
+        BOOST_TEST(test::equivalent(x2.key_eq(), eq2));
+        test::check_container(x1, v1);
+        test::check_container(x2, v1);
+        BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
     }
 
     std::cerr<<"assign_tests2.2\n";
@@ -110,7 +133,55 @@
             BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
             BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
         }
+        test::check_container(x1, v1);
+        test::check_container(x2, v1);
+        BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
+    }
+
+    std::cerr<<"assign_tests2.3\n";
+    {
+        test::check_instances check_;
+
+        test::random_values<T> v1(100, generator), v2(1000, 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));
+        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(x1, v1);
+        test::check_container(x2, v1);
+        BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
+    }
+
+    std::cerr<<"assign_tests2.4\n";
+    {
+        test::check_instances check_;
+
+        test::random_values<T> v1(1000, 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));
+        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(x1, v1);
         test::check_container(x2, v1);
+        BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
     }
 }
 
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	2012-09-01 11:50:36 EDT (Sat, 01 Sep 2012)
@@ -32,13 +32,13 @@
 
 template class boost::unordered_map<
     test::minimal::assignable,
-    test::minimal::default_copy_constructible,
+    test::minimal::default_assignable,
     test::minimal::hash<test::minimal::assignable>,
     test::minimal::equal_to<test::minimal::assignable>,
     test::minimal::allocator<test::minimal::assignable> >;
 template class boost::unordered_multimap<
     test::minimal::assignable,
-    test::minimal::copy_constructible,
+    test::minimal::assignable,
     test::minimal::hash<test::minimal::assignable>,
     test::minimal::equal_to<test::minimal::assignable>,
     test::minimal::allocator<test::minimal::assignable> >;
@@ -48,7 +48,7 @@
     test::minimal::constructor_param x;
 
     typedef std::pair<test::minimal::assignable const,
-            test::minimal::copy_constructible> value_type;
+            test::minimal::assignable> value_type;
     value_type value(x, x);
 
     std::cout<<"Test unordered_map.\n";
@@ -62,7 +62,7 @@
 
     boost::unordered_map<
         test::minimal::assignable,
-        test::minimal::copy_constructible,
+        test::minimal::assignable,
         test::minimal::hash<test::minimal::assignable>,
         test::minimal::equal_to<test::minimal::assignable>,
         test::minimal::allocator<value_type> > map;
@@ -82,7 +82,7 @@
 
     boost::unordered_multimap<
         test::minimal::assignable,
-        test::minimal::copy_constructible,
+        test::minimal::assignable,
         test::minimal::hash<test::minimal::assignable>,
         test::minimal::equal_to<test::minimal::assignable>,
         test::minimal::allocator<value_type> > multimap;
@@ -95,7 +95,7 @@
 UNORDERED_AUTO_TEST(equality_tests) {
     typedef std::pair<
             test::minimal::copy_constructible_equality_comparable const,
-            test::minimal::copy_constructible> value_type;
+            test::minimal::copy_constructible_equality_comparable> value_type;
 
     boost::unordered_map<int, int> int_map;
 
@@ -187,44 +187,44 @@
     test::minimal::equal_to<test::minimal::assignable> equal_to(x);
 
     typedef std::pair<test::minimal::assignable const,
-            test::minimal::copy_constructible> map_value_type;
-    map_value_type map_value(assignable, copy_constructible);
+            test::minimal::assignable> map_value_type;
+    map_value_type map_value(assignable, assignable);
 
     std::cout<<"Test unordered_map.\n";
 
     boost::unordered_map<
         test::minimal::assignable,
-        test::minimal::copy_constructible,
+        test::minimal::assignable,
         test::minimal::hash<test::minimal::assignable>,
         test::minimal::equal_to<test::minimal::assignable>,
         test::minimal::allocator<map_value_type> > map;
 
     unordered_unique_test(map, map_value);
-    unordered_map_test(map, assignable, copy_constructible);
+    unordered_map_test(map, assignable, assignable);
     unordered_copyable_test(map, assignable, map_value, hash, equal_to);
 
     boost::unordered_map<
         test::minimal::assignable,
-        test::minimal::default_copy_constructible,
+        test::minimal::default_assignable,
         test::minimal::hash<test::minimal::assignable>,
         test::minimal::equal_to<test::minimal::assignable>,
         test::minimal::allocator<map_value_type> > map2;
 
-    test::minimal::default_copy_constructible default_copy_constructible;
+    test::minimal::default_assignable default_assignable;
 
-    unordered_map_functions(map2, assignable, default_copy_constructible);
+    unordered_map_functions(map2, assignable, default_assignable);
 
     std::cout<<"Test unordered_multimap.\n";
 
     boost::unordered_multimap<
         test::minimal::assignable,
-        test::minimal::copy_constructible,
+        test::minimal::assignable,
         test::minimal::hash<test::minimal::assignable>,
         test::minimal::equal_to<test::minimal::assignable>,
         test::minimal::allocator<map_value_type> > multimap;
 
     unordered_equivalent_test(multimap, map_value);
-    unordered_map_test(multimap, assignable, copy_constructible);
+    unordered_map_test(multimap, assignable, assignable);
     unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
 }
 
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	2012-09-01 11:50:36 EDT (Sat, 01 Sep 2012)
@@ -170,7 +170,6 @@
     UNORDERED_TEST(unnecessary_copy_emplace_rvalue_test,
             ((set)(multiset)(map)(multimap)))
 
-#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
     template <class T>
     void unnecessary_copy_emplace_move_test(T*)
     {
@@ -178,13 +177,17 @@
         T x;
         BOOST_DEDUCED_TYPENAME T::value_type a;
         COPY_COUNT(1); MOVE_COUNT(0);
-        x.emplace(std::move(a));
+        x.emplace(boost::move(a));
+#if !defined(BOOST_NO_RVALUE_REFERENCES)
         COPY_COUNT(1); MOVE_COUNT(1);
+#else
+        // Since std::pair isn't movable, move only works for sets.
+        COPY_COUNT_RANGE(1, 2); MOVE_COUNT_RANGE(0, 1);
+#endif
     }
 
     UNORDERED_TEST(unnecessary_copy_emplace_move_test,
             ((set)(multiset)(map)(multimap)))
-#endif
 
     template <class T>
     void unnecessary_copy_emplace_boost_move_set_test(T*)
@@ -270,14 +273,16 @@
         x.emplace(source<count_copies>());
         COPY_COUNT(1); MOVE_COUNT(source_cost);
 
-#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
         // No move should take place.
         reset();
-        x.emplace(std::move(a));
+        x.emplace(boost::move(a));
+#if !defined(BOOST_NO_RVALUE_REFERENCES)
         COPY_COUNT(0); MOVE_COUNT(0);
+#else
+        COPY_COUNT(0); MOVE_COUNT(1);
 #endif
 
-        // Just in case a did get moved...
+        // Use a new value for cases where a did get moved...
         count_copies b;
 
         // The container will have to create a copy in order to compare with
@@ -367,16 +372,12 @@
 
 #endif
 
-#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
-
         // No move should take place.
         // (since a is already in the container)
         reset();
-        x.emplace(std::move(a));
+        x.emplace(boost::move(a));
         COPY_COUNT(0); MOVE_COUNT(0);
 
-#endif
-
         //
         // 2 arguments
         //