Boost logo

Boost-Commit :

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
         //


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