Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r74234 - in branches/release: boost/unordered boost/unordered/detail libs/unordered libs/unordered/doc libs/unordered/test/unordered
From: dnljms_at_[hidden]
Date: 2011-09-04 15:37:47


Author: danieljames
Date: 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
New Revision: 74234
URL: http://svn.boost.org/trac/boost/changeset/74234

Log:
Unordered: Merge from trunk

- Remove use of BOOST_DEDUCED_TYPENAME and BOOST_UNORDERED_PAIR_CAST, it's
  unlikely that the compilers which require them will be able to cope with the
  new version of unordered.
- Use the old equality algorithm if BOOST_UNORDERED_DEPRECATED_EQUALITY is
  defined.
- Use SFINAE to control which overloads of `construct_impl` are available.
  Fixes problems with differing overload resolution on different compilers.
- Support for piecewise pair construction.
- Only support the old variadic pair construction when
  BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT is defined (also fixed some bugs).
- Avoid instantiating BOOST_RV_REF for non-classes.
- Support optional allocator member functions for compilers with SFINAE
  expressions and Visual C++ 9.0/10.0
- Follow boost macro naming conventions.
- Improved portability for `allocator_traits` emulation.

Current compiler support:

- Full support for GCC 4.4+, Visual C++ 9.0+, Clang.
- All other compilers odn't support optional allocator members.
- No other errors for GCC 3.4.6+, Visual C++ 8.0, Intel, Pathscale.
- Visual Age has a compile error if `select_on_container_copy_construction`
  isn't `const` (it should ignore it).
- `select_on_container_copy_construction` detection doesn't work on Sun.
- `unnecessary_copy_tests` is failling for vacpp on AIX, but not on linux.
- Warnings causing failures for Visual C++ with STLport and WM5.

Added:
   branches/release/libs/unordered/test/unordered/equality_deprecated.cpp
      - copied unchanged from r74232, /trunk/libs/unordered/test/unordered/equality_deprecated.cpp
   branches/release/libs/unordered/test/unordered/minimal_allocator.cpp
      - copied unchanged from r74156, /trunk/libs/unordered/test/unordered/minimal_allocator.cpp
Properties modified:
   branches/release/boost/unordered/ (props changed)
   branches/release/libs/unordered/ (props changed)
Text files modified:
   branches/release/boost/unordered/detail/allocator_helpers.hpp | 216 +++++++++++++++++++-------
   branches/release/boost/unordered/detail/buckets.hpp | 312 +++++++++++++++++++++++++++-----------
   branches/release/boost/unordered/detail/equivalent.hpp | 76 ++++++--
   branches/release/boost/unordered/detail/extract_key.hpp | 67 +++++++
   branches/release/boost/unordered/detail/fwd.hpp | 3
   branches/release/boost/unordered/detail/node.hpp | 24 +-
   branches/release/boost/unordered/detail/table.hpp | 98 ++++++------
   branches/release/boost/unordered/detail/unique.hpp | 53 ++++--
   branches/release/boost/unordered/detail/util.hpp | 71 +++++--
   branches/release/boost/unordered/unordered_map.hpp | 187 +++++++++-------------
   branches/release/boost/unordered/unordered_set.hpp | 170 ++++++++------------
   branches/release/libs/unordered/doc/buckets.qbk | 2
   branches/release/libs/unordered/doc/changes.qbk | 3
   branches/release/libs/unordered/doc/comparison.qbk | 4
   branches/release/libs/unordered/doc/compliance.qbk | 89 ++++++++--
   branches/release/libs/unordered/doc/hash_equality.qbk | 5
   branches/release/libs/unordered/doc/intro.qbk | 19 -
   branches/release/libs/unordered/doc/rationale.qbk | 6
   branches/release/libs/unordered/doc/ref.php | 81 +++++----
   branches/release/libs/unordered/doc/ref.xml | 324 +++++++++++++++++++++++----------------
   branches/release/libs/unordered/doc/unordered.qbk | 2
   branches/release/libs/unordered/test/unordered/Jamfile.v2 | 5
   branches/release/libs/unordered/test/unordered/compile_set.cpp | 4
   branches/release/libs/unordered/test/unordered/insert_tests.cpp | 43 ++++
   branches/release/libs/unordered/test/unordered/unnecessary_copy_tests.cpp | 54 ++++++
   25 files changed, 1201 insertions(+), 717 deletions(-)

Modified: branches/release/boost/unordered/detail/allocator_helpers.hpp
==============================================================================
--- branches/release/boost/unordered/detail/allocator_helpers.hpp (original)
+++ branches/release/boost/unordered/detail/allocator_helpers.hpp 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -19,6 +19,8 @@
 #include <boost/detail/select_type.hpp>
 #include <boost/utility/enable_if.hpp>
 #include <boost/preprocessor/cat.hpp>
+#include <boost/limits.hpp>
+#include <boost/type_traits/add_lvalue_reference.hpp>
 
 #if (defined(BOOST_NO_STD_ALLOCATOR) || defined(BOOST_DINKUMWARE_STDLIB)) \
     && !defined(__BORLANDC__)
@@ -76,13 +78,12 @@
     template <typename Alloc, typename T>
     struct rebind_wrap
     {
- typedef BOOST_DEDUCED_TYPENAME
- Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
+ typedef typename Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
             type;
     };
 # endif
 
- template <typename T> T& make();
+ template <typename T> typename boost::add_lvalue_reference<T>::type make();
     struct choice9 { typedef char (&type)[9]; };
     struct choice8 : choice9 { typedef char (&type)[8]; };
     struct choice7 : choice8 { typedef char (&type)[7]; };
@@ -94,13 +95,14 @@
     struct choice1 : choice2 { typedef char (&type)[1]; };
     choice1 choose();
 
- #define BOOST_DEFAULT_TYPE_TMPLT(tname) \
+#if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
+
+ #define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
         template <typename Tp, typename Default> \
         struct default_type_ ## tname { \
                                                                             \
             template <typename X> \
- static choice1::type test(choice1, \
- BOOST_DEDUCED_TYPENAME X::tname* = 0); \
+ static choice1::type test(choice1, typename X::tname* = 0); \
                                                                             \
             template <typename X> \
             static choice2::type test(choice2, void* = 0); \
@@ -109,24 +111,50 @@
                                                                             \
             enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
                                                                             \
- typedef BOOST_DEDUCED_TYPENAME \
- boost::detail::if_true<value>:: \
+ typedef typename boost::detail::if_true<value>:: \
                 BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
                 ::type::tname type; \
         }
 
- #define BOOST_DEFAULT_TYPE(T,tname, arg) \
- BOOST_DEDUCED_TYPENAME default_type_ ## tname<T, arg>::type
+#else
 
- BOOST_DEFAULT_TYPE_TMPLT(pointer);
- BOOST_DEFAULT_TYPE_TMPLT(const_pointer);
- BOOST_DEFAULT_TYPE_TMPLT(void_pointer);
- BOOST_DEFAULT_TYPE_TMPLT(const_void_pointer);
- BOOST_DEFAULT_TYPE_TMPLT(difference_type);
- BOOST_DEFAULT_TYPE_TMPLT(size_type);
- BOOST_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment);
- BOOST_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
- BOOST_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
+ template <typename T, typename T2>
+ struct sfinae : T2 {};
+
+ #define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
+ template <typename Tp, typename Default> \
+ struct default_type_ ## tname { \
+ \
+ template <typename X> \
+ static typename sfinae<typename X::tname, choice1>::type \
+ test(choice1); \
+ \
+ template <typename X> \
+ static choice2::type test(choice2); \
+ \
+ struct DefaultWrap { typedef Default tname; }; \
+ \
+ enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
+ \
+ typedef typename boost::detail::if_true<value>:: \
+ BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
+ ::type::tname type; \
+ }
+
+#endif
+
+ #define BOOST_UNORDERED_DEFAULT_TYPE(T,tname, arg) \
+ typename default_type_ ## tname<T, arg>::type
+
+ BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(pointer);
+ BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_pointer);
+ BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(void_pointer);
+ BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_void_pointer);
+ BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(difference_type);
+ BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(size_type);
+ BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment);
+ BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
+ BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
 
 #if !defined(BOOST_NO_SFINAE_EXPR) || BOOST_WORKAROUND(BOOST_MSVC, >= 1500)
 
@@ -146,14 +174,40 @@
         static BOOST_PP_CAT(choice, result)::type test( \
             BOOST_PP_CAT(choice, count))
 
+#define BOOST_UNORDERED_HAS_EXPRESSION(name, expression) \
+ struct BOOST_PP_CAT(has_, name) \
+ { \
+ BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, expression); \
+ BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
+ \
+ enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) };\
+ }
+
     template <typename T>
- struct has_select_on_container_copy_construction
- {
- BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, make<U const>().select_on_container_copy_construction());
- BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2);
-
- enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) };
- };
+ BOOST_UNORDERED_HAS_EXPRESSION(
+ select_on_container_copy_construction,
+ make<U const>().select_on_container_copy_construction()
+ );
+
+ // Only supporting the basic copy constructor for now.
+
+ template <typename T, typename ValueType>
+ BOOST_UNORDERED_HAS_EXPRESSION(
+ construct,
+ make<U>().construct(make<ValueType*>(), make<ValueType const>())
+ );
+
+ template <typename T, typename ValueType>
+ BOOST_UNORDERED_HAS_EXPRESSION(
+ destroy,
+ make<U>().destroy(make<ValueType*>())
+ );
+
+ template <typename T>
+ BOOST_UNORDERED_HAS_EXPRESSION(
+ max_size,
+ make<U const>().max_size()
+ );
 
 #else
 
@@ -165,32 +219,43 @@
                                                                             \
     template <BOOST_PP_CAT(check, count) e> \
     struct BOOST_PP_CAT(test, count) { \
- typedef void* type; \
+ typedef BOOST_PP_CAT(choice, result) type; \
     }; \
                                                                             \
- template <class U> static BOOST_PP_CAT(choice, result)::type \
- test(BOOST_PP_CAT(choice, count), \
- typename BOOST_PP_CAT(test, count)< \
- &U::name>::type = 0)
+ template <class U> static typename \
+ BOOST_PP_CAT(test, count)<&U::name>::type \
+ test(BOOST_PP_CAT(choice, count))
 
 #define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \
     template <class U> static BOOST_PP_CAT(choice, result)::type \
- test(BOOST_PP_CAT(choice, count), void* = 0)
+ test(BOOST_PP_CAT(choice, count))
 
 
     template <typename T>
     struct has_select_on_container_copy_construction
     {
- BOOST_UNORDERED_CHECK_MEMBER(1, 1, select_on_container_copy_construction, T (T::*)() const);
+ BOOST_UNORDERED_CHECK_MEMBER(1, 1,
+ select_on_container_copy_construction,
+ T (T::*)() const);
         BOOST_UNORDERED_DEFAULT_MEMBER(2, 2);
  
         enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) };
     };
 
+ // Detection isn't reliable enough, so just assume that we have these
+ // functions.
+
+ template <typename Alloc, typename value_type>
+ struct has_construct : true_type {};
+ template <typename Alloc, typename value_type>
+ struct has_destroy : true_type {};
+ template <typename Alloc>
+ struct has_max_size : true_type {};
+
 #endif
 
     template <typename Alloc>
- inline BOOST_DEDUCED_TYPENAME boost::enable_if<
+ inline typename boost::enable_if<
             has_select_on_container_copy_construction<Alloc>, Alloc
>::type call_select_on_container_copy_construction(const Alloc& rhs)
     {
@@ -198,48 +263,62 @@
     }
 
     template <typename Alloc>
- inline BOOST_DEDUCED_TYPENAME boost::disable_if<
+ inline typename boost::disable_if<
             has_select_on_container_copy_construction<Alloc>, Alloc
>::type call_select_on_container_copy_construction(const Alloc& rhs)
     {
         return rhs;
     }
 
+ template <typename SizeType, typename Alloc>
+ SizeType call_max_size(const Alloc& a,
+ typename boost::enable_if<has_max_size<Alloc>, void*>::type = 0)
+ {
+ return a.max_size();
+ }
+
+ template <typename SizeType, typename Alloc>
+ SizeType call_max_size(const Alloc&,
+ typename boost::disable_if<has_max_size<Alloc>, void*>::type = 0)
+ {
+ return std::numeric_limits<SizeType>::max();
+ }
+
     template <typename Alloc>
     struct allocator_traits
     {
         typedef Alloc allocator_type;
         typedef typename Alloc::value_type value_type;
 
- typedef BOOST_DEFAULT_TYPE(Alloc, pointer, value_type*)
+ typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, pointer, value_type*)
             pointer;
 
         // For now always use the allocator's const_pointer.
 
- //typedef BOOST_DEFAULT_TYPE(Alloc, const_pointer,
- // BOOST_DEDUCED_TYPENAME pointer_traits<pointer>::
+ //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
+ // typename pointer_traits<pointer>::
         // BOOST_NESTED_TEMPLATE rebind<const value_type>::other)
         // const_pointer;
 
- typedef BOOST_DEFAULT_TYPE(Alloc, const_pointer, value_type const*)
- const_pointer;
+ typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
+ value_type const*) const_pointer;
 
         // I'm not using void pointers for now.
 
- //typedef BOOST_DEFAULT_TYPE(Alloc, void_pointer,
+ //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, void_pointer,
         // BOOST_NESTED_TEMPLATE pointer_traits<pointer>::
         // BOOST_NESTED_TEMPLATE rebind<void>::other)
         // void_pointer;
 
- //typedef BOOST_DEFAULT_TYPE(Alloc, const_void_pointer,
- // BOOST_DEDUCED_TYPENAME pointer_traits<pointer>::
+ //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_void_pointer,
+ // typename pointer_traits<pointer>::
         // BOOST_NESTED_TEMPLATE rebind<const void>::other)
         // const_void_pointer;
 
- typedef BOOST_DEFAULT_TYPE(Alloc, difference_type, std::ptrdiff_t)
- difference_type;
+ typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, difference_type,
+ std::ptrdiff_t) difference_type;
 
- typedef BOOST_DEFAULT_TYPE(Alloc, size_type, std::size_t)
+ typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, size_type, std::size_t)
             size_type;
 
         // TODO: rebind_alloc and rebind_traits
@@ -249,32 +328,49 @@
 
         // I never use this, so I'll just comment it out for now.
         //
- //static pointer allocate(Alloc& a, size_type n, const_void_pointer hint)
+ //static pointer allocate(Alloc& a, size_type n,
+ // const_void_pointer hint)
         // { return DEFAULT_FUNC(allocate, pointer)(a, n, hint); }
     
         static void deallocate(Alloc& a, pointer p, size_type n)
             { a.deallocate(p, n); }
 
- // Only support the basic copy constructor
+ public:
 
- // template <typename T, typename... Args>
- // static void construct(Alloc& a, T* p, Args&&... args) {
- // DEFAULT_FUNC(construct,void)(a, p, std::forward<Args>(args)...);
- // }
+ // Only supporting the basic copy constructor for now.
 
         template <typename T>
- static void construct(Alloc& a, T* p, T const& x) {
+ static void construct(Alloc& a, T* p, T const& x, typename
+ boost::enable_if<has_construct<Alloc, T>, void*>::type = 0)
+ {
             a.construct(p, x);
         }
 
         template <typename T>
- static void destroy(Alloc& a, T* p) {
- // DEFAULT_FUNC(destroy,void)(a, p);
+ static void construct(Alloc&, T* p, T const& x, typename
+ boost::disable_if<has_construct<Alloc, T>, void*>::type = 0)
+ {
+ new ((void*) p) T(x);
+ }
+
+ template <typename T>
+ static void destroy(Alloc& a, T* p, typename
+ boost::enable_if<has_destroy<Alloc, T>, void*>::type = 0)
+ {
             a.destroy(p);
         }
 
+ template <typename T>
+ static void destroy(Alloc&, T* p, typename
+ boost::disable_if<has_destroy<Alloc, T>, void*>::type = 0)
+ {
+ p->~T();
+ }
+
         static size_type max_size(const Alloc& a)
- { return a.max_size(); }
+ {
+ return boost::unordered::detail::call_max_size<size_type>(a);
+ }
 
         // Allocator propagation on construction
         
@@ -286,13 +382,13 @@
     
         // Allocator propagation on assignment and swap.
         // Return true if lhs is modified.
- typedef BOOST_DEFAULT_TYPE(
+ typedef BOOST_UNORDERED_DEFAULT_TYPE(
             Alloc, propagate_on_container_copy_assignment, false_type)
             propagate_on_container_copy_assignment;
- typedef BOOST_DEFAULT_TYPE(
+ typedef BOOST_UNORDERED_DEFAULT_TYPE(
             Alloc,propagate_on_container_move_assignment, false_type)
             propagate_on_container_move_assignment;
- typedef BOOST_DEFAULT_TYPE(
+ typedef BOOST_UNORDERED_DEFAULT_TYPE(
             Alloc,propagate_on_container_swap,false_type)
             propagate_on_container_swap;
     };
@@ -307,7 +403,7 @@
     template <typename Allocator>
     struct allocator_array_constructor
     {
- typedef BOOST_DEDUCED_TYPENAME allocator_traits<Allocator>::pointer
+ typedef typename allocator_traits<Allocator>::pointer
             pointer;
 
         Allocator& alloc_;

Modified: branches/release/boost/unordered/detail/buckets.hpp
==============================================================================
--- branches/release/boost/unordered/detail/buckets.hpp (original)
+++ branches/release/boost/unordered/detail/buckets.hpp 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -41,7 +41,7 @@
     public:
         // Types
 
- typedef BOOST_DEDUCED_TYPENAME ::boost::detail::if_true<Unique>::
+ typedef typename ::boost::detail::if_true<Unique>::
             BOOST_NESTED_TEMPLATE then<
                 ::boost::unordered::detail::ungrouped_node<A>,
                 ::boost::unordered::detail::grouped_node<A>
@@ -49,16 +49,15 @@
 
         typedef A value_allocator;
         typedef ::boost::unordered::detail::bucket<A> bucket;
- typedef BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type value_type;
+ typedef typename allocator_traits<A>::value_type value_type;
 
- typedef BOOST_DEDUCED_TYPENAME bucket::bucket_allocator
- bucket_allocator;
- typedef BOOST_DEDUCED_TYPENAME allocator_traits<bucket_allocator>::pointer bucket_ptr;
- typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
+ typedef typename bucket::bucket_allocator bucket_allocator;
+ typedef typename allocator_traits<bucket_allocator>::pointer bucket_ptr;
+ typedef typename bucket::node_ptr node_ptr;
 
- typedef BOOST_DEDUCED_TYPENAME rebind_wrap<value_allocator, node>::type
+ typedef typename rebind_wrap<value_allocator, node>::type
             node_allocator;
- typedef BOOST_DEDUCED_TYPENAME allocator_traits<node_allocator>::pointer real_node_ptr;
+ typedef typename allocator_traits<node_allocator>::pointer real_node_ptr;
 
         // Members
 
@@ -423,7 +422,7 @@
         functions& operator=(functions const&);
 
         typedef compressed_pair<H, P> function_pair;
- typedef BOOST_DEDUCED_TYPENAME ::boost::aligned_storage<
+ typedef typename ::boost::aligned_storage<
             sizeof(function_pair),
             ::boost::alignment_of<function_pair>::value>::type aligned_function;
 
@@ -515,28 +514,130 @@
     };
 
     ////////////////////////////////////////////////////////////////////////////
- // Node Constructors
+ //
+ // Value Construction
 
- template <typename T, typename Arg1 = void>
- struct emulated_pair_constructor
- {
- enum { value = false };
- };
-
- template <typename A, typename B>
- struct emulated_pair_constructor<std::pair<A, B>, void>
- {
- enum { value = true };
- };
-
- template <typename A, typename B, typename Value>
- struct emulated_pair_constructor<std::pair<A, B>, Value>
- {
+#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_TRAILING_PARAMS_Z(z, n, typename Arg)>\
+ void construct_from_tuple(T* ptr, \
+ namespace_::tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, Arg)> 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)
+
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost)
+
+#if !defined(BOOST_NO_0X_HDR_TUPLE)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std)
+#elif defined(BOOST_HAS_TR1_TUPLE)
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::tr1)
+#endif
+
+#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
+ template <typename A, typename B, typename Arg1>
+ struct emulation1 {
         static choice1::type check(choice1, std::pair<A, B> const&);
         static choice2::type check(choice2, A const&);
-
- enum { value = sizeof(check(choose(), make<Value>())) - 1 };
+
+ enum { value = sizeof(check(choose(), make<Arg1>())) == sizeof(choice2::type) };
+ };
+#endif
+
+#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
+ template <typename A, typename B, typename Arg1>
+ struct check3_base {
+ static choice1::type check(choice1, boost::unordered::piecewise_construct_t);
+ static choice2::type check(choice2, A const&);
+ static choice3::type check(choice3, ...);
+ };
+#else
+ template <typename A, typename B, typename Arg1>
+ struct check3_base {
+ static choice1::type check(choice1, boost::unordered::piecewise_construct_t);
+ static choice3::type check(choice3, ...);
     };
+#endif
+
+ template <typename A, typename B, typename Arg1>
+ struct piecewise3 {
+ enum { value =
+ sizeof(check3_base<A,B,Arg1>::check(choose(), make<Arg1>())) ==
+ sizeof(choice1::type) };
+ };
+
+ template <typename A, typename B, typename Arg1>
+ struct emulation3 {
+ enum { value =
+ sizeof(check3_base<A,B,Arg1>::check(choose(), make<Arg1>())) ==
+ sizeof(choice2::type) };
+ };
+
+ template <typename A, typename B, typename Arg1>
+ struct normal3 {
+ enum { value =
+ sizeof(check3_base<A,B,Arg1>::check(choose(), make<Arg1>())) ==
+ sizeof(choice3::type) };
+ };
+
+ template <typename T, typename Arg1>
+ struct pair_construct1 {};
+ template <typename T, typename Arg1>
+ struct normal_construct1 { typedef void type; };
+
+#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
+ template <typename A, typename B, typename Arg1>
+ struct pair_construct1<std::pair<A, B>, Arg1>
+ : enable_if<emulation1<A, B, Arg1>, void> {};
+
+ template <typename A, typename B, typename Arg1>
+ struct normal_construct1<std::pair<A, B>, Arg1>
+ : disable_if<emulation1<A, B, Arg1>, void> {};
+#endif
+
+ template <typename T, typename Arg1>
+ struct piecewise_construct3 {};
+ template <typename A, typename B, typename Arg1>
+ struct piecewise_construct3<std::pair<A, B>, Arg1>
+ : enable_if<piecewise3<A, B, Arg1>, void> {};
+
+ template <typename T, typename Arg1>
+ struct pair_construct3 {};
+ template <typename A, typename B, typename Arg1>
+ struct pair_construct3<std::pair<A, B>, Arg1>
+ : enable_if<emulation3<A, B, Arg1>, void> {};
+
+ template <typename T, typename Arg1>
+ struct normal_construct3 { typedef void type; };
+ template <typename A, typename B, typename Arg1>
+ struct normal_construct3<std::pair<A, B>, Arg1>
+ : enable_if<normal3<A, B, Arg1>, void> {};
+
+ template <typename T>
+ struct pair_construct_n {};
+ template <typename T>
+ struct normal_construct_n { typedef void type; };
+
+#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
+ template <typename A, typename B>
+ struct pair_construct_n<std::pair<A, B> > { typedef void type; };
+ template <typename A, typename B>
+ struct normal_construct_n<std::pair<A, B> > {};
+#endif
 
     template <class T>
     inline void construct_impl(void* address)
@@ -544,110 +645,135 @@
         new(address) T();
     }
 
-#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
-
     template <class T, class Arg1>
- inline void construct_impl(
- typename boost::disable_if<emulated_pair_constructor<T, Arg1>,
- void*>::type address,
- Arg1&& a1)
+ inline typename normal_construct1<T, Arg1>::type
+ construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1)
     {
- new(address) T(std::forward<Arg1>(a1));
+ new(address) T(
+ boost::forward<Arg1>(arg1)
+ );
     }
 
     template <class T, class Arg1>
- inline void construct_impl(
- typename boost::enable_if<emulated_pair_constructor<T, Arg1>,
- void*>::type address,
- Arg1&& a1)
+ inline typename pair_construct1<T, Arg1>::type
+ construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1)
     {
- new(address) T(std::forward<Arg1>(a1), typename T::second_type());
- }
+ new((void*)(&static_cast<T*>(address)->first))
+ typename T::first_type(
+ boost::forward<Arg1>(arg1));
+ new((void*)(&static_cast<T*>(address)->second))
+ typename T::second_type();
+ }
 
     template <class T, class Arg1, class Arg2>
- inline void construct_impl(void* address, Arg1&& a1, Arg2&& a2)
+ inline void construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1,
+ BOOST_FWD_REF(Arg2) arg2)
     {
- new(address) T(std::forward<Arg1>(a1), std::forward<Arg2>(a2));
+ new(address) T(
+ boost::forward<Arg1>(arg1),
+ boost::forward<Arg2>(arg2));
     }
 
- template <class T, class Arg1, class Arg2, class... Args>
- inline typename boost::disable_if<emulated_pair_constructor<T>, void>::type
- construct_impl(void* address, Arg1&& arg1, Arg2&& arg2, Args&&... args)
+ template <class T, class Arg1, class Arg2, class Arg3>
+ inline typename piecewise_construct3<T, Arg1>::type
+ construct_impl(void* address, BOOST_FWD_REF(Arg1),
+ BOOST_FWD_REF(Arg2) arg2, BOOST_FWD_REF(Arg3) arg3)
     {
- new(address) T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
- std::forward<Args>(args)...);
+ construct_from_tuple(&static_cast<T*>(address)->first, arg2);
+ construct_from_tuple(&static_cast<T*>(address)->second, arg3);
     }
 
- template <class T, class Arg1, class Arg2, class... Args>
- inline typename boost::enable_if<emulated_pair_constructor<T>, void>::type
- construct_impl(void* address, Arg1&& arg1, Arg2&& arg2, Args&&... args)
- {
- new(address) T(std::forward<Arg1>(arg1),
- typename T::second_type(
- std::forward<Arg2>(arg2), std::forward<Args>(args)...));
+ template <class T, class Arg1, class Arg2, class Arg3>
+ inline typename pair_construct3<T, Arg1>::type
+ construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1,
+ BOOST_FWD_REF(Arg2) arg2, BOOST_FWD_REF(Arg3) arg3)
+ {
+ new((void*)(&static_cast<T*>(address)->first))
+ typename T::first_type(
+ boost::forward<Arg1>(arg1));
+ new((void*)(&static_cast<T*>(address)->second))
+ typename T::second_type(
+ boost::forward<Arg2>(arg2),
+ boost::forward<Arg3>(arg3));
     }
 
-#else
-
- template <class T, class Arg1>
- inline BOOST_DEDUCED_TYPENAME boost::disable_if<emulated_pair_constructor<T, Arg1>, void>::type
- construct_impl(void* address, BOOST_FWD_REF(Arg1) a1)
+ template <class T, class Arg1, class Arg2, class Arg3>
+ inline typename normal_construct3<T, Arg1>::type
+ construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1,
+ BOOST_FWD_REF(Arg2) arg2, BOOST_FWD_REF(Arg3) arg3)
     {
- new(address) T(boost::forward<Arg1>(a1));
+ new(address) T(
+ boost::forward<Arg1>(arg1),
+ boost::forward<Arg2>(arg2),
+ boost::forward<Arg3>(arg3));
     }
 
- template <class T, class Arg1>
- inline BOOST_DEDUCED_TYPENAME boost::enable_if<emulated_pair_constructor<T, Arg1>, void>::type
- construct_impl(void* address, BOOST_FWD_REF(Arg1) a1)
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+
+ template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class... Args>
+ inline typename normal_construct_n<T>::type
+ construct_impl(void* address, Arg1&& arg1, Arg2&& arg2, Arg3&& arg3,
+ Arg4&& arg4, Args&&... args)
     {
         new(address) T(
- boost::forward<Arg1>(a1),
- BOOST_DEDUCED_TYPENAME T::second_type()
- );
+ std::forward<Arg1>(arg1),
+ std::forward<Arg2>(arg2),
+ std::forward<Arg3>(arg3),
+ std::forward<Arg4>(arg4),
+ std::forward<Args>(args)...);
     }
 
- template <class T, class Arg1, class Arg2>
- inline void construct_impl(void* address,
- BOOST_FWD_REF(Arg1) a1, BOOST_FWD_REF(Arg2) a2)
- {
- new(address) T(boost::forward<Arg1>(a1), boost::forward<Arg2>(a2));
+ template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class... Args>
+ inline typename pair_construct_n<T>::type
+ construct_impl(void* address, Arg1&& arg1, Arg2&& arg2, Arg3&& arg3,
+ Arg4&& arg4, Args&&... args)
+ {
+ new((void*)(&static_cast<T*>(address)->first))
+ typename T::first_type(
+ std::forward<Arg1>(arg1));
+ new((void*)(&static_cast<T*>(address)->second))
+ typename T::second_type(
+ std::forward<Arg2>(arg2),
+ std::forward<Arg3>(arg3),
+ std::forward<Arg4>(arg4),
+ std::forward<Args>(args)...);
     }
-
+
+#else
+
 #define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
     template < \
         class T, \
         BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
> \
- inline void construct_impl( \
- BOOST_DEDUCED_TYPENAME \
- boost::disable_if<emulated_pair_constructor<T>, void*>::type \
- address, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
- ) \
+ inline typename normal_construct_n<T>::type \
+ construct_impl(void* address, \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
     { \
         new(address) T( \
             BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
     }
 
- BOOST_PP_REPEAT_FROM_TO(3, BOOST_UNORDERED_EMPLACE_LIMIT,
+ BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
         BOOST_UNORDERED_CONSTRUCT_IMPL, _)
 
 #define BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(z, num_params, _) \
     template <class T, class Key, \
         BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
> \
- inline void construct_impl( \
- BOOST_DEDUCED_TYPENAME \
- boost::enable_if<emulated_pair_constructor<T>, void*>::type \
- address, \
- Key const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
+ inline typename pair_construct_n<T>::type \
+ construct_impl(void* address, BOOST_FWD_REF(Key) key, \
+ BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
     { \
- new(address) T(k, \
- BOOST_DEDUCED_TYPENAME \
- T::second_type(BOOST_UNORDERED_CALL_PARAMS(z, num_params))); \
+ new((void*)(&static_cast<T*>(address)->first)) \
+ typename T::first_type( \
+ boost::forward<Key>(key)); \
+ new((void*)(&static_cast<T*>(address)->second)) \
+ typename T::second_type( \
+ BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
     }
 
- BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT,
+ BOOST_PP_REPEAT_FROM_TO(3, BOOST_UNORDERED_EMPLACE_LIMIT,
         BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL, _)
 
 #undef BOOST_UNORDERED_CONSTRUCT_IMPL
@@ -661,10 +787,10 @@
     class node_constructor
     {
         typedef ::boost::unordered::detail::buckets<Alloc, Unique> buckets;
- typedef BOOST_DEDUCED_TYPENAME buckets::node node;
- typedef BOOST_DEDUCED_TYPENAME buckets::real_node_ptr real_node_ptr;
- typedef BOOST_DEDUCED_TYPENAME buckets::value_type value_type;
- typedef BOOST_DEDUCED_TYPENAME buckets::node_allocator node_allocator;
+ typedef typename buckets::node node;
+ typedef typename buckets::real_node_ptr real_node_ptr;
+ typedef typename buckets::value_type value_type;
+ typedef typename buckets::node_allocator node_allocator;
 
         buckets& buckets_;
         real_node_ptr node_;
@@ -731,7 +857,7 @@
         }
 
         // no throw
- BOOST_DEDUCED_TYPENAME buckets::node_ptr release()
+ typename buckets::node_ptr release()
         {
             real_node_ptr p = node_;
             node_ = real_node_ptr();

Modified: branches/release/boost/unordered/detail/equivalent.hpp
==============================================================================
--- branches/release/boost/unordered/detail/equivalent.hpp (original)
+++ branches/release/boost/unordered/detail/equivalent.hpp 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -15,19 +15,19 @@
     class equivalent_table : public T::table_base
     {
     public:
- typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
- typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
- typedef BOOST_DEDUCED_TYPENAME T::value_allocator value_allocator;
- typedef BOOST_DEDUCED_TYPENAME T::key_type key_type;
- typedef BOOST_DEDUCED_TYPENAME T::value_type value_type;
- typedef BOOST_DEDUCED_TYPENAME T::table_base table_base;
- typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor;
- typedef BOOST_DEDUCED_TYPENAME T::node_allocator node_allocator;
-
- typedef BOOST_DEDUCED_TYPENAME T::node node;
- typedef BOOST_DEDUCED_TYPENAME T::node_ptr node_ptr;
- typedef BOOST_DEDUCED_TYPENAME T::bucket_ptr bucket_ptr;
- typedef BOOST_DEDUCED_TYPENAME T::extractor extractor;
+ typedef typename T::hasher hasher;
+ typedef typename T::key_equal key_equal;
+ typedef typename T::value_allocator value_allocator;
+ typedef typename T::key_type key_type;
+ typedef typename T::value_type value_type;
+ typedef typename T::table_base table_base;
+ typedef typename T::node_constructor node_constructor;
+ typedef typename T::node_allocator node_allocator;
+
+ typedef typename T::node node;
+ typedef typename T::node_ptr node_ptr;
+ typedef typename T::bucket_ptr bucket_ptr;
+ typedef typename T::extractor extractor;
 
         // Constructors
 
@@ -67,7 +67,9 @@
     
             return true;
         }
-
+
+#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
+
         static bool group_equals(node_ptr n1, node_ptr end1,
                 node_ptr n2, node_ptr end2)
         {
@@ -108,7 +110,28 @@
             
             return true;
         }
-
+
+#else
+
+ static bool group_equals(node_ptr n1, node_ptr end1,
+ node_ptr n2, node_ptr end2)
+ {
+ for(;;)
+ {
+ if(!extractor::compare_mapped(
+ node::get_value(n1), node::get_value(n2)))
+ return false;
+
+ n1 = n1->next_;
+ n2 = n2->next_;
+
+ if (n1 == end1) return n2 == end2;
+ if (n2 == end2) return false;
+ }
+ }
+
+#endif
+
         static bool find(node_ptr n, node_ptr end, value_type const& v)
         {
             for(;n != end; n = n->next_)
@@ -203,6 +226,14 @@
                 this->find_node(bucket_index, hash, k));
         }
 
+#if defined(BOOST_NO_RVALUE_REFERENCES)
+ node_ptr emplace(please_ignore_this_overload const&)
+ {
+ BOOST_ASSERT(false);
+ return this->begin();
+ }
+#endif
+
 #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
 
         template <class... Args>
@@ -273,19 +304,18 @@
         template <class I>
         void insert_range(I i, I j)
         {
- BOOST_DEDUCED_TYPENAME ::boost::iterator_traversal<I>::type
- iterator_traversal_tag;
- insert_for_range(i, j, iterator_traversal_tag);
+ insert_for_range(i, j,
+ BOOST_DEDUCED_TYPENAME ::boost::iterator_traversal<I>::type());
         }
 
     };
 
     template <class H, class P, class A>
     struct multiset : public types<
- BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
- BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
+ typename allocator_traits<A>::value_type,
+ typename allocator_traits<A>::value_type,
         H, P, A,
- set_extractor<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>,
+ set_extractor<typename allocator_traits<A>::value_type>,
         false>
     {
         typedef equivalent_table<multiset<H, P, A> > impl;
@@ -294,9 +324,9 @@
 
     template <class K, class H, class P, class A>
     struct multimap : public types<
- K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
+ K, typename allocator_traits<A>::value_type,
         H, P, A,
- map_extractor<K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>,
+ map_extractor<K, typename allocator_traits<A>::value_type>,
         false>
     {
         typedef equivalent_table<multimap<K, H, P, A> > impl;

Modified: branches/release/boost/unordered/detail/extract_key.hpp
==============================================================================
--- branches/release/boost/unordered/detail/extract_key.hpp (original)
+++ branches/release/boost/unordered/detail/extract_key.hpp 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -27,6 +27,18 @@
         template <class T> no_key(T const&) {}
     };
 
+ template <typename Key, typename T>
+ struct is_key {
+ template <typename T2>
+ static choice1::type test(T2 const&);
+ static choice2::type test(Key const&);
+
+ enum { value = sizeof(test(make<T>())) == sizeof(choice2::type) };
+
+ typedef typename boost::detail::if_true<value>::
+ BOOST_NESTED_TEMPLATE then<Key const&, no_key>::type type;
+ };
+
     template <class ValueType>
     struct set_extractor
     {
@@ -64,8 +76,8 @@
             return no_key();
         }
 
- template <class Arg>
- static no_key extract(Arg const&, Arg const&)
+ template <class Arg1, class Arg2>
+ static no_key extract(Arg1 const&, Arg2 const&)
         {
             return no_key();
         }
@@ -81,7 +93,7 @@
     struct map_extractor
     {
         typedef ValueType value_type;
- typedef BOOST_DEDUCED_TYPENAME ::boost::remove_const<Key>::type key_type;
+ typedef typename ::boost::remove_const<Key>::type key_type;
 
         static key_type const& extract(value_type const& v)
         {
@@ -127,6 +139,7 @@
             return no_key();
         }
 #else
+
         template <class Arg1>
         static key_type const& extract(key_type const& k, Arg1 const&)
         {
@@ -151,6 +164,54 @@
         }
 #endif
 
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+
+#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
+ template <typename T2> \
+ static no_key extract(boost::unordered::piecewise_construct_t, \
+ namespace_::tuple<> const&, T2&&) \
+ { \
+ return no_key(); \
+ } \
+ \
+ template <typename T, typename T2> \
+ static typename is_key<key_type, T>::type \
+ extract(boost::unordered::piecewise_construct_t, \
+ namespace_::tuple<T> const& k, T2&&) \
+ { \
+ return typename is_key<key_type, T>::type( \
+ namespace_::get<0>(k)); \
+ }
+
+#else
+
+#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
+ static no_key extract(boost::unordered::piecewise_construct_t, \
+ namespace_::tuple<> const&) \
+ { \
+ return no_key(); \
+ } \
+ \
+ template <typename T> \
+ static typename is_key<key_type, T>::type \
+ extract(boost::unordered::piecewise_construct_t, \
+ namespace_::tuple<T> const& k) \
+ { \
+ return typename is_key<key_type, T>::type( \
+ namespace_::get<0>(k)); \
+ }
+
+#endif
+
+BOOST_UNORDERED_KEY_FROM_TUPLE(boost)
+
+#if !defined(BOOST_NO_0X_HDR_TUPLE)
+BOOST_UNORDERED_KEY_FROM_TUPLE(std)
+#elif defined(BOOST_HAS_TR1_TUPLE)
+BOOST_UNORDERED_KEY_FROM_TUPLE(std::tr1)
+#endif
+
+
         static bool compare_mapped(value_type const& x, value_type const& y)
         {
             return x.second == y.second;

Modified: branches/release/boost/unordered/detail/fwd.hpp
==============================================================================
--- branches/release/boost/unordered/detail/fwd.hpp (original)
+++ branches/release/boost/unordered/detail/fwd.hpp 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -44,6 +44,9 @@
         class P = std::equal_to<T>,
         class A = std::allocator<T> >
     class unordered_multiset;
+
+ struct piecewise_construct_t {};
+ const piecewise_construct_t piecewise_construct = piecewise_construct_t();
 }
 }
 

Modified: branches/release/boost/unordered/detail/node.hpp
==============================================================================
--- branches/release/boost/unordered/detail/node.hpp (original)
+++ branches/release/boost/unordered/detail/node.hpp 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -59,11 +59,9 @@
     {
         bucket& operator=(bucket const&);
     public:
- typedef BOOST_DEDUCED_TYPENAME
- ::boost::unordered::detail::rebind_wrap<A, bucket>::type
+ typedef typename ::boost::unordered::detail::rebind_wrap<A, bucket>::type
             bucket_allocator;
- typedef BOOST_DEDUCED_TYPENAME
- allocator_traits<bucket_allocator>::pointer bucket_ptr;
+ typedef typename allocator_traits<bucket_allocator>::pointer bucket_ptr;
         typedef bucket_ptr node_ptr;
     
         node_ptr next_;
@@ -77,7 +75,7 @@
     struct value_base
     {
         typedef ValueType value_type;
- BOOST_DEDUCED_TYPENAME ::boost::aligned_storage<
+ typename ::boost::aligned_storage<
             sizeof(value_type),
             ::boost::alignment_of<value_type>::value>::type data_;
 
@@ -107,12 +105,12 @@
     template <class A>
     struct ungrouped_node
       : ::boost::unordered::detail::bucket<A>,
- value_base<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>
+ value_base<typename allocator_traits<A>::value_type>
     {
         typedef ::boost::unordered::detail::bucket<A> bucket;
- typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
- typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
- typedef BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type value_type;
+ typedef typename bucket::bucket_ptr bucket_ptr;
+ typedef typename bucket::node_ptr node_ptr;
+ typedef typename allocator_traits<A>::value_type value_type;
 
         std::size_t hash_;
 
@@ -182,12 +180,12 @@
     template <class A>
     struct grouped_node
       : ::boost::unordered::detail::bucket<A>,
- value_base<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>
+ value_base<typename allocator_traits<A>::value_type>
     {
         typedef ::boost::unordered::detail::bucket<A> bucket;
- typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
- typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
- typedef BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type value_type;
+ typedef typename bucket::bucket_ptr bucket_ptr;
+ typedef typename bucket::node_ptr node_ptr;
+ typedef typename allocator_traits<A>::value_type value_type;
 
         std::size_t hash_;
         node_ptr group_prev_;

Modified: branches/release/boost/unordered/detail/table.hpp
==============================================================================
--- branches/release/boost/unordered/detail/table.hpp (original)
+++ branches/release/boost/unordered/detail/table.hpp 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -23,22 +23,22 @@
         table(table const&);
         table& operator=(table const&);
     public:
- typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
- typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
- typedef BOOST_DEDUCED_TYPENAME T::value_allocator value_allocator;
- typedef BOOST_DEDUCED_TYPENAME T::key_type key_type;
- typedef BOOST_DEDUCED_TYPENAME T::value_type value_type;
- typedef BOOST_DEDUCED_TYPENAME T::functions functions;
- typedef BOOST_DEDUCED_TYPENAME T::buckets buckets;
- typedef BOOST_DEDUCED_TYPENAME T::extractor extractor;
- typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor;
-
- typedef BOOST_DEDUCED_TYPENAME T::node node;
- typedef BOOST_DEDUCED_TYPENAME T::bucket bucket;
- typedef BOOST_DEDUCED_TYPENAME T::node_ptr node_ptr;
- typedef BOOST_DEDUCED_TYPENAME T::bucket_ptr bucket_ptr;
- typedef BOOST_DEDUCED_TYPENAME T::node_allocator node_allocator;
- typedef BOOST_DEDUCED_TYPENAME T::iterator_pair iterator_pair;
+ typedef typename T::hasher hasher;
+ typedef typename T::key_equal key_equal;
+ typedef typename T::value_allocator value_allocator;
+ typedef typename T::key_type key_type;
+ typedef typename T::value_type value_type;
+ typedef typename T::functions functions;
+ typedef typename T::buckets buckets;
+ typedef typename T::extractor extractor;
+ typedef typename T::node_constructor node_constructor;
+
+ typedef typename T::node node;
+ typedef typename T::bucket bucket;
+ typedef typename T::node_ptr node_ptr;
+ typedef typename T::bucket_ptr bucket_ptr;
+ typedef typename T::node_allocator node_allocator;
+ typedef typename T::iterator_pair iterator_pair;
 
         // Members
         
@@ -485,11 +485,11 @@
         typedef ::boost::unordered::detail::buckets<value_allocator, Unique> buckets;
         typedef ::boost::unordered::detail::functions<hasher, key_equal> functions;
 
- typedef BOOST_DEDUCED_TYPENAME buckets::node node;
- typedef BOOST_DEDUCED_TYPENAME buckets::bucket bucket;
- typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
- typedef BOOST_DEDUCED_TYPENAME buckets::bucket_ptr bucket_ptr;
- typedef BOOST_DEDUCED_TYPENAME buckets::node_allocator node_allocator;
+ typedef typename buckets::node node;
+ typedef typename buckets::bucket bucket;
+ typedef typename buckets::node_ptr node_ptr;
+ typedef typename buckets::bucket_ptr bucket_ptr;
+ typedef typename buckets::node_allocator node_allocator;
 
         typedef std::pair<node_ptr, node_ptr> iterator_pair;
     };
@@ -514,18 +514,18 @@
     class l_iterator
         : public ::boost::iterator <
             std::forward_iterator_tag,
- BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type,
+ typename boost::unordered::detail::allocator_traits<A>::value_type,
             std::ptrdiff_t,
- BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::pointer,
- BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type&>
+ typename boost::unordered::detail::allocator_traits<A>::pointer,
+ typename boost::unordered::detail::allocator_traits<A>::value_type&>
     {
     public:
- typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type value_type;
+ typedef typename boost::unordered::detail::allocator_traits<A>::value_type value_type;
 
     private:
         typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
- typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
- typedef BOOST_DEDUCED_TYPENAME buckets::node node;
+ typedef typename buckets::node_ptr node_ptr;
+ typedef typename buckets::node node;
         typedef cl_iterator<A, Unique> const_local_iterator;
 
         friend class cl_iterator<A, Unique>;
@@ -538,7 +538,7 @@
         l_iterator() : ptr_() {}
         l_iterator(node_ptr x, std::size_t b, std::size_t c)
             : ptr_(x), bucket_(b), bucket_count_(c) {}
- BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type& operator*() const {
+ typename boost::unordered::detail::allocator_traits<A>::value_type& operator*() const {
             return node::get_value(ptr_);
         }
         value_type* operator->() const {
@@ -575,18 +575,18 @@
     class cl_iterator
         : public ::boost::iterator <
             std::forward_iterator_tag,
- BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type,
+ typename boost::unordered::detail::allocator_traits<A>::value_type,
             std::ptrdiff_t,
- BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::const_pointer,
- BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type const& >
+ typename boost::unordered::detail::allocator_traits<A>::const_pointer,
+ typename boost::unordered::detail::allocator_traits<A>::value_type const& >
     {
     public:
- typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type value_type;
+ typedef typename boost::unordered::detail::allocator_traits<A>::value_type value_type;
 
     private:
         typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
- typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
- typedef BOOST_DEDUCED_TYPENAME buckets::node node;
+ typedef typename buckets::node_ptr node_ptr;
+ typedef typename buckets::node node;
         typedef l_iterator<A, Unique> local_iterator;
 
         friend class l_iterator<A, Unique>;
@@ -602,7 +602,7 @@
         cl_iterator(local_iterator x)
             : ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
         {}
- BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type const&
+ typename boost::unordered::detail::allocator_traits<A>::value_type const&
             operator*() const {
             return node::get_value(ptr_);
         }
@@ -640,18 +640,18 @@
     class iterator
         : public ::boost::iterator <
             std::forward_iterator_tag,
- BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type,
+ typename boost::unordered::detail::allocator_traits<A>::value_type,
             std::ptrdiff_t,
- BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::pointer,
- BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type& >
+ typename boost::unordered::detail::allocator_traits<A>::pointer,
+ typename boost::unordered::detail::allocator_traits<A>::value_type& >
     {
     public:
- typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type value_type;
+ typedef typename boost::unordered::detail::allocator_traits<A>::value_type value_type;
 
     private:
         typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
- typedef BOOST_DEDUCED_TYPENAME buckets::node node;
- typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
+ typedef typename buckets::node node;
+ typedef typename buckets::node_ptr node_ptr;
         typedef c_iterator<A, Unique> const_iterator;
         friend class c_iterator<A, Unique>;
         node_ptr node_;
@@ -660,7 +660,7 @@
 
         iterator() : node_() {}
         explicit iterator(node_ptr const& x) : node_(x) {}
- BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type& operator*() const {
+ typename boost::unordered::detail::allocator_traits<A>::value_type& operator*() const {
             return node::get_value(node_);
         }
         value_type* operator->() const {
@@ -690,18 +690,18 @@
     class c_iterator
         : public ::boost::iterator <
             std::forward_iterator_tag,
- BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type,
+ typename boost::unordered::detail::allocator_traits<A>::value_type,
             std::ptrdiff_t,
- BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::const_pointer,
- BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type const& >
+ typename boost::unordered::detail::allocator_traits<A>::const_pointer,
+ typename boost::unordered::detail::allocator_traits<A>::value_type const& >
     {
     public:
- typedef BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type value_type;
+ typedef typename boost::unordered::detail::allocator_traits<A>::value_type value_type;
 
     private:
         typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
- typedef BOOST_DEDUCED_TYPENAME buckets::node node;
- typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
+ typedef typename buckets::node node;
+ typedef typename buckets::node_ptr node_ptr;
         typedef ::boost::unordered::iterator_detail::iterator<A, Unique>
             iterator;
         friend class ::boost::unordered::iterator_detail::iterator<A, Unique>;
@@ -726,7 +726,7 @@
         c_iterator() : node_() {}
         explicit c_iterator(node_ptr const& x) : node_(x) {}
         c_iterator(iterator const& x) : node_(x.node_) {}
- BOOST_DEDUCED_TYPENAME boost::unordered::detail::allocator_traits<A>::value_type const& operator*() const {
+ typename boost::unordered::detail::allocator_traits<A>::value_type const& operator*() const {
             return node::get_value(node_);
         }
         value_type const* operator->() const {

Modified: branches/release/boost/unordered/detail/unique.hpp
==============================================================================
--- branches/release/boost/unordered/detail/unique.hpp (original)
+++ branches/release/boost/unordered/detail/unique.hpp 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -15,19 +15,19 @@
     class unique_table : public T::table_base
     {
     public:
- typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
- typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
- typedef BOOST_DEDUCED_TYPENAME T::value_allocator value_allocator;
- typedef BOOST_DEDUCED_TYPENAME T::key_type key_type;
- typedef BOOST_DEDUCED_TYPENAME T::value_type value_type;
- typedef BOOST_DEDUCED_TYPENAME T::table_base table_base;
- typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor;
- typedef BOOST_DEDUCED_TYPENAME T::node_allocator node_allocator;
-
- typedef BOOST_DEDUCED_TYPENAME T::node node;
- typedef BOOST_DEDUCED_TYPENAME T::node_ptr node_ptr;
- typedef BOOST_DEDUCED_TYPENAME T::bucket_ptr bucket_ptr;
- typedef BOOST_DEDUCED_TYPENAME T::extractor extractor;
+ typedef typename T::hasher hasher;
+ typedef typename T::key_equal key_equal;
+ typedef typename T::value_allocator value_allocator;
+ typedef typename T::key_type key_type;
+ typedef typename T::value_type value_type;
+ typedef typename T::table_base table_base;
+ typedef typename T::node_constructor node_constructor;
+ typedef typename T::node_allocator node_allocator;
+
+ typedef typename T::node node;
+ typedef typename T::node_ptr node_ptr;
+ typedef typename T::bucket_ptr bucket_ptr;
+ typedef typename T::extractor extractor;
         
         typedef std::pair<node_ptr, bool> emplace_return;
 
@@ -60,8 +60,15 @@
                 n1; n1 = n1->next_)
             {
                 node_ptr n2 = other.find_matching_node(n1);
+
+#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
                 if(!n2 || node::get_value(n1) != node::get_value(n2))
                     return false;
+#else
+ if(!n2 || !extractor::compare_mapped(
+ node::get_value(n1), node::get_value(n2)))
+ return false;
+#endif
             }
     
             return true;
@@ -111,7 +118,7 @@
 
         value_type& operator[](key_type const& k)
         {
- typedef BOOST_DEDUCED_TYPENAME value_type::second_type mapped_type;
+ typedef typename value_type::second_type mapped_type;
     
             std::size_t hash = this->hash_function()(k);
             std::size_t bucket_index = hash % this->bucket_count_;
@@ -189,6 +196,14 @@
         }
 
 
+#if defined(BOOST_NO_RVALUE_REFERENCES)
+ emplace_return emplace(please_ignore_this_overload const&)
+ {
+ BOOST_ASSERT(false);
+ return emplace_return(this->begin(), false);
+ }
+#endif
+
 #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
 
         template<class... Args>
@@ -392,10 +407,10 @@
 
     template <class H, class P, class A>
     struct set : public types<
- BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
- BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
+ typename allocator_traits<A>::value_type,
+ typename allocator_traits<A>::value_type,
         H, P, A,
- set_extractor<BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>,
+ set_extractor<typename allocator_traits<A>::value_type>,
         true>
     {
         typedef ::boost::unordered::detail::unique_table<set<H, P, A> > impl;
@@ -404,9 +419,9 @@
 
     template <class K, class H, class P, class A>
     struct map : public types<
- K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type,
+ K, typename allocator_traits<A>::value_type,
         H, P, A,
- map_extractor<K, BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type>,
+ map_extractor<K, typename allocator_traits<A>::value_type>,
         true>
     {
         typedef ::boost::unordered::detail::unique_table<map<K, H, P, A> > impl;

Modified: branches/release/boost/unordered/detail/util.hpp
==============================================================================
--- branches/release/boost/unordered/detail/util.hpp (original)
+++ branches/release/boost/unordered/detail/util.hpp 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -23,13 +23,23 @@
 #include <boost/type_traits/alignment_of.hpp>
 #include <boost/type_traits/remove_const.hpp>
 #include <boost/type_traits/is_empty.hpp>
+#if defined(BOOST_NO_RVALUE_REFERENCES)
+#include <boost/type_traits/is_class.hpp>
+#endif
 #include <boost/throw_exception.hpp>
-#include <boost/unordered/detail/allocator_helpers.hpp>
+#include <boost/move/move.hpp>
+#include <boost/swap.hpp>
 #include <boost/preprocessor/seq/size.hpp>
 #include <boost/preprocessor/seq/enum.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
 #include <boost/preprocessor/repetition/enum.hpp>
-#include <boost/move/move.hpp>
-#include <boost/swap.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+#include <boost/tuple/tuple.hpp>
+#if !defined(BOOST_NO_0X_HDR_TUPLE) || defined(BOOST_HAS_TR1_TUPLE)
+#include <tuple>
+#endif
+#include <boost/unordered/detail/allocator_helpers.hpp>
 
 // Template parameters:
 //
@@ -123,6 +133,36 @@
 #pragma warning(pop)
 #endif
 
+#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 <
+ rv_ref_impl<T>,
+ please_ignore_this_overload
+ >::type
+ {};
+
+#define BOOST_UNORDERED_RV_REF(T) \
+ typename ::boost::unordered::detail::rv_ref<T>::type
+
+#endif
+
     ////////////////////////////////////////////////////////////////////////////
     // convert double to std::size_t
 
@@ -198,22 +238,6 @@
     }
 
     ////////////////////////////////////////////////////////////////////////////
- // pair_cast - because some libraries don't have the full pair constructors.
-
-#if 0
- template <class Dst1, class Dst2, class Src1, class Src2>
- inline std::pair<Dst1, Dst2> pair_cast(std::pair<Src1, Src2> const& x)
- {
- return std::pair<Dst1, Dst2>(Dst1(x.first), Dst2(x.second));
- }
-
-#define BOOST_UNORDERED_PAIR_CAST(First, Last, Argument) \
- ::boost::unordered::detail::pair_cast<First, Last>(Argument)
-#else
-#define BOOST_UNORDERED_PAIR_CAST(First, Last, Argument) \
- Argument
-#endif
- ////////////////////////////////////////////////////////////////////////////
     // insert_size/initial_size
 
 #if !defined(BOOST_NO_STD_DISTANCE)
@@ -242,9 +266,8 @@
     template <class I>
     inline std::size_t insert_size(I i, I j)
     {
- BOOST_DEDUCED_TYPENAME ::boost::iterator_traversal<I>::type
- iterator_traversal_tag;
- return insert_size(i, j, iterator_traversal_tag);
+ return insert_size(i, j,
+ typename ::boost::iterator_traversal<I>::type());
     }
     
     template <class I>
@@ -295,8 +318,8 @@
       : private generate_base<T1, 1>::type,
         private generate_base<T2, 2>::type
     {
- typedef BOOST_DEDUCED_TYPENAME generate_base<T1, 1>::type base1;
- typedef BOOST_DEDUCED_TYPENAME generate_base<T2, 2>::type base2;
+ typedef typename generate_base<T1, 1>::type base1;
+ typedef typename generate_base<T2, 2>::type base2;
 
         typedef T1 first_type;
         typedef T2 second_type;

Modified: branches/release/boost/unordered/unordered_map.hpp
==============================================================================
--- branches/release/boost/unordered/unordered_map.hpp (original)
+++ branches/release/boost/unordered/unordered_map.hpp 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -52,24 +52,21 @@
     private:
 #endif
 
- typedef BOOST_DEDUCED_TYPENAME
- ::boost::unordered::detail::rebind_wrap<
+ typedef typename ::boost::unordered::detail::rebind_wrap<
                 allocator_type, value_type>::type
             value_allocator;
         typedef ::boost::unordered::detail::allocator_traits<value_allocator> allocator_traits;
 
         typedef ::boost::unordered::detail::map<K, H, P,
             value_allocator> types;
- typedef BOOST_DEDUCED_TYPENAME types::impl table;
+ typedef typename types::impl table;
 
- typedef BOOST_DEDUCED_TYPENAME types::node_ptr node_ptr;
+ typedef typename types::node_ptr node_ptr;
 
     public:
 
- typedef BOOST_DEDUCED_TYPENAME
- allocator_traits::pointer pointer;
- typedef BOOST_DEDUCED_TYPENAME
- allocator_traits::const_pointer const_pointer;
+ typedef typename allocator_traits::pointer pointer;
+ typedef typename allocator_traits::const_pointer const_pointer;
 
         typedef value_type& reference;
         typedef value_type const& const_reference;
@@ -135,9 +132,7 @@
 
         unordered_map(unordered_map const&);
 
-#if BOOST_UNORDERED_USE_RV_REF
- unordered_map& operator=(
- BOOST_RV_REF(unordered_map) x)
+ unordered_map& operator=(BOOST_RV_REF(unordered_map) x)
         {
             table_.move_assign(x.table_);
             return *this;
@@ -147,7 +142,6 @@
             : table_(other.table_, ::boost::unordered::detail::move_tag())
         {
         }
-#endif
 
 #if !defined(BOOST_NO_RVALUE_REFERENCES)
         unordered_map(unordered_map&&, allocator_type const&);
@@ -260,11 +254,10 @@
 #endif
 
         std::pair<iterator, bool> insert(value_type const&);
- iterator insert(const_iterator, value_type const&);
-#if BOOST_UNORDERED_USE_RV_REF
         std::pair<iterator, bool> insert(BOOST_RV_REF(value_type));
+ iterator insert(const_iterator, value_type const&);
         iterator insert(const_iterator, BOOST_RV_REF(value_type));
-#endif
+
         template <class InputIt> void insert(InputIt, InputIt);
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
@@ -403,8 +396,7 @@
     private:
 #endif
 
- typedef BOOST_DEDUCED_TYPENAME
- ::boost::unordered::detail::rebind_wrap<
+ typedef typename ::boost::unordered::detail::rebind_wrap<
                 allocator_type, value_type>::type
             value_allocator;
         typedef ::boost::unordered::detail::allocator_traits<value_allocator>
@@ -412,16 +404,14 @@
 
         typedef ::boost::unordered::detail::multimap<K, H, P,
             value_allocator> types;
- typedef BOOST_DEDUCED_TYPENAME types::impl table;
+ typedef typename types::impl table;
 
- typedef BOOST_DEDUCED_TYPENAME types::node_ptr node_ptr;
+ typedef typename types::node_ptr node_ptr;
 
     public:
 
- typedef BOOST_DEDUCED_TYPENAME
- allocator_traits::pointer pointer;
- typedef BOOST_DEDUCED_TYPENAME
- allocator_traits::const_pointer const_pointer;
+ typedef typename allocator_traits::pointer pointer;
+ typedef typename allocator_traits::const_pointer const_pointer;
 
         typedef value_type& reference;
         typedef value_type const& const_reference;
@@ -487,9 +477,7 @@
 
         unordered_multimap(unordered_multimap const&);
 
-#if BOOST_UNORDERED_USE_RV_REF
- unordered_multimap& operator=(
- BOOST_RV_REF(unordered_multimap) x)
+ unordered_multimap& operator=(BOOST_RV_REF(unordered_multimap) x)
         {
             table_.move_assign(x.table_);
             return *this;
@@ -499,7 +487,6 @@
             : table_(other.table_, ::boost::unordered::detail::move_tag())
         {
         }
-#endif
 
 #if !defined(BOOST_NO_RVALUE_REFERENCES)
         unordered_multimap(unordered_multimap&&, allocator_type const&);
@@ -612,11 +599,10 @@
 #endif
 
         iterator insert(value_type const&);
- iterator insert(const_iterator, value_type const&);
-#if BOOST_UNORDERED_USE_RV_REF
         iterator insert(BOOST_RV_REF(value_type));
+ iterator insert(const_iterator, value_type const&);
         iterator insert(const_iterator, BOOST_RV_REF(value_type));
-#endif
+
         template <class InputIt> void insert(InputIt, InputIt);
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
@@ -851,16 +837,15 @@
 #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
     template <class K, class T, class H, class P, class A>
     template <class... Args>
- std::pair<BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator, bool>
+ std::pair<typename unordered_map<K,T,H,P,A>::iterator, bool>
         unordered_map<K,T,H,P,A>::emplace(Args&&... args)
     {
- return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
- table_.emplace(std::forward<Args>(args)...));
+ return table_.emplace(std::forward<Args>(args)...);
     }
 
     template <class K, class T, class H, class P, class A>
     template <class... Args>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
+ typename unordered_map<K,T,H,P,A>::iterator
         unordered_map<K,T,H,P,A>::emplace_hint(const_iterator, Args&&... args)
     {
         return iterator(table_.emplace(std::forward<Args>(args)...).first);
@@ -869,18 +854,17 @@
 
 #if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
     template <class K, class T, class H, class P, class A>
- std::pair<BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator, bool>
+ std::pair<typename unordered_map<K,T,H,P,A>::iterator, bool>
         unordered_map<K,T,H,P,A>::emplace(
                 boost::unordered::detail::empty_emplace,
                 value_type v
             )
     {
- return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
- table_.emplace(boost::move(v)));
+ return table_.emplace(boost::move(v));
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
+ typename unordered_map<K,T,H,P,A>::iterator
         unordered_map<K,T,H,P,A>::emplace_hint(const_iterator,
                 boost::unordered::detail::empty_emplace,
                 value_type v
@@ -895,23 +879,18 @@
         template < \
             BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
- std::pair< \
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator, \
- bool> \
+ std::pair<typename unordered_map<K,T,H,P,A>::iterator, bool> \
             unordered_map<K,T,H,P,A>::emplace( \
                 BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
         { \
- return \
- BOOST_UNORDERED_PAIR_CAST(iterator, bool, \
- table_.emplace( \
- BOOST_UNORDERED_CALL_PARAMS(z, n))); \
+ return table_.emplace(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
         } \
                                                                             \
         template <class K, class T, class H, class P, class A> \
         template < \
             BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator \
+ typename unordered_map<K,T,H,P,A>::iterator \
             unordered_map<K,T,H,P,A>::emplace_hint( \
                 const_iterator, \
                 BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
@@ -929,38 +908,34 @@
 #endif
 
     template <class K, class T, class H, class P, class A>
- std::pair<BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator, bool>
+ std::pair<typename unordered_map<K,T,H,P,A>::iterator, bool>
         unordered_map<K,T,H,P,A>::insert(value_type const& obj)
     {
- return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
- table_.emplace(obj));
+ return table_.emplace(obj);
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
+ typename unordered_map<K,T,H,P,A>::iterator
         unordered_map<K,T,H,P,A>::insert(const_iterator,
                 value_type const& obj)
     {
         return iterator(table_.emplace(obj).first);
     }
 
-#if BOOST_UNORDERED_USE_RV_REF
     template <class K, class T, class H, class P, class A>
- std::pair<BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator, bool>
+ std::pair<typename unordered_map<K,T,H,P,A>::iterator, bool>
         unordered_map<K,T,H,P,A>::insert(BOOST_RV_REF(value_type) obj)
     {
- return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
- table_.emplace(boost::move(obj)));
+ return table_.emplace(boost::move(obj));
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
+ typename unordered_map<K,T,H,P,A>::iterator
         unordered_map<K,T,H,P,A>::insert(const_iterator,
                 BOOST_RV_REF(value_type) obj)
     {
         return iterator(table_.emplace(boost::move(obj)).first);
     }
-#endif
 
     template <class K, class T, class H, class P, class A>
     template <class InputIt>
@@ -979,21 +954,21 @@
 #endif
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
+ typename unordered_map<K,T,H,P,A>::iterator
         unordered_map<K,T,H,P,A>::erase(const_iterator position)
     {
         return iterator(table_.erase(position.node_));
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::size_type
+ typename unordered_map<K,T,H,P,A>::size_type
         unordered_map<K,T,H,P,A>::erase(const key_type& k)
     {
         return table_.erase_key(k);
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
+ typename unordered_map<K,T,H,P,A>::iterator
         unordered_map<K,T,H,P,A>::erase(
             const_iterator first, const_iterator last)
     {
@@ -1015,35 +990,35 @@
     // observers
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::hasher
+ typename unordered_map<K,T,H,P,A>::hasher
         unordered_map<K,T,H,P,A>::hash_function() const
     {
         return table_.hash_function();
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::key_equal
+ typename unordered_map<K,T,H,P,A>::key_equal
         unordered_map<K,T,H,P,A>::key_eq() const
     {
         return table_.key_eq();
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::mapped_type&
+ typename unordered_map<K,T,H,P,A>::mapped_type&
         unordered_map<K,T,H,P,A>::operator[](const key_type &k)
     {
         return table_[k].second;
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::mapped_type&
+ typename unordered_map<K,T,H,P,A>::mapped_type&
         unordered_map<K,T,H,P,A>::at(const key_type& k)
     {
         return table_.at(k).second;
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::mapped_type const&
+ typename unordered_map<K,T,H,P,A>::mapped_type const&
         unordered_map<K,T,H,P,A>::at(const key_type& k) const
     {
         return table_.at(k).second;
@@ -1052,14 +1027,14 @@
     // lookup
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
+ typename unordered_map<K,T,H,P,A>::iterator
         unordered_map<K,T,H,P,A>::find(const key_type& k)
     {
         return iterator(table_.find_node(k));
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::const_iterator
+ typename unordered_map<K,T,H,P,A>::const_iterator
         unordered_map<K,T,H,P,A>::find(const key_type& k) const
     {
         return const_iterator(table_.find_node(k));
@@ -1068,7 +1043,7 @@
     template <class K, class T, class H, class P, class A>
     template <class CompatibleKey, class CompatibleHash,
         class CompatiblePredicate>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator
+ typename unordered_map<K,T,H,P,A>::iterator
         unordered_map<K,T,H,P,A>::find(
             CompatibleKey const& k,
             CompatibleHash const& hash,
@@ -1080,7 +1055,7 @@
     template <class K, class T, class H, class P, class A>
     template <class CompatibleKey, class CompatibleHash,
         class CompatiblePredicate>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::const_iterator
+ typename unordered_map<K,T,H,P,A>::const_iterator
         unordered_map<K,T,H,P,A>::find(
             CompatibleKey const& k,
             CompatibleHash const& hash,
@@ -1090,7 +1065,7 @@
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::size_type
+ typename unordered_map<K,T,H,P,A>::size_type
         unordered_map<K,T,H,P,A>::count(const key_type& k) const
     {
         return table_.count(k);
@@ -1098,26 +1073,24 @@
 
     template <class K, class T, class H, class P, class A>
     std::pair<
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator,
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::iterator>
+ typename unordered_map<K,T,H,P,A>::iterator,
+ typename unordered_map<K,T,H,P,A>::iterator>
         unordered_map<K,T,H,P,A>::equal_range(const key_type& k)
     {
- return BOOST_UNORDERED_PAIR_CAST(iterator, iterator,
- table_.equal_range(k));
+ return table_.equal_range(k);
     }
 
     template <class K, class T, class H, class P, class A>
     std::pair<
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::const_iterator,
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::const_iterator>
+ typename unordered_map<K,T,H,P,A>::const_iterator,
+ typename unordered_map<K,T,H,P,A>::const_iterator>
         unordered_map<K,T,H,P,A>::equal_range(const key_type& k) const
     {
- return BOOST_UNORDERED_PAIR_CAST(const_iterator, const_iterator,
- table_.equal_range(k));
+ return table_.equal_range(k);
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_map<K,T,H,P,A>::size_type
+ typename unordered_map<K,T,H,P,A>::size_type
         unordered_map<K,T,H,P,A>::bucket_size(size_type n) const
     {
         return table_.bucket_size(n);
@@ -1293,7 +1266,7 @@
 
     template <class K, class T, class H, class P, class A>
     template <class... Args>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+ typename unordered_multimap<K,T,H,P,A>::iterator
         unordered_multimap<K,T,H,P,A>::emplace(Args&&... args)
     {
         return iterator(table_.emplace(std::forward<Args>(args)...));
@@ -1301,7 +1274,7 @@
 
     template <class K, class T, class H, class P, class A>
     template <class... Args>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+ typename unordered_multimap<K,T,H,P,A>::iterator
         unordered_multimap<K,T,H,P,A>::emplace_hint(
             const_iterator, Args&&... args)
     {
@@ -1312,7 +1285,7 @@
 
 #if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+ typename unordered_multimap<K,T,H,P,A>::iterator
         unordered_multimap<K,T,H,P,A>::emplace(
                 boost::unordered::detail::empty_emplace,
                 value_type v
@@ -1322,7 +1295,7 @@
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+ typename unordered_multimap<K,T,H,P,A>::iterator
         unordered_multimap<K,T,H,P,A>::emplace_hint(const_iterator,
                 boost::unordered::detail::empty_emplace,
                 value_type v
@@ -1337,7 +1310,7 @@
         template < \
             BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator \
+ typename unordered_multimap<K,T,H,P,A>::iterator \
             unordered_multimap<K,T,H,P,A>::emplace( \
                 BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
         { \
@@ -1349,7 +1322,7 @@
         template < \
             BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator \
+ typename unordered_multimap<K,T,H,P,A>::iterator \
             unordered_multimap<K,T,H,P,A>::emplace_hint( \
                 const_iterator, \
                 BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
@@ -1366,36 +1339,34 @@
 #endif
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+ typename unordered_multimap<K,T,H,P,A>::iterator
         unordered_multimap<K,T,H,P,A>::insert(value_type const& obj)
     {
         return iterator(table_.emplace(obj));
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+ typename unordered_multimap<K,T,H,P,A>::iterator
         unordered_multimap<K,T,H,P,A>::insert(
             const_iterator, value_type const& obj)
     {
         return iterator(table_.emplace(obj));
     }
 
-#if BOOST_UNORDERED_USE_RV_REF
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+ typename unordered_multimap<K,T,H,P,A>::iterator
         unordered_multimap<K,T,H,P,A>::insert(BOOST_RV_REF(value_type) obj)
     {
         return iterator(table_.emplace(boost::move(obj)));
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+ typename unordered_multimap<K,T,H,P,A>::iterator
         unordered_multimap<K,T,H,P,A>::insert(
             const_iterator, BOOST_RV_REF(value_type) obj)
     {
         return iterator(table_.emplace(boost::move(obj)));
     }
-#endif
 
     template <class K, class T, class H, class P, class A>
     template <class InputIt>
@@ -1414,21 +1385,21 @@
 #endif
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+ typename unordered_multimap<K,T,H,P,A>::iterator
         unordered_multimap<K,T,H,P,A>::erase(const_iterator position)
     {
         return iterator(table_.erase(position.node_));
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::size_type
+ typename unordered_multimap<K,T,H,P,A>::size_type
         unordered_multimap<K,T,H,P,A>::erase(const key_type& k)
     {
         return table_.erase_key(k);
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+ typename unordered_multimap<K,T,H,P,A>::iterator
         unordered_multimap<K,T,H,P,A>::erase(
             const_iterator first, const_iterator last)
     {
@@ -1450,14 +1421,14 @@
     // observers
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::hasher
+ typename unordered_multimap<K,T,H,P,A>::hasher
         unordered_multimap<K,T,H,P,A>::hash_function() const
     {
         return table_.hash_function();
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::key_equal
+ typename unordered_multimap<K,T,H,P,A>::key_equal
         unordered_multimap<K,T,H,P,A>::key_eq() const
     {
         return table_.key_eq();
@@ -1466,14 +1437,14 @@
     // lookup
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+ typename unordered_multimap<K,T,H,P,A>::iterator
         unordered_multimap<K,T,H,P,A>::find(const key_type& k)
     {
         return iterator(table_.find_node(k));
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::const_iterator
+ typename unordered_multimap<K,T,H,P,A>::const_iterator
         unordered_multimap<K,T,H,P,A>::find(const key_type& k) const
     {
         return const_iterator(table_.find_node(k));
@@ -1482,7 +1453,7 @@
     template <class K, class T, class H, class P, class A>
     template <class CompatibleKey, class CompatibleHash,
         class CompatiblePredicate>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator
+ typename unordered_multimap<K,T,H,P,A>::iterator
         unordered_multimap<K,T,H,P,A>::find(
             CompatibleKey const& k,
             CompatibleHash const& hash,
@@ -1494,7 +1465,7 @@
     template <class K, class T, class H, class P, class A>
     template <class CompatibleKey, class CompatibleHash,
         class CompatiblePredicate>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::const_iterator
+ typename unordered_multimap<K,T,H,P,A>::const_iterator
         unordered_multimap<K,T,H,P,A>::find(
             CompatibleKey const& k,
             CompatibleHash const& hash,
@@ -1504,7 +1475,7 @@
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::size_type
+ typename unordered_multimap<K,T,H,P,A>::size_type
         unordered_multimap<K,T,H,P,A>::count(const key_type& k) const
     {
         return table_.count(k);
@@ -1512,26 +1483,24 @@
 
     template <class K, class T, class H, class P, class A>
     std::pair<
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator,
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::iterator>
+ typename unordered_multimap<K,T,H,P,A>::iterator,
+ typename unordered_multimap<K,T,H,P,A>::iterator>
         unordered_multimap<K,T,H,P,A>::equal_range(const key_type& k)
     {
- return BOOST_UNORDERED_PAIR_CAST(iterator, iterator,
- table_.equal_range(k));
+ return table_.equal_range(k);
     }
 
     template <class K, class T, class H, class P, class A>
     std::pair<
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::const_iterator,
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::const_iterator>
+ typename unordered_multimap<K,T,H,P,A>::const_iterator,
+ typename unordered_multimap<K,T,H,P,A>::const_iterator>
         unordered_multimap<K,T,H,P,A>::equal_range(const key_type& k) const
     {
- return BOOST_UNORDERED_PAIR_CAST(const_iterator, const_iterator,
- table_.equal_range(k));
+ return table_.equal_range(k);
     }
 
     template <class K, class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multimap<K,T,H,P,A>::size_type
+ typename unordered_multimap<K,T,H,P,A>::size_type
         unordered_multimap<K,T,H,P,A>::bucket_size(size_type n) const
     {
         return table_.bucket_size(n);

Modified: branches/release/boost/unordered/unordered_set.hpp
==============================================================================
--- branches/release/boost/unordered/unordered_set.hpp (original)
+++ branches/release/boost/unordered/unordered_set.hpp 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -52,8 +52,7 @@
     private:
 #endif
 
- typedef BOOST_DEDUCED_TYPENAME
- ::boost::unordered::detail::rebind_wrap<
+ typedef typename ::boost::unordered::detail::rebind_wrap<
                 allocator_type, value_type>::type
             value_allocator;
         typedef ::boost::unordered::detail::allocator_traits<value_allocator>
@@ -61,16 +60,14 @@
 
         typedef ::boost::unordered::detail::set<H, P,
             value_allocator> types;
- typedef BOOST_DEDUCED_TYPENAME types::impl table;
+ typedef typename types::impl table;
 
- typedef BOOST_DEDUCED_TYPENAME types::node_ptr node_ptr;
+ typedef typename types::node_ptr node_ptr;
 
     public:
 
- typedef BOOST_DEDUCED_TYPENAME
- allocator_traits::pointer pointer;
- typedef BOOST_DEDUCED_TYPENAME
- allocator_traits::const_pointer const_pointer;
+ typedef typename allocator_traits::pointer pointer;
+ typedef typename allocator_traits::const_pointer const_pointer;
 
         typedef value_type& reference;
         typedef value_type const& const_reference;
@@ -134,9 +131,7 @@
 
         unordered_set(unordered_set const&);
 
-#if BOOST_UNORDERED_USE_RV_REF
- unordered_set& operator=(
- BOOST_RV_REF(unordered_set) x)
+ unordered_set& operator=(BOOST_RV_REF(unordered_set) x)
         {
             table_.move_assign(x.table_);
             return *this;
@@ -146,7 +141,6 @@
             : table_(other.table_, ::boost::unordered::detail::move_tag())
         {
         }
-#endif
 
 #if !defined(BOOST_NO_RVALUE_REFERENCES)
         unordered_set(unordered_set&&, allocator_type const&);
@@ -257,11 +251,9 @@
 #endif
 
         std::pair<iterator, bool> insert(value_type const&);
+ std::pair<iterator, bool> insert(BOOST_UNORDERED_RV_REF(value_type));
         iterator insert(const_iterator, value_type const&);
-#if BOOST_UNORDERED_USE_RV_REF
- std::pair<iterator, bool> insert(BOOST_RV_REF(value_type));
- iterator insert(const_iterator, BOOST_RV_REF(value_type));
-#endif
+ iterator insert(const_iterator, BOOST_UNORDERED_RV_REF(value_type));
         template <class InputIt> void insert(InputIt, InputIt);
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
@@ -384,8 +376,7 @@
     private:
 #endif
 
- typedef BOOST_DEDUCED_TYPENAME
- ::boost::unordered::detail::rebind_wrap<
+ typedef typename ::boost::unordered::detail::rebind_wrap<
                 allocator_type, value_type>::type
             value_allocator;
         typedef ::boost::unordered::detail::allocator_traits<value_allocator>
@@ -393,16 +384,14 @@
 
         typedef ::boost::unordered::detail::multiset<H, P,
             value_allocator> types;
- typedef BOOST_DEDUCED_TYPENAME types::impl table;
+ typedef typename types::impl table;
 
- typedef BOOST_DEDUCED_TYPENAME types::node_ptr node_ptr;
+ typedef typename types::node_ptr node_ptr;
 
     public:
 
- typedef BOOST_DEDUCED_TYPENAME
- allocator_traits::pointer pointer;
- typedef BOOST_DEDUCED_TYPENAME
- allocator_traits::const_pointer const_pointer;
+ typedef typename allocator_traits::pointer pointer;
+ typedef typename allocator_traits::const_pointer const_pointer;
 
         typedef value_type& reference;
         typedef value_type const& const_reference;
@@ -466,9 +455,7 @@
 
         unordered_multiset(unordered_multiset const&);
 
-#if BOOST_UNORDERED_USE_RV_REF
- unordered_multiset& operator=(
- BOOST_RV_REF(unordered_multiset) x)
+ unordered_multiset& operator=(BOOST_RV_REF(unordered_multiset) x)
         {
             table_.move_assign(x.table_);
             return *this;
@@ -478,7 +465,6 @@
             : table_(other.table_, ::boost::unordered::detail::move_tag())
         {
         }
-#endif
 
 #if !defined(BOOST_NO_RVALUE_REFERENCES)
         unordered_multiset(unordered_multiset&&, allocator_type const&);
@@ -589,11 +575,10 @@
 #endif
 
         iterator insert(value_type const&);
+ iterator insert(BOOST_UNORDERED_RV_REF(value_type));
         iterator insert(const_iterator, value_type const&);
-#if BOOST_UNORDERED_USE_RV_REF
- iterator insert(BOOST_RV_REF(value_type));
- iterator insert(const_iterator, BOOST_RV_REF(value_type));
-#endif
+ iterator insert(const_iterator, BOOST_UNORDERED_RV_REF(value_type));
+
         template <class InputIt>
         void insert(InputIt, InputIt);
 
@@ -818,16 +803,15 @@
 #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
     template <class T, class H, class P, class A>
     template <class... Args>
- std::pair<BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator, bool>
+ std::pair<typename unordered_set<T,H,P,A>::iterator, bool>
         unordered_set<T,H,P,A>::emplace(Args&&... args)
     {
- return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
- table_.emplace(std::forward<Args>(args)...));
+ return table_.emplace(std::forward<Args>(args)...);
     }
 
     template <class T, class H, class P, class A>
     template <class... Args>
- BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
+ typename unordered_set<T,H,P,A>::iterator
         unordered_set<T,H,P,A>::emplace_hint(const_iterator, Args&&... args)
     {
         return iterator(table_.emplace(std::forward<Args>(args)...).first);
@@ -835,18 +819,17 @@
 #else
 
     template <class T, class H, class P, class A>
- std::pair<BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator, bool>
+ std::pair<typename unordered_set<T,H,P,A>::iterator, bool>
         unordered_set<T,H,P,A>::emplace(
                 boost::unordered::detail::empty_emplace,
                 value_type v
             )
     {
- return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
- table_.emplace(boost::move(v)));
+ return table_.emplace(boost::move(v));
     }
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
+ typename unordered_set<T,H,P,A>::iterator
         unordered_set<T,H,P,A>::emplace_hint(const_iterator,
                 boost::unordered::detail::empty_emplace,
                 value_type v
@@ -860,23 +843,18 @@
         template < \
             BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
- std::pair< \
- BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator, \
- bool> \
+ std::pair<typename unordered_set<T,H,P,A>::iterator, bool> \
             unordered_set<T,H,P,A>::emplace( \
                 BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
         { \
- return \
- BOOST_UNORDERED_PAIR_CAST(iterator, bool, \
- table_.emplace( \
- BOOST_UNORDERED_CALL_PARAMS(z, n))); \
+ return table_.emplace(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
         } \
                                                                             \
         template <class T, class H, class P, class A> \
         template < \
             BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
- BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator \
+ typename unordered_set<T,H,P,A>::iterator \
             unordered_set<T,H,P,A>::emplace_hint( \
                 const_iterator, \
                 BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
@@ -894,38 +872,34 @@
 #endif
 
     template <class T, class H, class P, class A>
- std::pair<BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator, bool>
+ std::pair<typename unordered_set<T,H,P,A>::iterator, bool>
         unordered_set<T,H,P,A>::insert(value_type const& obj)
     {
- return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
- table_.emplace(obj));
+ return table_.emplace(obj);
     }
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
+ typename unordered_set<T,H,P,A>::iterator
         unordered_set<T,H,P,A>::insert(const_iterator,
                 value_type const& obj)
     {
         return iterator(table_.emplace(obj).first);
     }
 
-#if BOOST_UNORDERED_USE_RV_REF
     template <class T, class H, class P, class A>
- std::pair<BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator, bool>
- unordered_set<T,H,P,A>::insert(BOOST_RV_REF(value_type) obj)
+ std::pair<typename unordered_set<T,H,P,A>::iterator, bool>
+ unordered_set<T,H,P,A>::insert(BOOST_UNORDERED_RV_REF(value_type) obj)
     {
- return BOOST_UNORDERED_PAIR_CAST(iterator, bool,
- table_.emplace(boost::move(obj)));
+ return table_.emplace(boost::move(obj));
     }
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
+ typename unordered_set<T,H,P,A>::iterator
         unordered_set<T,H,P,A>::insert(const_iterator,
- BOOST_RV_REF(value_type) obj)
+ BOOST_UNORDERED_RV_REF(value_type) obj)
     {
         return iterator(table_.emplace(boost::move(obj)).first);
     }
-#endif
 
     template <class T, class H, class P, class A>
     template <class InputIt>
@@ -943,21 +917,21 @@
 #endif
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
+ typename unordered_set<T,H,P,A>::iterator
         unordered_set<T,H,P,A>::erase(const_iterator position)
     {
         return iterator(table_.erase(position.node_));
     }
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::size_type
+ typename unordered_set<T,H,P,A>::size_type
         unordered_set<T,H,P,A>::erase(const key_type& k)
     {
         return table_.erase_key(k);
     }
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::iterator
+ typename unordered_set<T,H,P,A>::iterator
         unordered_set<T,H,P,A>::erase(const_iterator first, const_iterator last)
     {
         return iterator(table_.erase_range(first.node_, last.node_));
@@ -978,14 +952,14 @@
     // observers
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::hasher
+ typename unordered_set<T,H,P,A>::hasher
         unordered_set<T,H,P,A>::hash_function() const
     {
         return table_.hash_function();
     }
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::key_equal
+ typename unordered_set<T,H,P,A>::key_equal
         unordered_set<T,H,P,A>::key_eq() const
     {
         return table_.key_eq();
@@ -994,7 +968,7 @@
     // lookup
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::const_iterator
+ typename unordered_set<T,H,P,A>::const_iterator
         unordered_set<T,H,P,A>::find(const key_type& k) const
     {
         return const_iterator(table_.find_node(k));
@@ -1003,7 +977,7 @@
     template <class T, class H, class P, class A>
     template <class CompatibleKey, class CompatibleHash,
         class CompatiblePredicate>
- BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::const_iterator
+ typename unordered_set<T,H,P,A>::const_iterator
         unordered_set<T,H,P,A>::find(
             CompatibleKey const& k,
             CompatibleHash const& hash,
@@ -1013,7 +987,7 @@
     }
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::size_type
+ typename unordered_set<T,H,P,A>::size_type
         unordered_set<T,H,P,A>::count(const key_type& k) const
     {
         return table_.count(k);
@@ -1021,16 +995,15 @@
 
     template <class T, class H, class P, class A>
     std::pair<
- BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::const_iterator,
- BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::const_iterator>
+ typename unordered_set<T,H,P,A>::const_iterator,
+ typename unordered_set<T,H,P,A>::const_iterator>
         unordered_set<T,H,P,A>::equal_range(const key_type& k) const
     {
- return BOOST_UNORDERED_PAIR_CAST(const_iterator, const_iterator,
- table_.equal_range(k));
+ return table_.equal_range(k);
     }
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_set<T,H,P,A>::size_type
+ typename unordered_set<T,H,P,A>::size_type
         unordered_set<T,H,P,A>::bucket_size(size_type n) const
     {
         return table_.bucket_size(n);
@@ -1206,7 +1179,7 @@
 
     template <class T, class H, class P, class A>
     template <class... Args>
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+ typename unordered_multiset<T,H,P,A>::iterator
         unordered_multiset<T,H,P,A>::emplace(Args&&... args)
     {
         return iterator(table_.emplace(std::forward<Args>(args)...));
@@ -1214,7 +1187,7 @@
 
     template <class T, class H, class P, class A>
     template <class... Args>
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+ typename unordered_multiset<T,H,P,A>::iterator
         unordered_multiset<T,H,P,A>::emplace_hint(
             const_iterator, Args&&... args)
     {
@@ -1224,7 +1197,7 @@
 #else
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+ typename unordered_multiset<T,H,P,A>::iterator
         unordered_multiset<T,H,P,A>::emplace(
                 boost::unordered::detail::empty_emplace,
                 value_type v
@@ -1234,7 +1207,7 @@
     }
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+ typename unordered_multiset<T,H,P,A>::iterator
         unordered_multiset<T,H,P,A>::emplace_hint(const_iterator,
                 boost::unordered::detail::empty_emplace,
                 value_type v
@@ -1248,7 +1221,7 @@
         template < \
             BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator \
+ typename unordered_multiset<T,H,P,A>::iterator \
             unordered_multiset<T,H,P,A>::emplace( \
                 BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
         { \
@@ -1260,7 +1233,7 @@
         template < \
             BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
> \
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator \
+ typename unordered_multiset<T,H,P,A>::iterator \
             unordered_multiset<T,H,P,A>::emplace_hint( \
                 const_iterator, \
                 BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
@@ -1277,36 +1250,34 @@
 #endif
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+ typename unordered_multiset<T,H,P,A>::iterator
         unordered_multiset<T,H,P,A>::insert(value_type const& obj)
     {
         return iterator(table_.emplace(obj));
     }
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+ typename unordered_multiset<T,H,P,A>::iterator
         unordered_multiset<T,H,P,A>::insert(const_iterator,
                 value_type const& obj)
     {
         return iterator(table_.emplace(obj));
     }
 
-#if BOOST_UNORDERED_USE_RV_REF
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
- unordered_multiset<T,H,P,A>::insert(BOOST_RV_REF(value_type) obj)
+ typename unordered_multiset<T,H,P,A>::iterator
+ unordered_multiset<T,H,P,A>::insert(BOOST_UNORDERED_RV_REF(value_type) obj)
     {
         return iterator(table_.emplace(boost::move(obj)));
     }
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+ typename unordered_multiset<T,H,P,A>::iterator
         unordered_multiset<T,H,P,A>::insert(const_iterator,
- BOOST_RV_REF(value_type) obj)
+ BOOST_UNORDERED_RV_REF(value_type) obj)
     {
         return iterator(table_.emplace(boost::move(obj)));
     }
-#endif
 
     template <class T, class H, class P, class A>
     template <class InputIt>
@@ -1324,21 +1295,21 @@
 #endif
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+ typename unordered_multiset<T,H,P,A>::iterator
         unordered_multiset<T,H,P,A>::erase(const_iterator position)
     {
         return iterator(table_.erase(position.node_));
     }
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::size_type
+ typename unordered_multiset<T,H,P,A>::size_type
         unordered_multiset<T,H,P,A>::erase(const key_type& k)
     {
         return table_.erase_key(k);
     }
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::iterator
+ typename unordered_multiset<T,H,P,A>::iterator
         unordered_multiset<T,H,P,A>::erase(const_iterator first, const_iterator last)
     {
         return iterator(table_.erase_range(first.node_, last.node_));
@@ -1359,14 +1330,14 @@
     // observers
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::hasher
+ typename unordered_multiset<T,H,P,A>::hasher
         unordered_multiset<T,H,P,A>::hash_function() const
     {
         return table_.hash_function();
     }
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::key_equal
+ typename unordered_multiset<T,H,P,A>::key_equal
         unordered_multiset<T,H,P,A>::key_eq() const
     {
         return table_.key_eq();
@@ -1375,7 +1346,7 @@
     // lookup
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::const_iterator
+ typename unordered_multiset<T,H,P,A>::const_iterator
         unordered_multiset<T,H,P,A>::find(const key_type& k) const
     {
         return const_iterator(table_.find_node(k));
@@ -1384,7 +1355,7 @@
     template <class T, class H, class P, class A>
     template <class CompatibleKey, class CompatibleHash,
         class CompatiblePredicate>
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::const_iterator
+ typename unordered_multiset<T,H,P,A>::const_iterator
         unordered_multiset<T,H,P,A>::find(
             CompatibleKey const& k,
             CompatibleHash const& hash,
@@ -1394,7 +1365,7 @@
     }
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::size_type
+ typename unordered_multiset<T,H,P,A>::size_type
         unordered_multiset<T,H,P,A>::count(const key_type& k) const
     {
         return table_.count(k);
@@ -1402,16 +1373,15 @@
 
     template <class T, class H, class P, class A>
     std::pair<
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::const_iterator,
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::const_iterator>
+ typename unordered_multiset<T,H,P,A>::const_iterator,
+ typename unordered_multiset<T,H,P,A>::const_iterator>
         unordered_multiset<T,H,P,A>::equal_range(const key_type& k) const
     {
- return BOOST_UNORDERED_PAIR_CAST(const_iterator, const_iterator,
- table_.equal_range(k));
+ return table_.equal_range(k);
     }
 
     template <class T, class H, class P, class A>
- BOOST_DEDUCED_TYPENAME unordered_multiset<T,H,P,A>::size_type
+ typename unordered_multiset<T,H,P,A>::size_type
         unordered_multiset<T,H,P,A>::bucket_size(size_type n) const
     {
         return table_.bucket_size(n);

Modified: branches/release/libs/unordered/doc/buckets.qbk
==============================================================================
--- branches/release/libs/unordered/doc/buckets.qbk (original)
+++ branches/release/libs/unordered/doc/buckets.qbk 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -112,7 +112,7 @@
 below the max load factor, and set the maximum load factor to be the same as
 or close to the hint - unless your hint is unreasonably small or large.
 
-[table Methods for Controlling Bucket Size
+[table:bucket_size Methods for Controlling Bucket Size
     [[Method] [Description]]
 
     [

Modified: branches/release/libs/unordered/doc/changes.qbk
==============================================================================
--- branches/release/libs/unordered/doc/changes.qbk (original)
+++ branches/release/libs/unordered/doc/changes.qbk 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -151,4 +151,7 @@
   the allocator has a member structure `propagate_on_container_swap`,
   such that `propagate_on_container_swap::value` is true.
 
+* Allocator's `construct` and `destroy` functions are called with raw
+ pointers, rather than the allocator's `pointer` type.
+
 [endsect]

Modified: branches/release/libs/unordered/doc/comparison.qbk
==============================================================================
--- branches/release/libs/unordered/doc/comparison.qbk (original)
+++ branches/release/libs/unordered/doc/comparison.qbk 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -4,7 +4,7 @@
 
 [section:comparison Comparison with Associative Containers]
 
-[table Interface differences.
+[table:interface_differences Interface differences.
     [[Associative Containers] [Unordered Associative Containers]]
 
     [
@@ -88,7 +88,7 @@
     ]
 ]
 
-[table Complexity Guarantees
+[table:complexity_guarantees Complexity Guarantees
     [[Operation] [Associative Containers] [Unordered Associative Containers]]
     [
         [Construction of empty container]

Modified: branches/release/libs/unordered/doc/compliance.qbk
==============================================================================
--- branches/release/libs/unordered/doc/compliance.qbk (original)
+++ branches/release/libs/unordered/doc/compliance.qbk 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -4,25 +4,42 @@
 
 [section:compliance C++11 Compliance]
 
-/TODO/: Look into C++11's `std::pair`.
-
 [section:allocator_compliance Use of allocators]
 
-* Objects are not constructed using the allocator. The node containing them
- is constructed using the allocator's `construct` function, but then the
- object is constructed in a buffer in that node by calling the constructor
- directly.
-* Similarly the object is destructed by calling its destructor directly, and
- then the allocator's `destroy` method is used to destruct the node.
-* For most compilers `select_on_container_copy` is only detected for an
- exact signature match in the allocator itself - not in a base. There is full
- detection for g++ 4.4 or laster, Visual C++ 2008 or later, Clang and maybe
- other compilers which support SFINAE for expressions.
-* `pointer_traits` aren't used. Instead, pointer types are obtained from
- rebound allocators.
-* /TODO/: Any other defficiences of `allocator_traits` emulation.
-* Pointers of base types are used to store the location of a derived type.
- (/TODO/: I'm not sure if that isn't compliant).
+C++11 introduced a new, mostly backwards compatible, allocator system.
+This uses a traits class, `allocator_traits` to handle the allocator
+adding extra functionality, and making some methods and types optional.
+At the time of writing there isn't a stable release of a standard library
+with `allocator_traits` (libc++ has `allocator_traits` but it hasn't been
+released yet) so a partial implementation is always used.
+
+A full implementation of `allocator_traits` requires sophisticated
+member function detection which requires support for SFINAE expressions,
+or something close. This is available on GCC from version 4.4, Clang and
+Visual C++ 2008 (with a little hacking) or later.
+
+On these compilers, the `construct`, `destroy` and `max_size` member functions
+are optional, as per C++11. On other compilers they are still required.
+
+`propagate_on_container_copy_assignment`,
+`propagate_on_container_move_assignment` and
+`propagate_on_container_swap` are supported on most compilers
+(/TODO/: which ones don't support them?).
+`select_on_container_copy_construction` is also supported, but on
+compilers without full member function detection it must have exactly
+the right function signature, and can't be declared in a base class
+in order for it to be detected.
+
+The use of the allocator's construct and destruct methods might be a bit
+surprising.
+Nodes are constructed and destructed using the allocator, but the objects
+contained in the node are stored in aligned space within the node
+and constructed and destructed by calling the constructor and destructor
+directly. So `construct` and `destroy` are called for the node, but not for
+the object.
+
+`pointer_traits` aren't used. Instead, pointer types are obtained from
+rebound allocators.
 
 [endsect]
 
@@ -35,19 +52,43 @@
 
 * Non-copyable objects can be stored in the containers, but without support
   for rvalue references the container will not be movable.
-* The number of arguments used in emplace is limited to /TODO/.
+* The number of arguments used in `emplace` is limited to /TODO/.
 * Argument forwarding is not perfect.
-* /TODO/: Constructor call for pairs.
 
 [endsect]
 
-[section:other Other]
+[section:pairs Pairs]
+
+Since the containers use `std::pair` they're limited to the version
+from the current standard library. But since C++11 `std::pair`'s
+`piecewise_construct` based constructor is very useful, `emplace`
+emulates it with a `piecewise_construct` in the `boost::unordered`
+namespace. So for example, the following will work:
+
+ boost::unordered_multimap<std::string, std::complex> x;
+
+ x.emplace(
+ boost::unordered::piecewise_construct,
+ boost::make_tuple("key"), boost::make_tuple(1, 2));
+
+Older drafts of the standard also supported variadic constructors
+for `std::pair`, where the first argument would be used for the
+first part of the pair, and the remaining for the second part.
+For the same example:
+
+ x.emplace("key", 1, 2);
+
+This is emulated in Boost.Unordered, but will be deprecated soon.
+While it is a lot more compact, it lead to ambiguities so it was
+removed.
+
+[endsect]
 
-* When swapping, `Pred` and `Hash` are not currently swapped by calling
- `swap`, their copy constructors are used.
-* As a consequence when swapping an exception may be throw from their
- copy constructor.
+[section:swap Swapping]
 
+When swapping, `Pred` and `Hash` are not currently swapped by calling
+`swap`, their copy constructors are used. As a consequence when swapping
+an exception may be throw from their copy constructor.
 
 [endsect]
 

Modified: branches/release/libs/unordered/doc/hash_equality.qbk
==============================================================================
--- branches/release/libs/unordered/doc/hash_equality.qbk (original)
+++ branches/release/libs/unordered/doc/hash_equality.qbk 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -67,9 +67,10 @@
 
 See the [link hash.custom Boost.Hash documentation] for more detail on how to
 do this. Remember that it relies on extensions to the draft standard - so it
-won't work on other implementations of the unordered associative containers.
+won't work for other implementations of the unordered associative containers,
+you'll need to explicitly use Boost.Hash.
 
-[table Methods for accessing the hash and equality functions.
+[table:access_methods Methods for accessing the hash and equality functions.
     [[Method] [Description]]
 
     [

Modified: branches/release/libs/unordered/doc/intro.qbk
==============================================================================
--- branches/release/libs/unordered/doc/intro.qbk (original)
+++ branches/release/libs/unordered/doc/intro.qbk 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -2,15 +2,6 @@
  / Distributed under the Boost Software License, Version 1.0. (See accompanying
  / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
 
-[def __tr1__
- [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
- C++ Standard Library Technical Report]]
-[def __boost-tr1__
- [@http://www.boost.org/doc/html/boost_tr1.html
- Boost.TR1]]
-[def __draft__
- [@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2960.pdf
- Working Draft of the C++ Standard]]
 [def __hash-table__ [@http://en.wikipedia.org/wiki/Hash_table
     hash table]]
 [def __hash-function__ [@http://en.wikipedia.org/wiki/Hash_function
@@ -31,12 +22,10 @@
 or isn't practical. In contrast, a hash table only needs an equality function
 and a hash function for the key.
 
-With this in mind, the __tr1__ introduced the unordered associative containers,
-which are implemented using hash tables, and they have now been added to the
-__draft__.
-
-This library supplies an almost complete implementation of the specification in
-the __draft__.
+With this in mind, unordered associative containers were added to the C++
+standard. This is an implementation of the containers described in C++11,
+with some [link unordered.compliance deviations from the standard] in
+order to work with non-C++11 compilers and libraries.
 
 `unordered_set` and `unordered_multiset` are defined in the header
 <[headerref boost/unordered_set.hpp]>

Modified: branches/release/libs/unordered/doc/rationale.qbk
==============================================================================
--- branches/release/libs/unordered/doc/rationale.qbk (original)
+++ branches/release/libs/unordered/doc/rationale.qbk 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -92,6 +92,8 @@
 
 [h2 Equality operators]
 
+/TODO/: This is out of date.
+
 `operator==` and `operator!=` are not included in the standard, but I've
 added them as I think they could be useful and can be implemented
 fairly efficiently. They are specified differently to the other standard
@@ -115,6 +117,8 @@
 
 [h3 C++0x allocators]
 
+/TODO/: This is out of date.
+
 Recent drafts have included an overhaul of the allocators, but this was
 dependent on concepts which are no longer in the standard.
 [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2946.pdf n2946]
@@ -124,6 +128,8 @@
 
 [h3 Swapping containers with unequal allocators]
 
+/TODO/: This is out of date.
+
 It isn't clear how to swap containers when their allocators aren't equal.
 This is
 [@http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#431

Modified: branches/release/libs/unordered/doc/ref.php
==============================================================================
--- branches/release/libs/unordered/doc/ref.php (original)
+++ branches/release/libs/unordered/doc/ref.php 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -60,10 +60,6 @@
 
           </simpara></purpose>
           <description>
- <para>Based on chapter 23 of
- <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
- But without the updated rules for allocators.
- </para>
             <para><emphasis role="bold">Template Parameters</emphasis>
               <informaltable>
                 <tgroup cols="2">
@@ -236,6 +232,9 @@
             </parameter>
             <description>
               <para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
+ <para>If <code>Allocator::select_on_container_copy_construction</code>
+ exists and has the right signature, the allocator will be
+ constructed from its result.</para>
             </description>
             <requires>
               <para><code>value_type</code> is copy constructible</para>
@@ -249,12 +248,18 @@
               <para>The move constructor.</para>
             </description>
             <notes>
- <para>This is emulated on compilers without rvalue references.</para>
+ <para>This is implemented using Boost.Move.</para>
             </notes>
             <requires>
               <para>
                 <code>value_type</code> is move constructible.
- (TODO: This is not actually required in this implementation).
+ </para>
+ <para>
+ On compilers without rvalue reference support the
+ emulation does not support moving without calling
+ <code>boost::move</code> if <code>value_type</code> is
+ not copyable. So, for example, you can't return the
+ container from a function.
               </para>
             </requires>
           </constructor>
@@ -289,14 +294,12 @@
             <type><?php echo $name; ?>&amp;</type>
             <description>
               <para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
+ <para>If <code>Alloc::propagate_on_container_copy_assignment</code>
+ exists and <code>Alloc::propagate_on_container_copy_assignment::value
+ </code> is true, the allocator is overwritten, if not the
+ copied elements are created using the existing
+ allocator.</para>
             </description>
- <notes>
- <para>
- On compilers without rvalue references, there is a single assignment
- operator with the signature <code>operator=(<?php echo $name; ?>)</code>
- in order to emulate move semantics.
- </para>
- </notes>
             <requires>
               <para><code>value_type</code> is copy constructible</para>
             </requires>
@@ -308,18 +311,21 @@
             <type><?php echo $name; ?>&amp;</type>
             <description>
               <para>The move assignment operator.</para>
+ <para>If <code>Alloc::propagate_on_container_move_assignment</code>
+ exists and <code>Alloc::propagate_on_container_move_assignment::value
+ </code> is true, the allocator is overwritten, if not the
+ moved elements are created using the existing
+ allocator.</para>
             </description>
             <notes>
               <para>
- On compilers without rvalue references, there is a single assignment
- operator with the signature <code>operator=(<?php echo $name; ?>)</code>
- in order to emulate move semantics.
+ On compilers without rvalue references, this is emulated using
+ Boost.Move.
               </para>
             </notes>
             <requires>
               <para>
                 <code>value_type</code> is move constructible.
- (TODO: This is not actually required in this implementation).
               </para>
             </requires>
           </method>
@@ -406,6 +412,10 @@
                 <para>If the compiler doesn't support variadic template arguments or rvalue
                       references, this is emulated for up to 10 arguments, with no support
                       for rvalue references or move semantics.</para>
+ <para>Since existing `std::pair` implementations don't support
+ <code>std::piecewise_construct</code> this emulates it,
+ but using <code>boost::unordered::piecewise_construct</code>.
+ </para>
               </notes>
             </method>
             <method name="emplace_hint">
@@ -444,6 +454,10 @@
                 <para>If the compiler doesn't support variadic template arguments or rvalue
                       references, this is emulated for up to 10 arguments, with no support
                       for rvalue references or move semantics.</para>
+ <para>Since existing `std::pair` implementations don't support
+ <code>std::piecewise_construct</code> this emulates it,
+ but using <code>boost::unordered::piecewise_construct</code>.
+ </para>
               </notes>
             </method>
             <method name="insert">
@@ -541,15 +555,13 @@
               </returns>
               <throws>
                 <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
- <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
               </throws>
               <notes>
                 <para>
- When the number of elements is a lot smaller than the number of buckets
- this function can be very inefficient as it has to search through empty
- buckets for the next element, in order to return the iterator.
- The method <methodname>quick_erase</methodname> is faster, but has yet
- to be standardized.
+ In older versions this could be inefficient because it had to search
+ through several buckets to find the position of the returned iterator.
+ The data structure has been changed so that this is no longer the case,
+ and the alternative erase methods have been deprecated.
                 </para>
               </notes>
             </method>
@@ -601,13 +613,10 @@
               </throws>
               <notes>
                 <para>
- This method is faster than <methodname>erase</methodname> as
- it doesn't have to find the next element in the container -
- a potentially costly operation.
- </para>
- <para>
- As it hasn't been standardized, it's likely that this may
- change in the future.
+ This method was implemented because returning an iterator to
+ the next element from <code>erase</code> was expensive, but
+ the container has been redesigned so that is no longer the
+ case. So this method is now deprecated.
                 </para>
               </notes>
             </method>
@@ -625,10 +634,10 @@
               </throws>
               <notes>
                 <para>
- This method is now deprecated, use
- <methodname>quick_return</methodname> instead. Although be
- warned that as that isn't standardized yet, it could also
- change.
+ This method was implemented because returning an iterator to
+ the next element from <code>erase</code> was expensive, but
+ the container has been redesigned so that is no longer the
+ case. So this method is now deprecated.
                 </para>
               </notes>
             </method>
@@ -653,6 +662,7 @@
                 <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
               </throws>
               <notes>
+ <para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
                 <para>For a discussion of the behavior when allocators aren't equal see
                   <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
               </notes>
@@ -952,6 +962,7 @@
               </parameter>
               <type>bool</type>
               <notes>
+ <para><emphasis>TODO</emphasis>: Documentation outdated.</para>
                 <para>This is a boost extension.</para>
                 <para>Behavior is undefined if the two containers don't have
                     equivalent equality predicates.</para>
@@ -975,6 +986,7 @@
               </parameter>
               <type>bool</type>
               <notes>
+ <para><emphasis>TODO</emphasis>: Documentation outdated.</para>
                 <para>This is a boost extension.</para>
                 <para>Behavior is undefined if the two containers don't have
                     equivalent equality predicates.</para>
@@ -1006,6 +1018,7 @@
                 <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
               </throws>
               <notes>
+ <para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
                 <para>For a discussion of the behavior when allocators aren't equal see
                   <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
               </notes>

Modified: branches/release/libs/unordered/doc/ref.xml
==============================================================================
--- branches/release/libs/unordered/doc/ref.xml (original)
+++ branches/release/libs/unordered/doc/ref.xml 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -23,10 +23,6 @@
             An unordered associative container that stores unique values.
           </simpara></purpose>
           <description>
- <para>Based on chapter 23 of
- <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
- But without the updated rules for allocators.
- </para>
             <para><emphasis role="bold">Template Parameters</emphasis>
               <informaltable>
                 <tgroup cols="2">
@@ -181,6 +177,9 @@
             </parameter>
             <description>
               <para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
+ <para>If <code>Allocator::select_on_container_copy_construction</code>
+ exists and has the right signature, the allocator will be
+ constructed from its result.</para>
             </description>
             <requires>
               <para><code>value_type</code> is copy constructible</para>
@@ -194,12 +193,18 @@
               <para>The move constructor.</para>
             </description>
             <notes>
- <para>This is emulated on compilers without rvalue references.</para>
+ <para>This is implemented using Boost.Move.</para>
             </notes>
             <requires>
               <para>
                 <code>value_type</code> is move constructible.
- (TODO: This is not actually required in this implementation).
+ </para>
+ <para>
+ On compilers without rvalue reference support the
+ emulation does not support moving without calling
+ <code>boost::move</code> if <code>value_type</code> is
+ not copyable. So, for example, you can't return the
+ container from a function.
               </para>
             </requires>
           </constructor>
@@ -234,14 +239,12 @@
             <type>unordered_set&amp;</type>
             <description>
               <para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
+ <para>If <code>Alloc::propagate_on_container_copy_assignment</code>
+ exists and <code>Alloc::propagate_on_container_copy_assignment::value
+ </code> is true, the allocator is overwritten, if not the
+ copied elements are created using the existing
+ allocator.</para>
             </description>
- <notes>
- <para>
- On compilers without rvalue references, there is a single assignment
- operator with the signature <code>operator=(unordered_set)</code>
- in order to emulate move semantics.
- </para>
- </notes>
             <requires>
               <para><code>value_type</code> is copy constructible</para>
             </requires>
@@ -253,18 +256,21 @@
             <type>unordered_set&amp;</type>
             <description>
               <para>The move assignment operator.</para>
+ <para>If <code>Alloc::propagate_on_container_move_assignment</code>
+ exists and <code>Alloc::propagate_on_container_move_assignment::value
+ </code> is true, the allocator is overwritten, if not the
+ moved elements are created using the existing
+ allocator.</para>
             </description>
             <notes>
               <para>
- On compilers without rvalue references, there is a single assignment
- operator with the signature <code>operator=(unordered_set)</code>
- in order to emulate move semantics.
+ On compilers without rvalue references, this is emulated using
+ Boost.Move.
               </para>
             </notes>
             <requires>
               <para>
                 <code>value_type</code> is move constructible.
- (TODO: This is not actually required in this implementation).
               </para>
             </requires>
           </method>
@@ -344,6 +350,10 @@
                 <para>If the compiler doesn't support variadic template arguments or rvalue
                       references, this is emulated for up to 10 arguments, with no support
                       for rvalue references or move semantics.</para>
+ <para>Since existing `std::pair` implementations don't support
+ <code>std::piecewise_construct</code> this emulates it,
+ but using <code>boost::unordered::piecewise_construct</code>.
+ </para>
               </notes>
             </method>
             <method name="emplace_hint">
@@ -375,6 +385,10 @@
                 <para>If the compiler doesn't support variadic template arguments or rvalue
                       references, this is emulated for up to 10 arguments, with no support
                       for rvalue references or move semantics.</para>
+ <para>Since existing `std::pair` implementations don't support
+ <code>std::piecewise_construct</code> this emulates it,
+ but using <code>boost::unordered::piecewise_construct</code>.
+ </para>
               </notes>
             </method>
             <method name="insert">
@@ -457,15 +471,13 @@
               </returns>
               <throws>
                 <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
- <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
               </throws>
               <notes>
                 <para>
- When the number of elements is a lot smaller than the number of buckets
- this function can be very inefficient as it has to search through empty
- buckets for the next element, in order to return the iterator.
- The method <methodname>quick_erase</methodname> is faster, but has yet
- to be standardized.
+ In older versions this could be inefficient because it had to search
+ through several buckets to find the position of the returned iterator.
+ The data structure has been changed so that this is no longer the case,
+ and the alternative erase methods have been deprecated.
                 </para>
               </notes>
             </method>
@@ -517,13 +529,10 @@
               </throws>
               <notes>
                 <para>
- This method is faster than <methodname>erase</methodname> as
- it doesn't have to find the next element in the container -
- a potentially costly operation.
- </para>
- <para>
- As it hasn't been standardized, it's likely that this may
- change in the future.
+ This method was implemented because returning an iterator to
+ the next element from <code>erase</code> was expensive, but
+ the container has been redesigned so that is no longer the
+ case. So this method is now deprecated.
                 </para>
               </notes>
             </method>
@@ -541,10 +550,10 @@
               </throws>
               <notes>
                 <para>
- This method is now deprecated, use
- <methodname>quick_return</methodname> instead. Although be
- warned that as that isn't standardized yet, it could also
- change.
+ This method was implemented because returning an iterator to
+ the next element from <code>erase</code> was expensive, but
+ the container has been redesigned so that is no longer the
+ case. So this method is now deprecated.
                 </para>
               </notes>
             </method>
@@ -569,6 +578,7 @@
                 <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
               </throws>
               <notes>
+ <para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
                 <para>For a discussion of the behavior when allocators aren't equal see
                   <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
               </notes>
@@ -832,6 +842,7 @@
               </parameter>
               <type>bool</type>
               <notes>
+ <para><emphasis>TODO</emphasis>: Documentation outdated.</para>
                 <para>This is a boost extension.</para>
                 <para>Behavior is undefined if the two containers don't have
                     equivalent equality predicates.</para>
@@ -856,6 +867,7 @@
               </parameter>
               <type>bool</type>
               <notes>
+ <para><emphasis>TODO</emphasis>: Documentation outdated.</para>
                 <para>This is a boost extension.</para>
                 <para>Behavior is undefined if the two containers don't have
                     equivalent equality predicates.</para>
@@ -888,6 +900,7 @@
                 <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
               </throws>
               <notes>
+ <para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
                 <para>For a discussion of the behavior when allocators aren't equal see
                   <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
               </notes>
@@ -912,10 +925,6 @@
             An unordered associative container that stores values. The same key can be stored multiple times.
           </simpara></purpose>
           <description>
- <para>Based on chapter 23 of
- <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
- But without the updated rules for allocators.
- </para>
             <para><emphasis role="bold">Template Parameters</emphasis>
               <informaltable>
                 <tgroup cols="2">
@@ -1070,6 +1079,9 @@
             </parameter>
             <description>
               <para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
+ <para>If <code>Allocator::select_on_container_copy_construction</code>
+ exists and has the right signature, the allocator will be
+ constructed from its result.</para>
             </description>
             <requires>
               <para><code>value_type</code> is copy constructible</para>
@@ -1083,12 +1095,18 @@
               <para>The move constructor.</para>
             </description>
             <notes>
- <para>This is emulated on compilers without rvalue references.</para>
+ <para>This is implemented using Boost.Move.</para>
             </notes>
             <requires>
               <para>
                 <code>value_type</code> is move constructible.
- (TODO: This is not actually required in this implementation).
+ </para>
+ <para>
+ On compilers without rvalue reference support the
+ emulation does not support moving without calling
+ <code>boost::move</code> if <code>value_type</code> is
+ not copyable. So, for example, you can't return the
+ container from a function.
               </para>
             </requires>
           </constructor>
@@ -1123,14 +1141,12 @@
             <type>unordered_multiset&amp;</type>
             <description>
               <para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
+ <para>If <code>Alloc::propagate_on_container_copy_assignment</code>
+ exists and <code>Alloc::propagate_on_container_copy_assignment::value
+ </code> is true, the allocator is overwritten, if not the
+ copied elements are created using the existing
+ allocator.</para>
             </description>
- <notes>
- <para>
- On compilers without rvalue references, there is a single assignment
- operator with the signature <code>operator=(unordered_multiset)</code>
- in order to emulate move semantics.
- </para>
- </notes>
             <requires>
               <para><code>value_type</code> is copy constructible</para>
             </requires>
@@ -1142,18 +1158,21 @@
             <type>unordered_multiset&amp;</type>
             <description>
               <para>The move assignment operator.</para>
+ <para>If <code>Alloc::propagate_on_container_move_assignment</code>
+ exists and <code>Alloc::propagate_on_container_move_assignment::value
+ </code> is true, the allocator is overwritten, if not the
+ moved elements are created using the existing
+ allocator.</para>
             </description>
             <notes>
               <para>
- On compilers without rvalue references, there is a single assignment
- operator with the signature <code>operator=(unordered_multiset)</code>
- in order to emulate move semantics.
+ On compilers without rvalue references, this is emulated using
+ Boost.Move.
               </para>
             </notes>
             <requires>
               <para>
                 <code>value_type</code> is move constructible.
- (TODO: This is not actually required in this implementation).
               </para>
             </requires>
           </method>
@@ -1232,6 +1251,10 @@
                 <para>If the compiler doesn't support variadic template arguments or rvalue
                       references, this is emulated for up to 10 arguments, with no support
                       for rvalue references or move semantics.</para>
+ <para>Since existing `std::pair` implementations don't support
+ <code>std::piecewise_construct</code> this emulates it,
+ but using <code>boost::unordered::piecewise_construct</code>.
+ </para>
               </notes>
             </method>
             <method name="emplace_hint">
@@ -1263,6 +1286,10 @@
                 <para>If the compiler doesn't support variadic template arguments or rvalue
                       references, this is emulated for up to 10 arguments, with no support
                       for rvalue references or move semantics.</para>
+ <para>Since existing `std::pair` implementations don't support
+ <code>std::piecewise_construct</code> this emulates it,
+ but using <code>boost::unordered::piecewise_construct</code>.
+ </para>
               </notes>
             </method>
             <method name="insert">
@@ -1344,15 +1371,13 @@
               </returns>
               <throws>
                 <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
- <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
               </throws>
               <notes>
                 <para>
- When the number of elements is a lot smaller than the number of buckets
- this function can be very inefficient as it has to search through empty
- buckets for the next element, in order to return the iterator.
- The method <methodname>quick_erase</methodname> is faster, but has yet
- to be standardized.
+ In older versions this could be inefficient because it had to search
+ through several buckets to find the position of the returned iterator.
+ The data structure has been changed so that this is no longer the case,
+ and the alternative erase methods have been deprecated.
                 </para>
               </notes>
             </method>
@@ -1404,13 +1429,10 @@
               </throws>
               <notes>
                 <para>
- This method is faster than <methodname>erase</methodname> as
- it doesn't have to find the next element in the container -
- a potentially costly operation.
- </para>
- <para>
- As it hasn't been standardized, it's likely that this may
- change in the future.
+ This method was implemented because returning an iterator to
+ the next element from <code>erase</code> was expensive, but
+ the container has been redesigned so that is no longer the
+ case. So this method is now deprecated.
                 </para>
               </notes>
             </method>
@@ -1428,10 +1450,10 @@
               </throws>
               <notes>
                 <para>
- This method is now deprecated, use
- <methodname>quick_return</methodname> instead. Although be
- warned that as that isn't standardized yet, it could also
- change.
+ This method was implemented because returning an iterator to
+ the next element from <code>erase</code> was expensive, but
+ the container has been redesigned so that is no longer the
+ case. So this method is now deprecated.
                 </para>
               </notes>
             </method>
@@ -1456,6 +1478,7 @@
                 <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
               </throws>
               <notes>
+ <para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
                 <para>For a discussion of the behavior when allocators aren't equal see
                   <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
               </notes>
@@ -1719,6 +1742,7 @@
               </parameter>
               <type>bool</type>
               <notes>
+ <para><emphasis>TODO</emphasis>: Documentation outdated.</para>
                 <para>This is a boost extension.</para>
                 <para>Behavior is undefined if the two containers don't have
                     equivalent equality predicates.</para>
@@ -1743,6 +1767,7 @@
               </parameter>
               <type>bool</type>
               <notes>
+ <para><emphasis>TODO</emphasis>: Documentation outdated.</para>
                 <para>This is a boost extension.</para>
                 <para>Behavior is undefined if the two containers don't have
                     equivalent equality predicates.</para>
@@ -1775,6 +1800,7 @@
                 <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
               </throws>
               <notes>
+ <para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
                 <para>For a discussion of the behavior when allocators aren't equal see
                   <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
               </notes>
@@ -1805,10 +1831,6 @@
             An unordered associative container that associates unique keys with another value.
           </simpara></purpose>
           <description>
- <para>Based on chapter 23 of
- <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
- But without the updated rules for allocators.
- </para>
             <para><emphasis role="bold">Template Parameters</emphasis>
               <informaltable>
                 <tgroup cols="2">
@@ -1969,6 +1991,9 @@
             </parameter>
             <description>
               <para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
+ <para>If <code>Allocator::select_on_container_copy_construction</code>
+ exists and has the right signature, the allocator will be
+ constructed from its result.</para>
             </description>
             <requires>
               <para><code>value_type</code> is copy constructible</para>
@@ -1982,12 +2007,18 @@
               <para>The move constructor.</para>
             </description>
             <notes>
- <para>This is emulated on compilers without rvalue references.</para>
+ <para>This is implemented using Boost.Move.</para>
             </notes>
             <requires>
               <para>
                 <code>value_type</code> is move constructible.
- (TODO: This is not actually required in this implementation).
+ </para>
+ <para>
+ On compilers without rvalue reference support the
+ emulation does not support moving without calling
+ <code>boost::move</code> if <code>value_type</code> is
+ not copyable. So, for example, you can't return the
+ container from a function.
               </para>
             </requires>
           </constructor>
@@ -2022,14 +2053,12 @@
             <type>unordered_map&amp;</type>
             <description>
               <para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
+ <para>If <code>Alloc::propagate_on_container_copy_assignment</code>
+ exists and <code>Alloc::propagate_on_container_copy_assignment::value
+ </code> is true, the allocator is overwritten, if not the
+ copied elements are created using the existing
+ allocator.</para>
             </description>
- <notes>
- <para>
- On compilers without rvalue references, there is a single assignment
- operator with the signature <code>operator=(unordered_map)</code>
- in order to emulate move semantics.
- </para>
- </notes>
             <requires>
               <para><code>value_type</code> is copy constructible</para>
             </requires>
@@ -2041,18 +2070,21 @@
             <type>unordered_map&amp;</type>
             <description>
               <para>The move assignment operator.</para>
+ <para>If <code>Alloc::propagate_on_container_move_assignment</code>
+ exists and <code>Alloc::propagate_on_container_move_assignment::value
+ </code> is true, the allocator is overwritten, if not the
+ moved elements are created using the existing
+ allocator.</para>
             </description>
             <notes>
               <para>
- On compilers without rvalue references, there is a single assignment
- operator with the signature <code>operator=(unordered_map)</code>
- in order to emulate move semantics.
+ On compilers without rvalue references, this is emulated using
+ Boost.Move.
               </para>
             </notes>
             <requires>
               <para>
                 <code>value_type</code> is move constructible.
- (TODO: This is not actually required in this implementation).
               </para>
             </requires>
           </method>
@@ -2132,6 +2164,10 @@
                 <para>If the compiler doesn't support variadic template arguments or rvalue
                       references, this is emulated for up to 10 arguments, with no support
                       for rvalue references or move semantics.</para>
+ <para>Since existing `std::pair` implementations don't support
+ <code>std::piecewise_construct</code> this emulates it,
+ but using <code>boost::unordered::piecewise_construct</code>.
+ </para>
               </notes>
             </method>
             <method name="emplace_hint">
@@ -2163,6 +2199,10 @@
                 <para>If the compiler doesn't support variadic template arguments or rvalue
                       references, this is emulated for up to 10 arguments, with no support
                       for rvalue references or move semantics.</para>
+ <para>Since existing `std::pair` implementations don't support
+ <code>std::piecewise_construct</code> this emulates it,
+ but using <code>boost::unordered::piecewise_construct</code>.
+ </para>
               </notes>
             </method>
             <method name="insert">
@@ -2245,15 +2285,13 @@
               </returns>
               <throws>
                 <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
- <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
               </throws>
               <notes>
                 <para>
- When the number of elements is a lot smaller than the number of buckets
- this function can be very inefficient as it has to search through empty
- buckets for the next element, in order to return the iterator.
- The method <methodname>quick_erase</methodname> is faster, but has yet
- to be standardized.
+ In older versions this could be inefficient because it had to search
+ through several buckets to find the position of the returned iterator.
+ The data structure has been changed so that this is no longer the case,
+ and the alternative erase methods have been deprecated.
                 </para>
               </notes>
             </method>
@@ -2305,13 +2343,10 @@
               </throws>
               <notes>
                 <para>
- This method is faster than <methodname>erase</methodname> as
- it doesn't have to find the next element in the container -
- a potentially costly operation.
- </para>
- <para>
- As it hasn't been standardized, it's likely that this may
- change in the future.
+ This method was implemented because returning an iterator to
+ the next element from <code>erase</code> was expensive, but
+ the container has been redesigned so that is no longer the
+ case. So this method is now deprecated.
                 </para>
               </notes>
             </method>
@@ -2329,10 +2364,10 @@
               </throws>
               <notes>
                 <para>
- This method is now deprecated, use
- <methodname>quick_return</methodname> instead. Although be
- warned that as that isn't standardized yet, it could also
- change.
+ This method was implemented because returning an iterator to
+ the next element from <code>erase</code> was expensive, but
+ the container has been redesigned so that is no longer the
+ case. So this method is now deprecated.
                 </para>
               </notes>
             </method>
@@ -2357,6 +2392,7 @@
                 <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
               </throws>
               <notes>
+ <para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
                 <para>For a discussion of the behavior when allocators aren't equal see
                   <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
               </notes>
@@ -2657,6 +2693,7 @@
               </parameter>
               <type>bool</type>
               <notes>
+ <para><emphasis>TODO</emphasis>: Documentation outdated.</para>
                 <para>This is a boost extension.</para>
                 <para>Behavior is undefined if the two containers don't have
                     equivalent equality predicates.</para>
@@ -2683,6 +2720,7 @@
               </parameter>
               <type>bool</type>
               <notes>
+ <para><emphasis>TODO</emphasis>: Documentation outdated.</para>
                 <para>This is a boost extension.</para>
                 <para>Behavior is undefined if the two containers don't have
                     equivalent equality predicates.</para>
@@ -2717,6 +2755,7 @@
                 <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
               </throws>
               <notes>
+ <para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
                 <para>For a discussion of the behavior when allocators aren't equal see
                   <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
               </notes>
@@ -2743,10 +2782,6 @@
             An unordered associative container that associates keys with another value. The same key can be stored multiple times.
           </simpara></purpose>
           <description>
- <para>Based on chapter 23 of
- <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2960.pdf">the working draft of the C++ standard [n2960]</ulink>.
- But without the updated rules for allocators.
- </para>
             <para><emphasis role="bold">Template Parameters</emphasis>
               <informaltable>
                 <tgroup cols="2">
@@ -2907,6 +2942,9 @@
             </parameter>
             <description>
               <para>The copy constructor. Copies the contained elements, hash function, predicate, maximum load factor and allocator.</para>
+ <para>If <code>Allocator::select_on_container_copy_construction</code>
+ exists and has the right signature, the allocator will be
+ constructed from its result.</para>
             </description>
             <requires>
               <para><code>value_type</code> is copy constructible</para>
@@ -2920,12 +2958,18 @@
               <para>The move constructor.</para>
             </description>
             <notes>
- <para>This is emulated on compilers without rvalue references.</para>
+ <para>This is implemented using Boost.Move.</para>
             </notes>
             <requires>
               <para>
                 <code>value_type</code> is move constructible.
- (TODO: This is not actually required in this implementation).
+ </para>
+ <para>
+ On compilers without rvalue reference support the
+ emulation does not support moving without calling
+ <code>boost::move</code> if <code>value_type</code> is
+ not copyable. So, for example, you can't return the
+ container from a function.
               </para>
             </requires>
           </constructor>
@@ -2960,14 +3004,12 @@
             <type>unordered_multimap&amp;</type>
             <description>
               <para>The assignment operator. Copies the contained elements, hash function, predicate and maximum load factor but not the allocator.</para>
+ <para>If <code>Alloc::propagate_on_container_copy_assignment</code>
+ exists and <code>Alloc::propagate_on_container_copy_assignment::value
+ </code> is true, the allocator is overwritten, if not the
+ copied elements are created using the existing
+ allocator.</para>
             </description>
- <notes>
- <para>
- On compilers without rvalue references, there is a single assignment
- operator with the signature <code>operator=(unordered_multimap)</code>
- in order to emulate move semantics.
- </para>
- </notes>
             <requires>
               <para><code>value_type</code> is copy constructible</para>
             </requires>
@@ -2979,18 +3021,21 @@
             <type>unordered_multimap&amp;</type>
             <description>
               <para>The move assignment operator.</para>
+ <para>If <code>Alloc::propagate_on_container_move_assignment</code>
+ exists and <code>Alloc::propagate_on_container_move_assignment::value
+ </code> is true, the allocator is overwritten, if not the
+ moved elements are created using the existing
+ allocator.</para>
             </description>
             <notes>
               <para>
- On compilers without rvalue references, there is a single assignment
- operator with the signature <code>operator=(unordered_multimap)</code>
- in order to emulate move semantics.
+ On compilers without rvalue references, this is emulated using
+ Boost.Move.
               </para>
             </notes>
             <requires>
               <para>
                 <code>value_type</code> is move constructible.
- (TODO: This is not actually required in this implementation).
               </para>
             </requires>
           </method>
@@ -3069,6 +3114,10 @@
                 <para>If the compiler doesn't support variadic template arguments or rvalue
                       references, this is emulated for up to 10 arguments, with no support
                       for rvalue references or move semantics.</para>
+ <para>Since existing `std::pair` implementations don't support
+ <code>std::piecewise_construct</code> this emulates it,
+ but using <code>boost::unordered::piecewise_construct</code>.
+ </para>
               </notes>
             </method>
             <method name="emplace_hint">
@@ -3100,6 +3149,10 @@
                 <para>If the compiler doesn't support variadic template arguments or rvalue
                       references, this is emulated for up to 10 arguments, with no support
                       for rvalue references or move semantics.</para>
+ <para>Since existing `std::pair` implementations don't support
+ <code>std::piecewise_construct</code> this emulates it,
+ but using <code>boost::unordered::piecewise_construct</code>.
+ </para>
               </notes>
             </method>
             <method name="insert">
@@ -3181,15 +3234,13 @@
               </returns>
               <throws>
                 <para>Only throws an exception if it is thrown by <code>hasher</code> or <code>key_equal</code>.</para>
- <para>In this implementation, this overload doesn't call either function object's methods so it is no throw, but this might not be true in other implementations.</para>
               </throws>
               <notes>
                 <para>
- When the number of elements is a lot smaller than the number of buckets
- this function can be very inefficient as it has to search through empty
- buckets for the next element, in order to return the iterator.
- The method <methodname>quick_erase</methodname> is faster, but has yet
- to be standardized.
+ In older versions this could be inefficient because it had to search
+ through several buckets to find the position of the returned iterator.
+ The data structure has been changed so that this is no longer the case,
+ and the alternative erase methods have been deprecated.
                 </para>
               </notes>
             </method>
@@ -3241,13 +3292,10 @@
               </throws>
               <notes>
                 <para>
- This method is faster than <methodname>erase</methodname> as
- it doesn't have to find the next element in the container -
- a potentially costly operation.
- </para>
- <para>
- As it hasn't been standardized, it's likely that this may
- change in the future.
+ This method was implemented because returning an iterator to
+ the next element from <code>erase</code> was expensive, but
+ the container has been redesigned so that is no longer the
+ case. So this method is now deprecated.
                 </para>
               </notes>
             </method>
@@ -3265,10 +3313,10 @@
               </throws>
               <notes>
                 <para>
- This method is now deprecated, use
- <methodname>quick_return</methodname> instead. Although be
- warned that as that isn't standardized yet, it could also
- change.
+ This method was implemented because returning an iterator to
+ the next element from <code>erase</code> was expensive, but
+ the container has been redesigned so that is no longer the
+ case. So this method is now deprecated.
                 </para>
               </notes>
             </method>
@@ -3293,6 +3341,7 @@
                 <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
               </throws>
               <notes>
+ <para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
                 <para>For a discussion of the behavior when allocators aren't equal see
                   <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
               </notes>
@@ -3558,6 +3607,7 @@
               </parameter>
               <type>bool</type>
               <notes>
+ <para><emphasis>TODO</emphasis>: Documentation outdated.</para>
                 <para>This is a boost extension.</para>
                 <para>Behavior is undefined if the two containers don't have
                     equivalent equality predicates.</para>
@@ -3584,6 +3634,7 @@
               </parameter>
               <type>bool</type>
               <notes>
+ <para><emphasis>TODO</emphasis>: Documentation outdated.</para>
                 <para>This is a boost extension.</para>
                 <para>Behavior is undefined if the two containers don't have
                     equivalent equality predicates.</para>
@@ -3618,6 +3669,7 @@
                 <para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
               </throws>
               <notes>
+ <para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
                 <para>For a discussion of the behavior when allocators aren't equal see
                   <link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
               </notes>

Modified: branches/release/libs/unordered/doc/unordered.qbk
==============================================================================
--- branches/release/libs/unordered/doc/unordered.qbk (original)
+++ branches/release/libs/unordered/doc/unordered.qbk 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -3,7 +3,7 @@
  / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
 
 [library Boost.Unordered
- [quickbook 1.4]
+ [quickbook 1.5]
     [authors [James, Daniel]]
     [copyright 2003 2004 Jeremy B. Maitin-Shepard]
     [copyright 2005 2006 2007 2008 Daniel James]

Modified: branches/release/libs/unordered/test/unordered/Jamfile.v2
==============================================================================
--- branches/release/libs/unordered/test/unordered/Jamfile.v2 (original)
+++ branches/release/libs/unordered/test/unordered/Jamfile.v2 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -23,6 +23,7 @@
         [ run fwd_set_test.cpp ]
         [ run fwd_map_test.cpp ]
         [ run allocator_traits.cpp ]
+ [ run minimal_allocator.cpp ]
         [ run compile_set.cpp ]
         [ run compile_map.cpp ]
         [ run link_test_1.cpp link_test_2.cpp ]
@@ -34,6 +35,9 @@
         [ run move_tests.cpp ]
         [ run assign_tests.cpp ]
         [ run insert_tests.cpp ]
+ [ run insert_tests.cpp : :
+ : <define>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
+ : insert_deprecated ]
         [ run insert_stable_tests.cpp ]
         [ run unnecessary_copy_tests.cpp ]
         [ run erase_tests.cpp ]
@@ -44,5 +48,6 @@
         [ run load_factor_tests.cpp ]
         [ run rehash_tests.cpp ]
         [ run equality_tests.cpp ]
+ [ run equality_deprecated.cpp ]
         [ run swap_tests.cpp ]
     ;

Modified: branches/release/libs/unordered/test/unordered/compile_set.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/compile_set.cpp (original)
+++ branches/release/libs/unordered/test/unordered/compile_set.cpp 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -16,7 +16,7 @@
 #include "./compile_tests.hpp"
 
 // Explicit instantiation to catch compile-time errors
-/*
+
 template class boost::unordered_set<
     int,
     boost::hash<int>,
@@ -27,7 +27,7 @@
     boost::hash<int>,
     std::equal_to<int>,
     test::minimal::allocator<int> >;
-*/
+
 template class boost::unordered_set<
     test::minimal::assignable,
     test::minimal::hash<test::minimal::assignable>,

Modified: branches/release/libs/unordered/test/unordered/insert_tests.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/insert_tests.cpp (original)
+++ branches/release/libs/unordered/test/unordered/insert_tests.cpp 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -537,8 +537,6 @@
     }
 };
 
-// This will actually be deprecated pretty soon.
-
 UNORDERED_AUTO_TEST(map_emplace_test)
 {
     boost::unordered_map<int, overloaded_constructor> x;
@@ -547,14 +545,15 @@
     BOOST_TEST(x.find(0) != x.end() &&
         x.find(0)->second == overloaded_constructor());
 
- x.emplace(1);
- BOOST_TEST(x.find(1) != x.end() &&
- x.find(1)->second == overloaded_constructor());
-
     x.emplace(2, 3);
     BOOST_TEST(x.find(2) != x.end() &&
         x.find(2)->second == overloaded_constructor(3));
 
+#if defined (BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
+ x.emplace(1);
+ BOOST_TEST(x.find(1) != x.end() &&
+ x.find(1)->second == overloaded_constructor());
+
     x.emplace(4, 5, 6);
     BOOST_TEST(x.find(4) != x.end() &&
         x.find(4)->second == overloaded_constructor(5, 6));
@@ -562,6 +561,7 @@
     x.emplace(7, 8, 9, 10);
     BOOST_TEST(x.find(7) != x.end() &&
         x.find(7)->second == overloaded_constructor(8, 9, 10));
+#endif
 }
 
 UNORDERED_AUTO_TEST(set_emplace_test)
@@ -593,6 +593,37 @@
     BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
 }
 
+UNORDERED_AUTO_TEST(map_emplace_test2)
+{
+ boost::unordered_map<overloaded_constructor, overloaded_constructor> x;
+
+ x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(), boost::make_tuple());
+ BOOST_TEST(x.find(overloaded_constructor()) != x.end() &&
+ x.find(overloaded_constructor())->second == overloaded_constructor());
+
+ x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(1), boost::make_tuple());
+ BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() &&
+ x.find(overloaded_constructor(1))->second == overloaded_constructor());
+
+ x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(2,3), boost::make_tuple(4,5,6));
+ BOOST_TEST(x.find(overloaded_constructor(2,3)) != x.end() &&
+ x.find(overloaded_constructor(2,3))->second == overloaded_constructor(4,5,6));
+}
+
+UNORDERED_AUTO_TEST(set_emplace_test2)
+{
+ boost::unordered_set<std::pair<overloaded_constructor, overloaded_constructor> > x;
+ std::pair<overloaded_constructor, overloaded_constructor> check;
+
+ x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(), boost::make_tuple());
+ BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
+
+ x.clear();
+ x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(1), boost::make_tuple(2,3));
+ check = std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3));;
+ BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
+}
+
 }
 
 RUN_TESTS()

Modified: branches/release/libs/unordered/test/unordered/unnecessary_copy_tests.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/unnecessary_copy_tests.cpp (original)
+++ branches/release/libs/unordered/test/unordered/unnecessary_copy_tests.cpp 2011-09-04 15:37:45 EDT (Sun, 04 Sep 2011)
@@ -1,4 +1,4 @@
-
+#include <iostream>
 // Copyright 2006-2009 Daniel James.
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -327,6 +327,13 @@
         x.emplace();
         COPY_COUNT(2); MOVE_COUNT(0);
 
+ reset();
+ x.emplace(boost::unordered::piecewise_construct,
+ boost::make_tuple(),
+ boost::make_tuple());
+ COPY_COUNT(2); MOVE_COUNT(0);
+
+
         //
         // 1 argument
         //
@@ -345,19 +352,23 @@
     (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 2) || \
     (defined(BOOST_MSVC) && BOOST_MSVC >= 1600 ) || \
     (!defined(__GNUC__) && !defined(BOOST_MSVC))
+
         count_copies part;
         reset();
         std::pair<count_copies const&, count_copies const&> a_ref(part, part);
         x.emplace(a_ref);
         COPY_COUNT(2); MOVE_COUNT(0);
+
 #endif
 
 #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+
         // No move should take place.
         // (since a is already in the container)
         reset();
         x.emplace(std::move(a));
         COPY_COUNT(0); MOVE_COUNT(0);
+
 #endif
 
         //
@@ -382,6 +393,47 @@
         reset();
         x.emplace(count_copies(b.first.tag_), count_copies(b.second.tag_));
         COPY_COUNT(2); MOVE_COUNT(0);
+
+ reset();
+ x.emplace(boost::unordered::piecewise_construct,
+ boost::make_tuple(boost::ref(b.first)),
+ boost::make_tuple(boost::ref(b.second)));
+ COPY_COUNT(0); MOVE_COUNT(0);
+
+#if !defined(BOOST_NO_0X_HDR_TUPLE) || defined(BOOST_HAS_TR1_TUPLE)
+
+ reset();
+ x.emplace(boost::unordered::piecewise_construct,
+ std::make_tuple(std::ref(b.first)),
+ std::make_tuple(std::ref(b.second)));
+ COPY_COUNT(0); MOVE_COUNT(0);
+
+ std::pair<count_copies const, count_copies> move_source_trial;
+ reset();
+ std::make_tuple(std::move(move_source_trial.first));
+ std::make_tuple(std::move(move_source_trial.second));
+ int tuple_move_cost = ::unnecessary_copy_tests::count_copies::moves;
+ int tuple_copy_cost = ::unnecessary_copy_tests::count_copies::copies;
+
+ std::pair<count_copies const, count_copies> move_source;
+ reset();
+ x.emplace(boost::unordered::piecewise_construct,
+ std::make_tuple(std::move(move_source.first)),
+ std::make_tuple(std::move(move_source.second)));
+ COPY_COUNT(tuple_copy_cost);
+ MOVE_COUNT(tuple_move_cost);
+
+#if defined(__GNUC__) && __GNUC__ > 4 || \
+ defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 6
+ reset();
+ x.emplace(boost::unordered::piecewise_construct,
+ std::forward_as_tuple(b.first),
+ std::forward_as_tuple(b.second));
+ COPY_COUNT(0); MOVE_COUNT(0);
+#endif
+
+#endif
+
     }
 }
 


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