Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r74859 - in branches/release: boost/unordered boost/unordered/detail libs/unordered libs/unordered/doc libs/unordered/test/exception libs/unordered/test/objects libs/unordered/test/unordered
From: dnljms_at_[hidden]
Date: 2011-10-09 14:30:15


Author: danieljames
Date: 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
New Revision: 74859
URL: http://svn.boost.org/trac/boost/changeset/74859

Log:
Unordered: Merge from trunk.

Anotehr overhaul. Can now use `void_pointer` for links between nodes, although
it doesn't as I don't think `void_pointer` support is strong enough in existing
allocators.

Also no longer relies on using base pointers for custome pointer types. And
scaled back member function detection to just detect if an allocator has a
member, not what its signature is. I found that the trait could be confused by
ambiguous overloads. This might be fixable.

Better documentation of C++11 compliance to come.

Added:
   branches/release/boost/unordered/detail/emplace_args.hpp
      - copied unchanged from r74857, /trunk/boost/unordered/detail/emplace_args.hpp
Removed:
   branches/release/boost/unordered/detail/node.hpp
Properties modified:
   branches/release/boost/unordered/ (props changed)
   branches/release/libs/unordered/ (props changed)
Text files modified:
   branches/release/boost/unordered/detail/allocator_helpers.hpp | 368 +++++++-----
   branches/release/boost/unordered/detail/buckets.hpp | 1107 +++++++++++++--------------------------
   branches/release/boost/unordered/detail/equivalent.hpp | 821 +++++++++++++++++++++++------
   branches/release/boost/unordered/detail/extract_key.hpp | 5
   branches/release/boost/unordered/detail/fwd.hpp | 8
   branches/release/boost/unordered/detail/table.hpp | 901 ++++++++++++++-----------------
   branches/release/boost/unordered/detail/unique.hpp | 815 +++++++++++++++++++---------
   branches/release/boost/unordered/detail/util.hpp | 214 ++-----
   branches/release/boost/unordered/unordered_map.hpp | 645 +++++++++-------------
   branches/release/boost/unordered/unordered_map_fwd.hpp | 10
   branches/release/boost/unordered/unordered_set.hpp | 656 ++++++++++-------------
   branches/release/boost/unordered/unordered_set_fwd.hpp | 10
   branches/release/libs/unordered/doc/ref.php | 11
   branches/release/libs/unordered/doc/ref.xml | 32
   branches/release/libs/unordered/test/exception/Jamfile.v2 | 4
   branches/release/libs/unordered/test/objects/minimal.hpp | 68 +
   branches/release/libs/unordered/test/unordered/Jamfile.v2 | 4
   branches/release/libs/unordered/test/unordered/allocator_traits.cpp | 19
   branches/release/libs/unordered/test/unordered/assign_tests.cpp | 5
   branches/release/libs/unordered/test/unordered/compile_set.cpp | 4
   branches/release/libs/unordered/test/unordered/compile_tests.hpp | 1
   branches/release/libs/unordered/test/unordered/constructor_tests.cpp | 2
   branches/release/libs/unordered/test/unordered/incomplete_test.cpp | 1
   branches/release/libs/unordered/test/unordered/unnecessary_copy_tests.cpp | 8
   24 files changed, 2917 insertions(+), 2802 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-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -19,34 +19,45 @@
 #include <boost/detail/select_type.hpp>
 #include <boost/utility/enable_if.hpp>
 #include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/enum.hpp>
 #include <boost/limits.hpp>
 #include <boost/type_traits/add_lvalue_reference.hpp>
+#include <boost/pointer_to_other.hpp>
+#include <boost/assert.hpp>
+#include <boost/utility/addressof.hpp>
 
 #if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
 # include <memory>
 #endif
 
 #if !defined(BOOST_NO_0X_HDR_TYPE_TRAITS)
-#include <type_traits>
+# include <type_traits>
+#endif
+
 namespace boost { namespace unordered { namespace detail {
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Integral_constrant, true_type, false_type
+ //
+ // Uses the standard versions if available.
+
+#if !defined(BOOST_NO_0X_HDR_TYPE_TRAITS)
+
     using std::integral_constant;
     using std::true_type;
     using std::false_type;
-}}}
+
 #else
-namespace boost { namespace unordered { namespace detail {
+
     template <typename T, T Value>
     struct integral_constant { enum { value = Value }; };
- typedef integral_constant<bool, true> true_type;
- typedef integral_constant<bool, false> false_type;
-}}}
-#endif
 
-// TODO: Use std::addressof if available?
-#include <boost/utility/addressof.hpp>
+ typedef boost::unordered::detail::integral_constant<bool, true> true_type;
+ typedef boost::unordered::detail::integral_constant<bool, false> false_type;
 
-namespace boost { namespace unordered { namespace detail {
+#endif
 
+ ////////////////////////////////////////////////////////////////////////////
     // Explicitly call a destructor
 
 #if defined(BOOST_MSVC)
@@ -63,21 +74,135 @@
 #pragma warning(pop)
 #endif
 
+ ////////////////////////////////////////////////////////////////////////////
+ // Bits and pieces for implementing traits
+ //
+ // Some of these are also used elsewhere
+
+ 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]; };
+ struct choice6 : choice7 { typedef char (&type)[6]; };
+ struct choice5 : choice6 { typedef char (&type)[5]; };
+ struct choice4 : choice5 { typedef char (&type)[4]; };
+ struct choice3 : choice4 { typedef char (&type)[3]; };
+ struct choice2 : choice3 { typedef char (&type)[2]; };
+ struct choice1 : choice2 { typedef char (&type)[1]; };
+ choice1 choose();
+
+ typedef choice1::type yes_type;
+ typedef choice2::type no_type;
+
+ struct private_type
+ {
+ private_type const &operator,(int) const;
+ };
+
+ template <typename T>
+ no_type is_private_type(T const&);
+ yes_type is_private_type(private_type const&);
+
+ struct convert_from_anything {
+ convert_from_anything(...);
+ };
+
+#if !defined(BOOST_NO_SFINAE_EXPR) || BOOST_WORKAROUND(BOOST_MSVC, >= 1500)
+
+# define BOOST_UNORDERED_HAVE_CALL_DETECTION 1
+
+ template <typename T, unsigned int> struct expr_test;
+ template <typename T> struct expr_test<T, sizeof(char)> : T {};
+ template <typename U> static char for_expr_test(U const&);
+
+#define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
+ template <typename U> \
+ static typename boost::unordered::detail::expr_test< \
+ BOOST_PP_CAT(choice, result), \
+ sizeof(boost::unordered::detail::for_expr_test(( \
+ (expression), \
+ 0)))>::type test( \
+ BOOST_PP_CAT(choice, count))
+
+#define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \
+ template <typename U> \
+ static BOOST_PP_CAT(choice, result)::type test( \
+ BOOST_PP_CAT(choice, count))
+
+#define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
+ struct BOOST_PP_CAT(has_, name) \
+ { \
+ BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \
+ boost::unordered::detail::make< thing >().name args); \
+ BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
+ \
+ enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) };\
+ }
+
+#else
+
+# define BOOST_UNORDERED_HAVE_CALL_DETECTION 0
+
+ template <typename T> struct identity { typedef T type; };
+
+#define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
+ \
+ typedef typename boost::unordered::detail::identity<member>::type \
+ BOOST_PP_CAT(check, count); \
+ \
+ template <BOOST_PP_CAT(check, count) e> \
+ struct BOOST_PP_CAT(test, count) { \
+ typedef BOOST_PP_CAT(choice, result) type; \
+ }; \
+ \
+ 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))
+
+#define BOOST_UNORDERED_HAS_MEMBER(name) \
+ struct BOOST_PP_CAT(has_, name) \
+ { \
+ struct impl { \
+ struct base_mixin { int name; }; \
+ struct base : public T, public base_mixin {}; \
+ \
+ BOOST_UNORDERED_CHECK_MEMBER(1, 1, name, int base_mixin::*); \
+ BOOST_UNORDERED_DEFAULT_MEMBER(2, 2); \
+ \
+ enum { value = sizeof(choice2::type) == \
+ sizeof(test<base>(choose())) \
+ }; \
+ }; \
+ \
+ enum { value = impl::value }; \
+ }
+
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Allocator traits
+ //
+ // Uses the standard versions if available.
+ // (although untested as I don't have access to a standard version yet)
+
 #if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
+
     template <typename Alloc>
     struct allocator_traits : std::allocator_traits<Alloc> {};
-
+
     template <typename Alloc, typename T>
     struct rebind_wrap
     {
- typedef typename allocator_traits<Alloc>::rebind_alloc<T> type;
+ typedef typename std::allocator_traits<Alloc>::rebind_alloc<T> type;
     };
+
 #else
- // rebind_wrap
- //
- // Rebind allocators. For some problematic libraries, use rebind_to
- // from <boost/detail/allocator_utilities.hpp>.
 
+ // TODO: Does this match std::allocator_traits<Alloc>::rebind_alloc<T>?
     template <typename Alloc, typename T>
     struct rebind_wrap
     {
@@ -85,18 +210,6 @@
             type;
     };
 
- 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]; };
- struct choice6 : choice7 { typedef char (&type)[6]; };
- struct choice5 : choice6 { typedef char (&type)[5]; };
- struct choice4 : choice5 { typedef char (&type)[4]; };
- struct choice3 : choice4 { typedef char (&type)[3]; };
- struct choice2 : choice3 { typedef char (&type)[2]; };
- struct choice1 : choice2 { typedef char (&type)[1]; };
- choice1 choose();
-
 #if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
 
     #define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
@@ -128,7 +241,8 @@
         struct default_type_ ## tname { \
                                                                             \
             template <typename X> \
- static typename sfinae<typename X::tname, choice1>::type \
+ static typename boost::unordered::detail::sfinae< \
+ typename X::tname, choice1>::type \
                 test(choice1); \
                                                                             \
             template <typename X> \
@@ -158,130 +272,72 @@
     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)
-
- template <typename T, unsigned int> struct expr_test;
- template <typename T> struct expr_test<T, sizeof(char)> : T {};
- template <typename U> static char for_expr_test(U const&);
-
-#define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
- template <typename U> \
- static typename expr_test< \
- BOOST_PP_CAT(choice, result), \
- sizeof(for_expr_test(((expression), 0)))>::type test( \
- BOOST_PP_CAT(choice, count))
-
-#define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \
- template <typename U> \
- 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) };\
- }
-
+#if BOOST_UNORDERED_HAVE_CALL_DETECTION
     template <typename T>
- BOOST_UNORDERED_HAS_EXPRESSION(
- select_on_container_copy_construction,
- make<U const>().select_on_container_copy_construction()
+ BOOST_UNORDERED_HAS_FUNCTION(
+ select_on_container_copy_construction, U const, (), 0
     );
 
- // 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>
+ BOOST_UNORDERED_HAS_FUNCTION(
+ max_size, U const, (), 0
     );
 
     template <typename T, typename ValueType>
- BOOST_UNORDERED_HAS_EXPRESSION(
- destroy,
- make<U>().destroy(make<ValueType*>())
+ BOOST_UNORDERED_HAS_FUNCTION(
+ construct, U, (
+ boost::unordered::detail::make<ValueType*>(),
+ boost::unordered::detail::make<ValueType const>()), 2
     );
 
- template <typename T>
- BOOST_UNORDERED_HAS_EXPRESSION(
- max_size,
- make<U const>().max_size()
+ template <typename T, typename ValueType>
+ BOOST_UNORDERED_HAS_FUNCTION(
+ destroy, U, (boost::unordered::detail::make<ValueType*>()), 1
     );
-
 #else
-
- template <typename T> struct identity { typedef T type; };
-
-#define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
- \
- typedef typename identity<member>::type BOOST_PP_CAT(check, count); \
- \
- template <BOOST_PP_CAT(check, count) e> \
- struct BOOST_PP_CAT(test, count) { \
- typedef BOOST_PP_CAT(choice, result) type; \
- }; \
- \
- 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))
-
+ template <typename T>
+ BOOST_UNORDERED_HAS_MEMBER(select_on_container_copy_construction);
 
     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_DEFAULT_MEMBER(2, 2);
-
- enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) };
- };
+ BOOST_UNORDERED_HAS_MEMBER(max_size);
 
- // 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 {};
+ template <typename T, typename ValueType>
+ BOOST_UNORDERED_HAS_MEMBER(construct);
 
+ template <typename T, typename ValueType>
+ BOOST_UNORDERED_HAS_MEMBER(destroy);
 #endif
 
     template <typename Alloc>
- inline typename boost::enable_if<
- has_select_on_container_copy_construction<Alloc>, Alloc
+ inline typename boost::enable_if_c<
+ boost::unordered::detail::
+ has_select_on_container_copy_construction<Alloc>::value, Alloc
>::type call_select_on_container_copy_construction(const Alloc& rhs)
     {
         return rhs.select_on_container_copy_construction();
     }
 
     template <typename Alloc>
- inline typename boost::disable_if<
- has_select_on_container_copy_construction<Alloc>, Alloc
+ inline typename boost::disable_if_c<
+ boost::unordered::detail::
+ has_select_on_container_copy_construction<Alloc>::value, 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)
+ inline typename boost::enable_if_c<
+ boost::unordered::detail::has_max_size<Alloc>::value, SizeType
+ >::type call_max_size(const Alloc& a)
     {
         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)
+ inline typename boost::disable_if_c<
+ boost::unordered::detail::has_max_size<Alloc>::value, SizeType
+ >::type call_max_size(const Alloc&)
     {
         return std::numeric_limits<SizeType>::max();
     }
@@ -295,26 +351,19 @@
         typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, pointer, value_type*)
             pointer;
 
- // For now always use the allocator's const_pointer.
-
- //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
- // typename pointer_traits<pointer>::
- // BOOST_NESTED_TEMPLATE rebind<const value_type>::other)
- // const_pointer;
+ template <typename T>
+ struct pointer_to_other : boost::pointer_to_other<pointer, T> {};
 
         typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
- value_type const*) const_pointer;
-
- // I'm not using void pointers for now.
+ typename pointer_to_other<const value_type>::type)
+ const_pointer;
 
         //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, void_pointer,
- // BOOST_NESTED_TEMPLATE pointer_traits<pointer>::
- // BOOST_NESTED_TEMPLATE rebind<void>::other)
+ // typename pointer_to_other<void>::type)
         // void_pointer;
-
+ //
         //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_void_pointer,
- // typename pointer_traits<pointer>::
- // BOOST_NESTED_TEMPLATE rebind<const void>::other)
+ // typename pointer_to_other<const void>::type)
         // const_void_pointer;
 
         typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, difference_type,
@@ -342,31 +391,35 @@
         // Only supporting the basic copy constructor for now.
 
         template <typename T>
- static void construct(Alloc& a, T* p, T const& x, typename
- boost::enable_if<has_construct<Alloc, T>, void*>::type = 0)
+ static typename boost::enable_if_c<
+ boost::unordered::detail::has_construct<Alloc, T>::value>::type
+ construct(Alloc& a, T* p, T const& x)
         {
             a.construct(p, x);
         }
 
         template <typename T>
- static void construct(Alloc&, T* p, T const& x, typename
- boost::disable_if<has_construct<Alloc, T>, void*>::type = 0)
+ static typename boost::disable_if_c<
+ boost::unordered::detail::has_construct<Alloc, T>::value>::type
+ construct(Alloc&, T* p, T const& x)
         {
             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)
+ static typename boost::enable_if_c<
+ boost::unordered::detail::has_destroy<Alloc, T>::value>::type
+ destroy(Alloc& a, T* p)
         {
             a.destroy(p);
         }
 
         template <typename T>
- static void destroy(Alloc&, T* p, typename
- boost::disable_if<has_destroy<Alloc, T>, void*>::type = 0)
+ static typename boost::disable_if_c<
+ boost::unordered::detail::has_destroy<Alloc, T>::value>::type
+ destroy(Alloc&, T* p)
         {
- ::boost::unordered::detail::destroy(p);
+ boost::unordered::detail::destroy(p);
         }
 
         static size_type max_size(const Alloc& a)
@@ -394,39 +447,42 @@
             Alloc,propagate_on_container_swap,false_type)
             propagate_on_container_swap;
     };
+
+#undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
+#undef BOOST_UNORDERED_DEFAULT_TYPE
+
 #endif
 
- // allocator_array_constructor
+ // array_constructor
     //
     // Allocate and construct an array in an exception safe manner, and
     // clean up if an exception is thrown before the container takes charge
     // of it.
 
     template <typename Allocator>
- struct allocator_array_constructor
+ struct array_constructor
     {
- typedef typename allocator_traits<Allocator>::pointer
- pointer;
+ typedef boost::unordered::detail::allocator_traits<Allocator> traits;
+ typedef typename traits::pointer pointer;
 
         Allocator& alloc_;
         pointer ptr_;
         pointer constructed_;
         std::size_t length_;
 
- allocator_array_constructor(Allocator& a)
+ array_constructor(Allocator& a)
             : alloc_(a), ptr_(), constructed_(), length_(0)
         {
             constructed_ = pointer();
             ptr_ = pointer();
         }
 
- ~allocator_array_constructor() {
+ ~array_constructor() {
             if (ptr_) {
                 for(pointer p = ptr_; p != constructed_; ++p)
- allocator_traits<Allocator>::destroy(alloc_,
- boost::addressof(*p));
+ traits::destroy(alloc_, boost::addressof(*p));
 
- allocator_traits<Allocator>::deallocate(alloc_, ptr_, length_);
+ traits::deallocate(alloc_, ptr_, length_);
             }
         }
 
@@ -435,11 +491,10 @@
         {
             BOOST_ASSERT(!ptr_);
             length_ = l;
- ptr_ = allocator_traits<Allocator>::allocate(alloc_, length_);
+ ptr_ = traits::allocate(alloc_, length_);
             pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
             for(constructed_ = ptr_; constructed_ != end; ++constructed_)
- allocator_traits<Allocator>::construct(alloc_,
- boost::addressof(*constructed_), v);
+ traits::construct(alloc_, boost::addressof(*constructed_), v);
         }
 
         pointer get() const
@@ -454,9 +509,8 @@
             return p;
         }
     private:
- allocator_array_constructor(allocator_array_constructor const&);
- allocator_array_constructor& operator=(
- allocator_array_constructor const&);
+ array_constructor(array_constructor const&);
+ array_constructor& operator=(array_constructor const&);
     };
 }}}
 

Modified: branches/release/boost/unordered/detail/buckets.hpp
==============================================================================
--- branches/release/boost/unordered/detail/buckets.hpp (original)
+++ branches/release/boost/unordered/detail/buckets.hpp 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -7,65 +7,221 @@
 #ifndef BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
 #define BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
 
-#include <boost/unordered/detail/node.hpp>
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/unordered/detail/util.hpp>
+#include <boost/unordered/detail/allocator_helpers.hpp>
+#include <boost/unordered/detail/emplace_args.hpp>
+#include <boost/type_traits/aligned_storage.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/swap.hpp>
+#include <boost/assert.hpp>
+
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+#pragma warning(disable:4127) // conditional expression is constant
+#endif
 
 namespace boost { namespace unordered { namespace detail {
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Now the main data structure:
- //
- // buckets<A, Unique> functions<H, P>
- // | |
- // +---------------+--------------+
- // |
- // table<T>
+
+ template <typename Types> struct table;
+ template <typename NodePointer> struct bucket;
+ struct ptr_bucket;
+ template <typename A, typename Bucket, typename Node> struct buckets;
+
+ ///////////////////////////////////////////////////////////////////
     //
- // T is a class which contains typedefs for all the types we need.
+ // Node construction
+
+ template <typename NodeAlloc>
+ struct node_constructor
+ {
+ private:
+
+ typedef NodeAlloc node_allocator;
+ typedef boost::unordered::detail::allocator_traits<NodeAlloc>
+ node_allocator_traits;
+ typedef typename node_allocator_traits::value_type node;
+ typedef typename node_allocator_traits::pointer node_pointer;
+ typedef typename node::value_type value_type;
+
+ node_allocator& alloc_;
+ node_pointer node_;
+ bool node_constructed_;
+ bool value_constructed_;
+
+ public:
+
+ node_constructor(node_allocator& n) :
+ alloc_(n),
+ node_(),
+ node_constructed_(false),
+ value_constructed_(false)
+ {
+ }
+
+ ~node_constructor();
+
+ void construct_node();
+
+ template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ void construct_value(BOOST_UNORDERED_EMPLACE_ARGS)
+ {
+ BOOST_ASSERT(node_ && node_constructed_ && !value_constructed_);
+ boost::unordered::detail::construct_impl(
+ node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
+ value_constructed_ = true;
+ }
+
+ template <typename A0>
+ void construct_value2(BOOST_FWD_REF(A0) a0)
+ {
+ BOOST_ASSERT(node_ && node_constructed_ && !value_constructed_);
+ boost::unordered::detail::construct_impl2(
+ node_->value_ptr(), boost::forward<A0>(a0));
+ value_constructed_ = true;
+ }
+
+ value_type const& value() const {
+ BOOST_ASSERT(node_ && node_constructed_ && value_constructed_);
+ return node_->value();
+ }
+
+ // no throw
+ node_pointer release()
+ {
+ node_pointer p = node_;
+ node_ = node_pointer();
+ return p;
+ }
+
+ private:
+ node_constructor(node_constructor const&);
+ node_constructor& operator=(node_constructor const&);
+ };
     
- // buckets
+ template <typename Alloc>
+ node_constructor<Alloc>::~node_constructor()
+ {
+ if (node_) {
+ if (value_constructed_) {
+ boost::unordered::detail::destroy(node_->value_ptr());
+ }
+
+ if (node_constructed_) {
+ node_allocator_traits::destroy(alloc_,
+ boost::addressof(*node_));
+ }
+
+ node_allocator_traits::deallocate(alloc_, node_, 1);
+ }
+ }
+
+ template <typename Alloc>
+ void node_constructor<Alloc>::construct_node()
+ {
+ if(!node_) {
+ node_constructed_ = false;
+ value_constructed_ = false;
+
+ node_ = node_allocator_traits::allocate(alloc_, 1);
+
+ node_allocator_traits::construct(alloc_,
+ boost::addressof(*node_), node());
+ node_->init(static_cast<typename node::link_pointer>(node_));
+ node_constructed_ = true;
+ }
+ else {
+ BOOST_ASSERT(node_constructed_);
+
+ if (value_constructed_)
+ {
+ boost::unordered::detail::destroy(node_->value_ptr());
+ value_constructed_ = false;
+ }
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////
     //
- // This is responsible for allocating and deallocating buckets and nodes.
+ // Bucket
+
+ template <typename NodePointer>
+ struct bucket
+ {
+ typedef NodePointer previous_pointer;
+ previous_pointer next_;
+
+ bucket() : next_() {}
+
+ previous_pointer first_from_start()
+ {
+ return next_;
+ }
+
+ enum { extra_node = true };
+ };
+
+ struct ptr_bucket
+ {
+ typedef ptr_bucket* previous_pointer;
+ previous_pointer next_;
+
+ ptr_bucket() : next_(0) {}
+
+ previous_pointer first_from_start()
+ {
+ return this;
+ }
+
+ enum { extra_node = false };
+ };
+
+ ///////////////////////////////////////////////////////////////////
     //
- // Notes:
- // 1. For the sake exception safety the consturctors don't allocate
- // anything.
- // 2. It's the callers responsibility to allocate the buckets before calling
- // any of the methods (other than getters and setters).
+ // Buckets
 
- template <class A, bool Unique>
- class buckets
+ template <typename A, typename Bucket, typename Node>
+ struct buckets
     {
+ private:
         buckets(buckets const&);
         buckets& operator=(buckets const&);
     public:
- // Types
-
- typedef typename ::boost::detail::if_true<Unique>::
- BOOST_NESTED_TEMPLATE then<
- ::boost::unordered::detail::ungrouped_node<A>,
- ::boost::unordered::detail::grouped_node<A>
- >::type node;
-
- typedef A value_allocator;
- typedef ::boost::unordered::detail::bucket<A> bucket;
- typedef typename allocator_traits<A>::value_type value_type;
-
- 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::unordered::detail::allocator_traits<A> traits;
+ typedef typename traits::value_type value_type;
 
- typedef typename rebind_wrap<value_allocator, node>::type
+ typedef Node node;
+ typedef Bucket bucket;
+ typedef typename boost::unordered::detail::rebind_wrap<A, node>::type
             node_allocator;
- typedef typename allocator_traits<node_allocator>::pointer real_node_ptr;
+ typedef typename boost::unordered::detail::rebind_wrap<A, bucket>::type
+ bucket_allocator;
+ typedef boost::unordered::detail::allocator_traits<node_allocator>
+ node_allocator_traits;
+ typedef boost::unordered::detail::allocator_traits<bucket_allocator>
+ bucket_allocator_traits;
+ typedef typename node_allocator_traits::pointer
+ node_pointer;
+ typedef typename node_allocator_traits::const_pointer
+ const_node_pointer;
+ typedef typename bucket_allocator_traits::pointer
+ bucket_pointer;
+ typedef typename bucket::previous_pointer
+ previous_pointer;
+ typedef boost::unordered::detail::node_constructor<node_allocator>
+ node_constructor;
 
         // Members
 
- bucket_ptr buckets_;
+ bucket_pointer buckets_;
         std::size_t bucket_count_;
         std::size_t size_;
- compressed_pair<bucket_allocator, node_allocator> allocators_;
-
+ boost::unordered::detail::compressed<bucket_allocator, node_allocator>
+ allocators_;
+
         // Data access
 
         bucket_allocator const& bucket_alloc() const
@@ -91,22 +247,73 @@
         std::size_t max_bucket_count() const
         {
             // -1 to account for the start bucket.
- return prev_prime(allocator_traits<bucket_allocator>::max_size(bucket_alloc()) - 1);
+ return boost::unordered::detail::prev_prime(
+ bucket_allocator_traits::max_size(bucket_alloc()) - 1);
+ }
+
+ bucket_pointer get_bucket(std::size_t bucket_index) const
+ {
+ return buckets_ + static_cast<std::ptrdiff_t>(bucket_index);
+ }
+
+ previous_pointer get_previous_start() const
+ {
+ return this->get_bucket(this->bucket_count_)->first_from_start();
+ }
+
+ previous_pointer get_previous_start(std::size_t bucket_index) const
+ {
+ return this->get_bucket(bucket_index)->next_;
+ }
+
+ node_pointer get_start() const
+ {
+ return static_cast<node_pointer>(this->get_previous_start()->next_);
+ }
+
+ node_pointer get_start(std::size_t bucket_index) const
+ {
+ previous_pointer prev = this->get_previous_start(bucket_index);
+ return prev ? static_cast<node_pointer>(prev->next_) :
+ node_pointer();
+ }
+
+ float load_factor() const
+ {
+ BOOST_ASSERT(this->bucket_count_ != 0);
+ return static_cast<float>(this->size_)
+ / static_cast<float>(this->bucket_count_);
+ }
+
+ std::size_t bucket_size(std::size_t index) const
+ {
+ if (!this->size_) return 0;
+ node_pointer ptr = this->get_start(index);
+ if (!ptr) return 0;
+
+ std::size_t count = 0;
+ while(ptr && ptr->hash_ % this->bucket_count_ == index)
+ {
+ ++count;
+ ptr = static_cast<node_pointer>(ptr->next_);
+ }
+
+ return count;
         }
 
         ////////////////////////////////////////////////////////////////////////
- // Constructors and Destructors
+ // Constructors
 
- buckets(node_allocator const& a, std::size_t bucket_count)
- : buckets_(),
+ buckets(node_allocator const& a, std::size_t bucket_count) :
+ buckets_(),
             bucket_count_(bucket_count),
             size_(),
             allocators_(a,a)
         {
         }
 
- buckets(buckets& b, move_tag m)
- : buckets_(),
+ buckets(buckets& b, boost::unordered::detail::move_tag m) :
+ buckets_(),
             bucket_count_(b.bucket_count_),
             size_(),
             allocators_(b.allocators_, m)
@@ -114,50 +321,59 @@
             swap(b);
         }
 
- template <typename T>
- buckets(table<T>& x, move_tag m)
- : buckets_(),
+ template <typename Types>
+ buckets(boost::unordered::detail::table<Types>& x,
+ boost::unordered::detail::move_tag m) :
+ buckets_(),
             bucket_count_(x.bucket_count_),
+ size_(),
             allocators_(x.allocators_, m)
         {
             swap(x);
- x.size_ = 0;
- }
-
- inline ~buckets()
- {
- if(this->buckets_) { this->delete_buckets(); }
         }
 
+ ////////////////////////////////////////////////////////////////////////
+ // Create buckets
+ // (never called in constructor to avoid exception issues)
+
         void create_buckets()
         {
- // The array constructor will clean up in the event of an
- // exception.
- allocator_array_constructor<bucket_allocator>
+ boost::unordered::detail::array_constructor<bucket_allocator>
                 constructor(bucket_alloc());
     
             // Creates an extra bucket to act as the start node.
             constructor.construct(bucket(), this->bucket_count_ + 1);
     
- // Only release the buckets once everything is successfully
- // done.
+ if (bucket::extra_node)
+ {
+ node_constructor a(this->node_alloc());
+ a.construct_node();
+
+ (constructor.get() +
+ static_cast<std::ptrdiff_t>(this->bucket_count_))->next_ =
+ a.release();
+ }
+
             this->buckets_ = constructor.release();
         }
-
+
+ ////////////////////////////////////////////////////////////////////////
+ // Swap and Move
+
         void swap(buckets& other, false_type = false_type())
         {
             BOOST_ASSERT(node_alloc() == other.node_alloc());
- std::swap(buckets_, other.buckets_);
- std::swap(bucket_count_, other.bucket_count_);
- std::swap(size_, other.size_);
+ boost::swap(buckets_, other.buckets_);
+ boost::swap(bucket_count_, other.bucket_count_);
+ boost::swap(size_, other.size_);
         }
 
         void swap(buckets& other, true_type)
         {
             allocators_.swap(other.allocators_);
- std::swap(buckets_, other.buckets_);
- std::swap(bucket_count_, other.bucket_count_);
- std::swap(size_, other.size_);
+ boost::swap(buckets_, other.buckets_);
+ boost::swap(bucket_count_, other.bucket_count_);
+ boost::swap(size_, other.size_);
         }
 
         void move_buckets_from(buckets& other)
@@ -167,189 +383,137 @@
             this->buckets_ = other.buckets_;
             this->bucket_count_ = other.bucket_count_;
             this->size_ = other.size_;
- other.buckets_ = bucket_ptr();
+ other.buckets_ = bucket_pointer();
             other.bucket_count_ = 0;
             other.size_ = 0;
         }
 
- std::size_t bucket_size(std::size_t index) const
+ ////////////////////////////////////////////////////////////////////////
+ // Delete/destruct
+
+ inline void delete_node(node_pointer n)
+ {
+ boost::unordered::detail::destroy(n->value_ptr());
+ node_allocator_traits::destroy(node_alloc(), boost::addressof(*n));
+ node_allocator_traits::deallocate(node_alloc(), n, 1);
+ --size_;
+ }
+
+ std::size_t delete_nodes(node_pointer begin, node_pointer end)
         {
- if (!this->size_) return 0;
- node_ptr ptr = this->buckets_[index].next_;
- if (!ptr) return 0;
- ptr = ptr->next_;
-
             std::size_t count = 0;
- while(BOOST_UNORDERED_BORLAND_BOOL(ptr) &&
- node::get_hash(ptr) % this->bucket_count_ == index)
- {
+
+ while(begin != end) {
+ node_pointer n = begin;
+ begin = static_cast<node_pointer>(begin->next_);
+ delete_node(n);
                 ++count;
- ptr = ptr->next_;
             }
-
+
             return count;
         }
 
- node_ptr bucket_begin(std::size_t bucket_index) const
- {
- if (!this->size_) return node_ptr();
- bucket& b = this->buckets_[bucket_index];
- if (!b.next_) return node_ptr();
- return b.next_->next_;
- }
+ inline void delete_extra_node(bucket_pointer) {}
 
- // For the remaining functions, buckets_ must not be null.
-
- bucket_ptr get_bucket(std::size_t bucket_index) const
- {
- return buckets_ + static_cast<std::ptrdiff_t>(bucket_index);
+ inline void delete_extra_node(node_pointer n) {
+ node_allocator_traits::destroy(node_alloc(), boost::addressof(*n));
+ node_allocator_traits::deallocate(node_alloc(), n, 1);
         }
 
- float load_factor() const
+ inline ~buckets()
         {
- BOOST_ASSERT(this->bucket_count_ != 0);
- return static_cast<float>(this->size_)
- / static_cast<float>(this->bucket_count_);
+ this->delete_buckets();
         }
 
- ////////////////////////////////////////////////////////////////////////
- // Delete
-
- void delete_node(node_ptr n)
+ void delete_buckets()
         {
- node* raw_ptr = static_cast<node*>(boost::addressof(*n));
- real_node_ptr real_ptr(node_alloc().address(*raw_ptr));
+ if(this->buckets_) {
+ previous_pointer prev = this->get_previous_start();
 
- ::boost::unordered::detail::destroy(raw_ptr->value_ptr());
- allocator_traits<node_allocator>::destroy(node_alloc(), raw_ptr);
- allocator_traits<node_allocator>::deallocate(node_alloc(), real_ptr, 1);
+ while(prev->next_) {
+ node_pointer n = static_cast<node_pointer>(prev->next_);
+ prev->next_ = n->next_;
+ delete_node(n);
+ }
 
- --this->size_;
- }
+ delete_extra_node(prev);
 
- void delete_buckets()
- {
- bucket_ptr end = this->get_bucket(this->bucket_count_);
- node_ptr n = (end)->next_;
- while(BOOST_UNORDERED_BORLAND_BOOL(n))
- {
- node_ptr node_to_delete = n;
- n = n->next_;
- delete_node(node_to_delete);
- }
+ bucket_pointer end = this->get_bucket(this->bucket_count_ + 1);
+ for(bucket_pointer it = this->buckets_; it != end; ++it)
+ {
+ bucket_allocator_traits::destroy(bucket_alloc(),
+ boost::addressof(*it));
+ }
+
+ bucket_allocator_traits::deallocate(bucket_alloc(),
+ this->buckets_, this->bucket_count_ + 1);
     
- ++end;
- for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
- allocator_traits<bucket_allocator>::destroy(bucket_alloc(),
- boost::addressof(*begin));
+ this->buckets_ = bucket_pointer();
             }
-
- allocator_traits<bucket_allocator>::deallocate(bucket_alloc(), this->buckets_, this->bucket_count_ + 1);
-
- this->buckets_ = bucket_ptr();
- BOOST_ASSERT(this->size_ == 0);
- }
 
- std::size_t delete_nodes(node_ptr begin, node_ptr end)
- {
- std::size_t count = 0;
- while(begin != end) {
- node_ptr n = begin;
- begin = begin->next_;
- delete_node(n);
- ++count;
- }
- return count;
+ BOOST_ASSERT(!this->size_);
         }
 
         void clear()
         {
             if(!this->size_) return;
-
- bucket_ptr end = this->get_bucket(this->bucket_count_);
-
- node_ptr n = (end)->next_;
- while(BOOST_UNORDERED_BORLAND_BOOL(n))
- {
- node_ptr node_to_delete = n;
- n = n->next_;
- this->delete_node(node_to_delete);
- }
-
- ++end;
- for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
- begin->next_ = bucket_ptr();
+
+ previous_pointer prev = this->get_previous_start();
+
+ while(prev->next_) {
+ node_pointer n = static_cast<node_pointer>(prev->next_);
+ prev->next_ = n->next_;
+ delete_node(n);
             }
-
- this->size_ = 0;
- }
 
- node_ptr erase(node_ptr r)
- {
- BOOST_ASSERT(r);
- node_ptr next = r->next_;
-
- bucket_ptr bucket = this->get_bucket(
- node::get_hash(r) % this->bucket_count_);
- node_ptr prev = node::unlink_node(*bucket, r);
-
- this->fix_buckets(bucket, prev, next);
-
- this->delete_node(r);
-
- return next;
- }
+ bucket_pointer end = this->get_bucket(this->bucket_count_);
+ for(bucket_pointer it = this->buckets_; it != end; ++it)
+ {
+ it->next_ = node_pointer();
+ }
 
- node_ptr erase_range(node_ptr r1, node_ptr r2)
- {
- if (r1 == r2) return r2;
-
- std::size_t bucket_index = node::get_hash(r1) % this->bucket_count_;
- node_ptr prev = node::unlink_nodes(
- this->buckets_[bucket_index], r1, r2);
- this->fix_buckets_range(bucket_index, prev, r1, r2);
- this->delete_nodes(r1, r2);
-
- return r2;
+ BOOST_ASSERT(!this->size_);
         }
 
         // This is called after erasing a node or group of nodes to fix up
         // the bucket pointers.
- void fix_buckets(bucket_ptr bucket, node_ptr prev, node_ptr next)
+ void fix_buckets(bucket_pointer bucket,
+ previous_pointer prev, node_pointer next)
         {
             if (!next)
             {
- if (bucket->next_ == prev) bucket->next_ = node_ptr();
+ if (bucket->next_ == prev) bucket->next_ = node_pointer();
             }
             else
             {
- bucket_ptr next_bucket = this->get_bucket(
- node::get_hash(next) % this->bucket_count_);
+ bucket_pointer next_bucket = this->get_bucket(
+ next->hash_ % this->bucket_count_);
+
                 if (next_bucket != bucket)
                 {
                     next_bucket->next_ = prev;
- if (bucket->next_ == prev) bucket->next_ = node_ptr();
+ if (bucket->next_ == prev) bucket->next_ = node_pointer();
                 }
             }
         }
 
         // This is called after erasing a range of nodes to fix any bucket
         // pointers into that range.
- void fix_buckets_range(
- std::size_t bucket_index, node_ptr prev, node_ptr begin, node_ptr end)
+ void fix_buckets_range(std::size_t bucket_index,
+ previous_pointer prev, node_pointer begin, node_pointer end)
         {
- node_ptr n = begin;
+ node_pointer n = begin;
     
             // If we're not at the start of the current bucket, then
             // go to the start of the next bucket.
             if (this->get_bucket(bucket_index)->next_ != prev)
             {
                 for(;;) {
- n = n->next_;
+ n = static_cast<node_pointer>(n->next_);
                     if (n == end) return;
     
                     std::size_t new_bucket_index =
- node::get_hash(n) % this->bucket_count_;
+ n->hash_ % this->bucket_count_;
                     if (bucket_index != new_bucket_index) {
                         bucket_index = new_bucket_index;
                         break;
@@ -359,49 +523,30 @@
     
             // Iterate through the remaining nodes, clearing out the bucket
             // pointers.
- this->buckets_[bucket_index].next_ = bucket_ptr();
+ this->get_bucket(bucket_index)->next_ = previous_pointer();
             for(;;) {
- n = n->next_;
+ n = static_cast<node_pointer>(n->next_);
                 if (n == end) break;
     
                 std::size_t new_bucket_index =
- node::get_hash(n) % this->bucket_count_;
+ n->hash_ % this->bucket_count_;
                 if (bucket_index != new_bucket_index) {
                     bucket_index = new_bucket_index;
- this->buckets_[bucket_index].next_ = bucket_ptr();
+ this->get_bucket(bucket_index)->next_ = previous_pointer();
                 }
             };
     
             // Finally fix the bucket containing the trailing node.
- if (BOOST_UNORDERED_BORLAND_BOOL(n)) {
- this->buckets_[node::get_hash(n) % this->bucket_count_].next_
+ if (n) {
+ this->get_bucket(n->hash_ % this->bucket_count_)->next_
                     = prev;
             }
         }
-
- // Iterate through the nodes placing them in the correct buckets.
- // pre: prev->next_ is not null.
- node_ptr place_in_bucket(node_ptr prev, node_ptr end) {
- bucket_ptr b = this->get_bucket(node::get_hash(prev->next_) % this->bucket_count_);
-
- if (!b->next_) {
- b->next_ = prev;
- return end;
- }
- else {
- node_ptr next = end->next_;
- end->next_ = b->next_->next_;
- b->next_->next_ = prev->next_;
- prev->next_ = next;
- return prev;
- }
- }
-
- void copy_buckets_to(buckets&) const;
- void move_buckets_to(buckets&) const;
- void rehash_impl(std::size_t);
     };
 
+ ////////////////////////////////////////////////////////////////////////////
+ // Functions
+
     // Assigning and swapping the equality and hash function objects
     // needs strong exception safety. To implement that normally we'd
     // require one of them to be known to not throw and the other to
@@ -418,13 +563,14 @@
     template <class H, class P>
     class functions
     {
- friend class set_hash_functions<H, P>;
+ friend class boost::unordered::detail::set_hash_functions<H, P>;
         functions& operator=(functions const&);
 
- typedef compressed_pair<H, P> function_pair;
- typedef typename ::boost::aligned_storage<
+ typedef compressed<H, P> function_pair;
+
+ typedef typename boost::aligned_storage<
             sizeof(function_pair),
- ::boost::alignment_of<function_pair>::value>::type aligned_function;
+ boost::alignment_of<function_pair>::value>::type aligned_function;
 
         bool current_; // The currently active functions.
         aligned_function funcs_[2];
@@ -446,7 +592,7 @@
         
         void destroy(bool which)
         {
- ::boost::unordered::detail::destroy((function_pair*)(&funcs_[which]));
+ boost::unordered::detail::destroy((function_pair*)(&funcs_[which]));
         }
         
     public:
@@ -464,7 +610,7 @@
         }
 
         ~functions() {
- destroy(current_);
+ this->destroy(current_);
         }
 
         H const& hash_function() const {
@@ -512,517 +658,10 @@
             tmp_functions_ = !tmp_functions_;
         }
     };
+}}}
 
- ////////////////////////////////////////////////////////////////////////////
- //
- // Value Construction
-
-#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<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)
- {
- new(address) T();
- }
-
- template <class T, class Arg1>
- inline typename normal_construct1<T, Arg1>::type
- construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1)
- {
- new(address) T(
- boost::forward<Arg1>(arg1)
- );
- }
-
- template <class T, class Arg1>
- inline typename pair_construct1<T, Arg1>::type
- construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1)
- {
- 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, BOOST_FWD_REF(Arg1) arg1,
- BOOST_FWD_REF(Arg2) arg2)
- {
- new(address) T(
- boost::forward<Arg1>(arg1),
- boost::forward<Arg2>(arg2));
- }
-
- 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)
- {
- 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 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));
- }
-
- 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>(arg1),
- boost::forward<Arg2>(arg2),
- boost::forward<Arg3>(arg3));
- }
-
-#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(
- 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, 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 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(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 typename pair_construct_n<T>::type \
- construct_impl(void* address, BOOST_FWD_REF(Key) key, \
- BOOST_UNORDERED_FUNCTION_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(3, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL, _)
-
-#undef BOOST_UNORDERED_CONSTRUCT_IMPL
-#endif
-
- ///////////////////////////////////////////////////////////////////
- //
- // Node construction
-
- template <class Alloc, bool Unique>
- class node_constructor
- {
- typedef ::boost::unordered::detail::buckets<Alloc, Unique> buckets;
- typedef 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_;
- bool node_constructed_;
- bool value_constructed_;
-
- public:
-
- node_constructor(buckets& m) :
- buckets_(m),
- node_(),
- node_constructed_(false),
- value_constructed_(false)
- {
- }
-
- ~node_constructor();
- void construct_preamble();
-
-#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
- template <class... Args>
- void construct(Args&&... args)
- {
- construct_preamble();
- construct_impl<value_type>(node_->address(),
- std::forward<Args>(args)...);
- value_constructed_ = true;
- }
-#else
-
-#define BOOST_UNORDERED_CONSTRUCT(z, num_params, _) \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
- > \
- void construct( \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
- ) \
- { \
- construct_preamble(); \
- construct_impl<value_type>(node_->address(), \
- BOOST_UNORDERED_CALL_PARAMS(z, num_params) \
- ); \
- value_constructed_ = true; \
- }
-
- BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_CONSTRUCT, _)
-
-#undef BOOST_UNORDERED_CONSTRUCT
-
-#endif
- template <class K, class M>
- void construct_pair(K const& k, M*)
- {
- construct_preamble();
- new(node_->address()) value_type(k, M());
- value_constructed_ = true;
- }
-
- value_type& value() const
- {
- BOOST_ASSERT(node_);
- return node_->value();
- }
-
- // no throw
- typename buckets::node_ptr release()
- {
- real_node_ptr p = node_;
- node_ = real_node_ptr();
- // node_ptr cast
- return buckets_.bucket_alloc().address(*p);
- }
-
- private:
- node_constructor(node_constructor const&);
- node_constructor& operator=(node_constructor const&);
- };
-
- // node_constructor
-
- template <class Alloc, bool Unique>
- inline node_constructor<Alloc, Unique>::~node_constructor()
- {
- if (node_) {
- if (value_constructed_) {
-#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
- struct dummy { node<Alloc, Grouped> x; };
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
 #endif
- ::boost::unordered::detail::destroy(node_->value_ptr());
- }
-
- if (node_constructed_)
- allocator_traits<node_allocator>::destroy(buckets_.node_alloc(),
- boost::addressof(*node_));
-
- allocator_traits<node_allocator>::deallocate(buckets_.node_alloc(), node_, 1);
- }
- }
-
- template <class Alloc, bool Unique>
- inline void node_constructor<Alloc, Unique>::construct_preamble()
- {
- if(!node_) {
- node_constructed_ = false;
- value_constructed_ = false;
-
- node_ = allocator_traits<node_allocator>::allocate(buckets_.node_alloc(), 1);
- allocator_traits<node_allocator>::construct(buckets_.node_alloc(),
- boost::addressof(*node_), node());
- node_->init(buckets_.bucket_alloc().address(*node_));
-
- node_constructed_ = true;
- }
- else {
- BOOST_ASSERT(node_constructed_ && value_constructed_);
- ::boost::unordered::detail::destroy(node_->value_ptr());
- value_constructed_ = false;
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // copy_buckets_to
- //
- // basic exception safety. If an exception is thrown this will
- // leave dst partially filled and the buckets unset.
-
- template <class A, bool Unique>
- void buckets<A, Unique>::copy_buckets_to(buckets& dst) const
- {
- BOOST_ASSERT(!dst.buckets_);
-
- dst.create_buckets();
- bucket_ptr dst_start = dst.get_bucket(dst.bucket_count_);
-
- {
- node_constructor<A, Unique> a(dst);
-
- node_ptr n = this->buckets_[this->bucket_count_].next_;
- node_ptr prev = dst_start;
-
- while(n) {
- std::size_t hash = node::get_hash(n);
- node_ptr group_end = node::next_group(n);
-
- a.construct(node::get_value(n));
- node_ptr first_node = a.release();
- node::set_hash(first_node, hash);
- node_ptr end = prev->next_ = first_node;
- ++dst.size_;
-
- for(n = n->next_; n != group_end; n = n->next_) {
- a.construct(node::get_value(n));
- end = a.release();
- node::set_hash(end, hash);
- node::add_after_node(end, first_node);
- ++dst.size_;
- }
-
- prev = dst.place_in_bucket(prev, end);
- }
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // move_buckets_to
- //
- // Basic exception safety. The source nodes are left in an unusable state
- // if an exception throws.
-
- template <class A, bool Unique>
- void buckets<A, Unique>::move_buckets_to(buckets& dst) const
- {
- BOOST_ASSERT(!dst.buckets_);
-
- dst.create_buckets();
- bucket_ptr dst_start = dst.get_bucket(dst.bucket_count_);
-
- {
- node_constructor<A, Unique> a(dst);
-
- node_ptr n = this->buckets_[this->bucket_count_].next_;
- node_ptr prev = dst_start;
-
- while(n) {
- std::size_t hash = node::get_hash(n);
- node_ptr group_end = node::next_group(n);
-
- a.construct(boost::move(node::get_value(n)));
- node_ptr first_node = a.release();
- node::set_hash(first_node, hash);
- node_ptr end = prev->next_ = first_node;
- ++dst.size_;
-
- for(n = n->next_; n != group_end; n = n->next_) {
- a.construct(boost::move(node::get_value(n)));
- end = a.release();
- node::set_hash(end, hash);
- node::add_after_node(end, first_node);
- ++dst.size_;
- }
-
- prev = dst.place_in_bucket(prev, end);
- }
- }
- }
-
- // strong otherwise exception safety
- template <class A, bool Unique>
- void buckets<A, Unique>::rehash_impl(std::size_t num_buckets)
- {
- BOOST_ASSERT(this->size_);
-
- buckets dst(this->node_alloc(), num_buckets);
- dst.create_buckets();
-
- bucket_ptr src_start = this->get_bucket(this->bucket_count_);
- bucket_ptr dst_start = dst.get_bucket(dst.bucket_count_);
-
- dst_start->next_ = src_start->next_;
- src_start->next_ = bucket_ptr();
- dst.size_ = this->size_;
- this->size_ = 0;
-
- node_ptr prev = dst_start;
- while (BOOST_UNORDERED_BORLAND_BOOL(prev->next_))
- prev = dst.place_in_bucket(prev, node::next_group2(prev));
-
- // Swap the new nodes back into the container and setup the
- // variables.
- dst.swap(*this); // no throw
- }
-}}}
 
 #endif

Modified: branches/release/boost/unordered/detail/equivalent.hpp
==============================================================================
--- branches/release/boost/unordered/detail/equivalent.hpp (original)
+++ branches/release/boost/unordered/detail/equivalent.hpp 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -7,60 +7,278 @@
 #ifndef BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
 #define BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
 
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/unordered/detail/table.hpp>
+#include <boost/unordered/detail/emplace_args.hpp>
 #include <boost/unordered/detail/extract_key.hpp>
 
 namespace boost { namespace unordered { namespace detail {
 
- template <class T>
- class equivalent_table : public T::table_base
+ template <typename A, typename T> struct grouped_node;
+ template <typename T> struct grouped_ptr_node;
+ template <typename Types> struct grouped_table_impl;
+
+ template <typename A, typename T>
+ struct grouped_node :
+ boost::unordered::detail::value_base<T>
+ {
+ typedef typename ::boost::unordered::detail::rebind_wrap<
+ A, grouped_node<A, T> >::type::pointer link_pointer;
+
+ link_pointer next_;
+ link_pointer group_prev_;
+ std::size_t hash_;
+
+ grouped_node() :
+ next_(),
+ group_prev_(),
+ hash_(0)
+ {}
+
+ void init(link_pointer self)
+ {
+ group_prev_ = self;
+ }
+ };
+
+ template <typename T>
+ struct grouped_ptr_node :
+ boost::unordered::detail::value_base<T>,
+ boost::unordered::detail::ptr_bucket
+ {
+ typedef boost::unordered::detail::ptr_bucket bucket_base;
+ typedef ptr_bucket* link_pointer;
+
+ link_pointer group_prev_;
+ std::size_t hash_;
+
+ grouped_ptr_node() :
+ bucket_base(),
+ group_prev_(0),
+ hash_(0)
+ {}
+
+ void init(link_pointer self)
+ {
+ group_prev_ = self;
+ }
+ };
+
+ // If the allocator uses raw pointers use grouped_ptr_node
+ // Otherwise use grouped_node.
+
+ template <typename A, typename T, typename NodePtr, typename BucketPtr>
+ struct pick_grouped_node2
+ {
+ typedef boost::unordered::detail::grouped_node<A, T> node;
+
+ typedef typename boost::unordered::detail::allocator_traits<
+ typename boost::unordered::detail::rebind_wrap<A, node>::type
+ >::pointer node_pointer;
+
+ typedef boost::unordered::detail::bucket<node_pointer> bucket;
+ typedef node_pointer link_pointer;
+ };
+
+ template <typename A, typename T>
+ struct pick_grouped_node2<A, T,
+ boost::unordered::detail::grouped_ptr_node<T>*,
+ boost::unordered::detail::ptr_bucket*>
     {
- public:
- 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 boost::unordered::detail::grouped_ptr_node<T> node;
+ typedef boost::unordered::detail::ptr_bucket bucket;
+ typedef bucket* link_pointer;
+ };
+
+ template <typename A, typename T>
+ struct pick_grouped_node
+ {
+ typedef boost::unordered::detail::allocator_traits<
+ typename boost::unordered::detail::rebind_wrap<A,
+ boost::unordered::detail::grouped_ptr_node<T> >::type
+ > tentative_node_traits;
+
+ typedef boost::unordered::detail::allocator_traits<
+ typename boost::unordered::detail::rebind_wrap<A,
+ boost::unordered::detail::ptr_bucket >::type
+ > tentative_bucket_traits;
+
+ typedef pick_grouped_node2<A, T,
+ typename tentative_node_traits::pointer,
+ typename tentative_bucket_traits::pointer> pick;
+
+ typedef typename pick::node node;
+ typedef typename pick::bucket bucket;
+ typedef typename pick::link_pointer link_pointer;
+ };
+
+ template <typename A, typename H, typename P>
+ struct multiset
+ {
+ typedef boost::unordered::detail::multiset<A, H, P> types;
+
+ typedef A allocator;
+ typedef H hasher;
+ typedef P key_equal;
+
+ typedef boost::unordered::detail::allocator_traits<A> traits;
+ typedef typename traits::value_type value_type;
+ typedef value_type key_type;
+
+ typedef boost::unordered::detail::pick_grouped_node<A, value_type> pick;
+ typedef typename pick::node node;
+ typedef typename pick::bucket bucket;
+ typedef typename pick::link_pointer link_pointer;
+
+ typedef boost::unordered::detail::grouped_table_impl<types> table;
+ typedef boost::unordered::detail::set_extractor<value_type> extractor;
+ };
+
+ template <typename A, typename K, typename H, typename P>
+ struct multimap
+ {
+ typedef boost::unordered::detail::multimap<A, K, H, P> types;
+
+ typedef A allocator;
+ typedef H hasher;
+ typedef P key_equal;
+ typedef K key_type;
+
+ typedef boost::unordered::detail::allocator_traits<A> traits;
+ typedef typename traits::value_type value_type;
+
+ typedef boost::unordered::detail::pick_grouped_node<A, value_type> pick;
+ typedef typename pick::node node;
+ typedef typename pick::bucket bucket;
+ typedef typename pick::link_pointer link_pointer;
+
+ typedef boost::unordered::detail::grouped_table_impl<types> table;
+ typedef boost::unordered::detail::map_extractor<key_type, value_type>
+ extractor;
+ };
+
+ template <typename Types>
+ struct grouped_table_impl : boost::unordered::detail::table<Types>
+ {
+ typedef boost::unordered::detail::table<Types> table;
+ typedef typename table::value_type value_type;
+ typedef typename table::bucket bucket;
+ typedef typename table::buckets buckets;
+ typedef typename table::node_pointer node_pointer;
+ typedef typename table::node_allocator node_allocator;
+ typedef typename table::node_allocator_traits node_allocator_traits;
+ typedef typename table::bucket_pointer bucket_pointer;
+ typedef typename table::link_pointer link_pointer;
+ typedef typename table::previous_pointer previous_pointer;
+ typedef typename table::hasher hasher;
+ typedef typename table::key_equal key_equal;
+ typedef typename table::key_type key_type;
+ typedef typename table::node_constructor node_constructor;
+ typedef typename table::extractor extractor;
 
         // Constructors
 
- equivalent_table(std::size_t n,
- hasher const& hf, key_equal const& eq, value_allocator const& a)
- : table_base(n, hf, eq, a) {}
- equivalent_table(equivalent_table const& x)
- : table_base(x,
- allocator_traits<node_allocator>::
+ grouped_table_impl(std::size_t n,
+ hasher const& hf,
+ key_equal const& eq,
+ node_allocator const& a)
+ : table(n, hf, eq, a)
+ {}
+
+ grouped_table_impl(grouped_table_impl const& x)
+ : table(x, node_allocator_traits::
                 select_on_container_copy_construction(x.node_alloc())) {}
- equivalent_table(equivalent_table const& x,
- value_allocator const& a)
- : table_base(x, a) {}
- equivalent_table(equivalent_table& x, move_tag m)
- : table_base(x, m) {}
- equivalent_table(equivalent_table& x,
- value_allocator const& a, move_tag m)
- : table_base(x, a, m) {}
- ~equivalent_table() {}
+
+ grouped_table_impl(grouped_table_impl const& x,
+ node_allocator const& a)
+ : table(x, a)
+ {}
+
+ grouped_table_impl(grouped_table_impl& x,
+ boost::unordered::detail::move_tag m)
+ : table(x, m)
+ {}
+
+ grouped_table_impl(grouped_table_impl& x,
+ node_allocator const& a,
+ boost::unordered::detail::move_tag m)
+ : table(x, a, m)
+ {}
+
+ // Accessors
+
+ template <class Key, class Pred>
+ node_pointer find_node_impl(
+ std::size_t hash,
+ Key const& k,
+ Pred const& eq) const
+ {
+ std::size_t bucket_index = hash % this->bucket_count_;
+ node_pointer n = this->get_start(bucket_index);
+
+ for (;;)
+ {
+ if (!n) return n;
+
+ std::size_t node_hash = n->hash_;
+ if (hash == node_hash)
+ {
+ if (eq(k, this->get_key(n->value())))
+ return n;
+ }
+ else
+ {
+ if (node_hash % this->bucket_count_ != bucket_index)
+ return node_pointer();
+ }
+
+ n = static_cast<node_pointer>(
+ static_cast<node_pointer>(n->group_prev_)->next_);
+ }
+ }
+
+ std::size_t count(key_type const& k) const
+ {
+ node_pointer n = this->find_node(k);
+ if (!n) return 0;
+
+ std::size_t count = 0;
+ node_pointer it = n;
+ do {
+ it = static_cast<node_pointer>(it->group_prev_);
+ ++count;
+ } while(it != n);
+
+ return count;
+ }
+
+ std::pair<node_pointer, node_pointer>
+ equal_range(key_type const& k) const
+ {
+ node_pointer n = this->find_node(k);
+ return std::make_pair(n,
+ n ? static_cast<node_pointer>(
+ static_cast<node_pointer>(n->group_prev_)->next_) : n);
+ }
 
         // Equality
 
- bool equals(equivalent_table const& other) const
+ bool equals(grouped_table_impl const& other) const
         {
             if(this->size_ != other.size_) return false;
             if(!this->size_) return true;
     
- for(node_ptr n1 = this->buckets_[this->bucket_count_].next_; n1;)
+ for(node_pointer n1 = this->get_start(); n1;)
             {
- node_ptr n2 = other.find_matching_node(n1);
+ node_pointer n2 = other.find_matching_node(n1);
                 if (!n2) return false;
- node_ptr end1 = node::next_group(n1);
- node_ptr end2 = node::next_group(n2);
+ node_pointer end1 = static_cast<node_pointer>(
+ static_cast<node_pointer>(n1->group_prev_)->next_);
+ node_pointer end2 = static_cast<node_pointer>(
+ static_cast<node_pointer>(n2->group_prev_)->next_);
                 if (!group_equals(n1, end1, n2, end2)) return false;
                 n1 = end1;
             }
@@ -70,60 +288,79 @@
 
 #if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
 
- static bool group_equals(node_ptr n1, node_ptr end1,
- node_ptr n2, node_ptr end2)
+ static bool group_equals(node_pointer n1, node_pointer end1,
+ node_pointer n2, node_pointer end2)
         {
             for(;;)
             {
- if (node::get_value(n1) != node::get_value(n2))
+ if (n1->value() != n2->value())
                     break;
 
- n1 = n1->next_;
- n2 = n2->next_;
+ n1 = static_cast<node_pointer>(n1->next_);
+ n2 = static_cast<node_pointer>(n2->next_);
             
                 if (n1 == end1) return n2 == end2;
                 if (n2 == end2) return false;
             }
             
- for(node_ptr n1a = n1, n2a = n2;;)
+ for(node_pointer n1a = n1, n2a = n2;;)
             {
- n1a = n1a->next_;
- n2a = n2a->next_;
+ n1a = static_cast<node_pointer>(n1a->next_);
+ n2a = static_cast<node_pointer>(n2a->next_);
 
                 if (n1a == end1)
                 {
                     if (n2a == end2) break;
                     else return false;
                 }
+
                 if (n2a == end2) return false;
             }
 
- node_ptr start = n1;
- for(;n1 != end2; n1 = n1->next_)
+ node_pointer start = n1;
+ for(;n1 != end2; n1 = static_cast<node_pointer>(n1->next_))
             {
- value_type const& v = node::get_value(n1);
+ value_type const& v = n1->value();
                 if (find(start, n1, v)) continue;
                 std::size_t matches = count_equal(n2, end2, v);
- if (!matches || matches != 1 + count_equal(n1->next_, end1, v))
+ if (!matches || matches != 1 + count_equal(
+ static_cast<node_pointer>(n1->next_), end1, v))
                     return false;
             }
             
             return true;
         }
 
+ static bool find(node_pointer n, node_pointer end, value_type const& v)
+ {
+ for(;n != end; n = static_cast<node_pointer>(n->next_))
+ if (n->value() == v)
+ return true;
+ return false;
+ }
+
+ static std::size_t count_equal(node_pointer n, node_pointer end,
+ value_type const& v)
+ {
+ std::size_t count = 0;
+ for(;n != end; n = static_cast<node_pointer>(n->next_))
+ if (n->value() == v) ++count;
+ return count;
+ }
+
 #else
 
- static bool group_equals(node_ptr n1, node_ptr end1,
- node_ptr n2, node_ptr end2)
+ static bool group_equals(node_pointer n1, node_pointer end1,
+ node_pointer n2, node_pointer end2)
         {
             for(;;)
             {
                 if(!extractor::compare_mapped(
- node::get_value(n1), node::get_value(n2)))
+ n1->value(), n2->value()))
                     return false;
 
- n1 = n1->next_;
- n2 = n2->next_;
+ n1 = static_cast<node_pointer>(n1->next_);
+ n2 = static_cast<node_pointer>(n2->next_);
 
                 if (n1 == end1) return n2 == end2;
                 if (n2 == end2) return false;
@@ -132,205 +369,455 @@
 
 #endif
 
- static bool find(node_ptr n, node_ptr end, value_type const& v)
+ // Emplace/Insert
+
+ static inline void add_after_node(
+ node_pointer n,
+ node_pointer pos)
         {
- for(;n != end; n = n->next_)
- if (node::get_value(n) == v)
- return true;
- return false;
+ n->next_ = static_cast<node_pointer>(pos->group_prev_)->next_;
+ n->group_prev_ = pos->group_prev_;
+ static_cast<node_pointer>(pos->group_prev_)->next_ =
+ static_cast<link_pointer>(n);
+ pos->group_prev_ = static_cast<link_pointer>(n);
         }
-
- static std::size_t count_equal(node_ptr n, node_ptr end, value_type const& v)
- {
- std::size_t count = 0;
- for(;n != end; n = n->next_)
- if (node::get_value(n) == v) ++count;
- return count;
- }
-
- ////////////////////////////////////////////////////////////////////////
- // A convenience method for adding nodes.
 
- inline node_ptr add_node(
+ inline node_pointer add_node(
                 node_constructor& a,
- std::size_t bucket_index,
                 std::size_t hash,
- node_ptr pos)
+ node_pointer pos)
         {
- node_ptr n = a.release();
- node::set_hash(n, hash);
-
- if(BOOST_UNORDERED_BORLAND_BOOL(pos)) {
- node::add_after_node(n, pos);
+ node_pointer n = a.release();
+ n->hash_ = hash;
+ if(pos) {
+ this->add_after_node(n, pos);
                 if (n->next_) {
                     std::size_t next_bucket =
- node::get_hash(n->next_) % this->bucket_count_;
- if (next_bucket != bucket_index) {
- this->buckets_[next_bucket].next_ = n;
+ static_cast<node_pointer>(n->next_)->hash_ %
+ this->bucket_count_;
+ if (next_bucket != hash % this->bucket_count_) {
+ this->get_bucket(next_bucket)->next_ = n;
                     }
                 }
             }
             else {
- bucket_ptr b = this->get_bucket(bucket_index);
-
+ bucket_pointer b = this->get_bucket(hash % this->bucket_count_);
+
                 if (!b->next_)
                 {
- bucket_ptr start_node =
- this->get_bucket(this->bucket_count_);
+ previous_pointer start_node = this->get_previous_start();
                     
- if (BOOST_UNORDERED_BORLAND_BOOL(start_node->next_)) {
- this->buckets_[
- node::get_hash(start_node->next_) %
- this->bucket_count_].next_ = n;
+ if (start_node->next_) {
+ this->get_bucket(
+ static_cast<node_pointer>(start_node->next_)->hash_
+ % this->bucket_count_)->next_ = n;
                     }
     
                     b->next_ = start_node;
                     n->next_ = start_node->next_;
- start_node->next_ = n;
+ start_node->next_ = static_cast<link_pointer>(n);
                 }
                 else
                 {
                     n->next_ = b->next_->next_;
- b->next_->next_ = n;
+ b->next_->next_ = static_cast<link_pointer>(n);
                 }
             }
             ++this->size_;
             return n;
         }
 
- ////////////////////////////////////////////////////////////////////////
- // Insert methods
-
- node_ptr emplace_impl(node_constructor& a)
+ node_pointer emplace_impl(node_constructor& a)
         {
             key_type const& k = this->get_key(a.value());
             std::size_t hash = this->hash_function()(k);
- std::size_t bucket_index = hash % this->bucket_count_;
- node_ptr position = this->find_node(bucket_index, hash, k);
-
+ node_pointer position = this->find_node(hash, k);
+
             // reserve has basic exception safety if the hash function
             // throws, strong otherwise.
- if(this->reserve_for_insert(this->size_ + 1)) {
- bucket_index = hash % this->bucket_count_;
- }
-
- return add_node(a, bucket_index, hash, position);
+ this->reserve_for_insert(this->size_ + 1);
+ return this->add_node(a, hash, position);
         }
 
         void emplace_impl_no_rehash(node_constructor& a)
         {
             key_type const& k = this->get_key(a.value());
             std::size_t hash = this->hash_function()(k);
- std::size_t bucket_index = hash % this->bucket_count_;
- add_node(a, bucket_index, hash,
- this->find_node(bucket_index, hash, k));
+ this->add_node(a, hash,
+ this->find_node(hash, k));
         }
 
 #if defined(BOOST_NO_RVALUE_REFERENCES)
- node_ptr emplace(please_ignore_this_overload const&)
+ node_pointer emplace(boost::unordered::detail::emplace_args1<
+ boost::unordered::detail::please_ignore_this_overload> const&)
         {
             BOOST_ASSERT(false);
             return this->begin();
         }
 #endif
 
-#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
-
- template <class... Args>
- node_ptr emplace(Args&&... args)
+ template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ node_pointer emplace(BOOST_UNORDERED_EMPLACE_ARGS)
         {
- // Create the node before rehashing in case it throws an
- // exception (need strong safety in such a case).
- node_constructor a(*this);
- a.construct(std::forward<Args>(args)...);
-
- return emplace_impl(a);
- }
+ node_constructor a(this->node_alloc());
+ a.construct_node();
+ a.construct_value(BOOST_UNORDERED_EMPLACE_FORWARD);
 
-#else
-
-#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \
- template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)> \
- node_ptr emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
- { \
- node_constructor a(*this); \
- a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
- return emplace_impl(a); \
+ return emplace_impl(a);
         }
 
- BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_INSERT_IMPL, _)
-
-#undef BOOST_UNORDERED_INSERT_IMPL
-#endif
-
         ////////////////////////////////////////////////////////////////////////
         // Insert range methods
 
         // if hash function throws, or inserting > 1 element, basic exception
         // safety. Strong otherwise
         template <class I>
- void insert_for_range(I i, I j, forward_traversal_tag)
+ typename boost::unordered::detail::enable_if_forward<I, void>::type
+ insert_range(I i, I j)
         {
             if(i == j) return;
- std::size_t distance = ::boost::unordered::detail::distance(i, j);
+
+ std::size_t distance = boost::unordered::detail::distance(i, j);
             if(distance == 1) {
- emplace(*i);
+ node_constructor a(this->node_alloc());
+ a.construct_node();
+ a.construct_value2(*i);
+ emplace_impl(a);
             }
             else {
                 // Only require basic exception safety here
                 this->reserve_for_insert(this->size_ + distance);
 
- node_constructor a(*this);
+ node_constructor a(this->node_alloc());
                 for (; i != j; ++i) {
- a.construct(*i);
+ a.construct_node();
+ a.construct_value2(*i);
                     emplace_impl_no_rehash(a);
                 }
             }
         }
 
         template <class I>
- void insert_for_range(I i, I j, ::boost::incrementable_traversal_tag)
+ typename boost::unordered::detail::disable_if_forward<I, void>::type
+ insert_range(I i, I j)
         {
- node_constructor a(*this);
+ node_constructor a(this->node_alloc());
             for (; i != j; ++i) {
- a.construct(*i);
+ a.construct_node();
+ a.construct_value2(*i);
                 emplace_impl(a);
             }
         }
 
- // If hash function throws, or inserting > 1 element, basic exception
- // safety. Strong otherwise
- template <class I>
- void insert_range(I i, I j)
+ ////////////////////////////////////////////////////////////////////////
+ // Erase
+ //
+ // no throw
+
+ std::size_t erase_key(key_type const& k)
         {
- insert_for_range(i, j,
- BOOST_DEDUCED_TYPENAME ::boost::iterator_traversal<I>::type());
+ if(!this->size_) return 0;
+
+ std::size_t hash = this->hash_function()(k);
+ std::size_t bucket_index = hash % this->bucket_count_;
+ bucket_pointer bucket = this->get_bucket(bucket_index);
+
+ previous_pointer prev = bucket->next_;
+ if (!prev) return 0;
+
+ for (;;)
+ {
+ if (!prev->next_) return 0;
+ std::size_t node_hash =
+ static_cast<node_pointer>(prev->next_)->hash_;
+ if (node_hash % this->bucket_count_ != bucket_index)
+ return 0;
+ if (node_hash == hash &&
+ this->key_eq()(k, this->get_key(
+ static_cast<node_pointer>(prev->next_)->value())))
+ break;
+ prev = static_cast<previous_pointer>(
+ static_cast<node_pointer>(prev->next_)->group_prev_);
+ }
+
+ node_pointer pos = static_cast<node_pointer>(prev->next_);
+ link_pointer end1 =
+ static_cast<node_pointer>(pos->group_prev_)->next_;
+ node_pointer end = static_cast<node_pointer>(end1);
+ prev->next_ = end1;
+ this->fix_buckets(bucket, prev, end);
+ return this->delete_nodes(pos, end);
         }
 
- };
+ node_pointer erase(node_pointer r)
+ {
+ BOOST_ASSERT(r);
+ node_pointer next = static_cast<node_pointer>(r->next_);
 
- template <class H, class P, class A>
- struct multiset : public types<
- typename allocator_traits<A>::value_type,
- typename allocator_traits<A>::value_type,
- H, P, A,
- set_extractor<typename allocator_traits<A>::value_type>,
- false>
- {
- typedef equivalent_table<multiset<H, P, A> > impl;
- typedef table<multiset<H, P, A> > table_base;
- };
+ bucket_pointer bucket = this->get_bucket(
+ r->hash_ % this->bucket_count_);
+ previous_pointer prev = unlink_node(*bucket, r);
 
- template <class K, class H, class P, class A>
- struct multimap : public types<
- K, typename allocator_traits<A>::value_type,
- H, P, A,
- map_extractor<K, typename allocator_traits<A>::value_type>,
- false>
- {
- typedef equivalent_table<multimap<K, H, P, A> > impl;
- typedef table<multimap<K, H, P, A> > table_base;
+ this->fix_buckets(bucket, prev, next);
+
+ this->delete_node(r);
+
+ return next;
+ }
+
+ node_pointer erase_range(node_pointer r1, node_pointer r2)
+ {
+ if (r1 == r2) return r2;
+
+ std::size_t bucket_index = r1->hash_ % this->bucket_count_;
+ previous_pointer prev = unlink_nodes(
+ *this->get_bucket(bucket_index), r1, r2);
+ this->fix_buckets_range(bucket_index, prev, r1, r2);
+ this->delete_nodes(r1, r2);
+
+ return r2;
+ }
+
+ static previous_pointer unlink_node(bucket& b, node_pointer n)
+ {
+ node_pointer next = static_cast<node_pointer>(n->next_);
+ previous_pointer prev =
+ static_cast<previous_pointer>(n->group_prev_);
+
+ if(prev->next_ != n) {
+ // The node is at the beginning of a group.
+
+ // Find the previous node pointer:
+ prev = b.next_;
+ while(prev->next_ != n) {
+ prev = static_cast<previous_pointer>(
+ static_cast<node_pointer>(prev->next_)->group_prev_);
+ }
+
+ // Remove from group
+ if (next && next->group_prev_ == static_cast<link_pointer>(n))
+ {
+ next->group_prev_ = n->group_prev_;
+ }
+ }
+ else if (next && next->group_prev_ == static_cast<link_pointer>(n))
+ {
+ // The deleted node is not at the end of the group, so
+ // change the link from the next node.
+ next->group_prev_ = n->group_prev_;
+ }
+ else {
+ // The deleted node is at the end of the group, so the
+ // first node in the group is pointing to it.
+ // Find that to change its pointer.
+ node_pointer x = static_cast<node_pointer>(n->group_prev_);
+ while(x->group_prev_ != static_cast<link_pointer>(n)) {
+ x = static_cast<node_pointer>(x->group_prev_);
+ }
+ x->group_prev_ = n->group_prev_;
+ }
+
+ prev->next_ = static_cast<link_pointer>(next);
+ return prev;
+ }
+
+ static previous_pointer unlink_nodes(bucket& b,
+ node_pointer begin, node_pointer end)
+ {
+ previous_pointer prev = static_cast<previous_pointer>(
+ begin->group_prev_);
+
+ if(prev->next_ != static_cast<link_pointer>(begin)) {
+ // The node is at the beginning of a group.
+
+ // Find the previous node pointer:
+ prev = b.next_;
+ while(prev->next_ != static_cast<link_pointer>(begin))
+ prev = static_cast<previous_pointer>(
+ static_cast<node_pointer>(prev->next_)->group_prev_);
+
+ if (end) split_group(end);
+ }
+ else {
+ node_pointer group1 = split_group(begin);
+
+ if (end) {
+ node_pointer group2 = split_group(end);
+
+ if(begin == group2) {
+ link_pointer end1 = group1->group_prev_;
+ link_pointer end2 = group2->group_prev_;
+ group1->group_prev_ = end2;
+ group2->group_prev_ = end1;
+ }
+ }
+ }
+
+ prev->next_ = static_cast<link_pointer>(end);
+
+ return prev;
+ }
+
+ // Break a ciruclar list into two, with split as the beginning
+ // of the second group (if split is at the beginning then don't
+ // split).
+ static node_pointer split_group(node_pointer split)
+ {
+ // Find first node in group.
+ node_pointer first = split;
+ while (static_cast<node_pointer>(first->group_prev_)->next_ ==
+ static_cast<link_pointer>(first))
+ first = static_cast<node_pointer>(first->group_prev_);
+
+ if(first == split) return split;
+
+ link_pointer last = first->group_prev_;
+ first->group_prev_ = split->group_prev_;
+ split->group_prev_ = last;
+
+ return first;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // copy_buckets_to
+ //
+ // Basic exception safety. If an exception is thrown this will
+ // leave dst partially filled and the buckets unset.
+
+ static void copy_buckets_to(buckets const& src, buckets& dst)
+ {
+ BOOST_ASSERT(!dst.buckets_);
+
+ dst.create_buckets();
+
+ node_constructor a(dst.node_alloc());
+
+ node_pointer n = src.get_start();
+ previous_pointer prev = dst.get_previous_start();
+
+ while(n) {
+ std::size_t hash = n->hash_;
+ node_pointer group_end =
+ static_cast<node_pointer>(
+ static_cast<node_pointer>(n->group_prev_)->next_);
+
+ a.construct_node();
+ a.construct_value2(n->value());
+
+ node_pointer first_node = a.release();
+ node_pointer end = first_node;
+ first_node->hash_ = hash;
+ prev->next_ = static_cast<link_pointer>(first_node);
+ ++dst.size_;
+
+ for(n = static_cast<node_pointer>(n->next_); n != group_end;
+ n = static_cast<node_pointer>(n->next_))
+ {
+ a.construct_node();
+ a.construct_value2(n->value());
+ end = a.release();
+ end->hash_ = hash;
+ add_after_node(end, first_node);
+ ++dst.size_;
+ }
+
+ prev = place_in_bucket(dst, prev, end);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // move_buckets_to
+ //
+ // Basic exception safety. The source nodes are left in an unusable
+ // state if an exception throws.
+
+ static void move_buckets_to(buckets& src, buckets& dst)
+ {
+ BOOST_ASSERT(!dst.buckets_);
+
+ dst.create_buckets();
+
+ node_constructor a(dst.node_alloc());
+
+ node_pointer n = src.get_start();
+ previous_pointer prev = dst.get_previous_start();
+
+ while(n) {
+ std::size_t hash = n->hash_;
+ node_pointer group_end =
+ static_cast<node_pointer>(
+ static_cast<node_pointer>(n->group_prev_)->next_);
+
+ a.construct_node();
+ a.construct_value2(boost::move(n->value()));
+
+ node_pointer first_node = a.release();
+ node_pointer end = first_node;
+ first_node->hash_ = hash;
+ prev->next_ = static_cast<link_pointer>(first_node);
+ ++dst.size_;
+
+ for(n = static_cast<node_pointer>(n->next_); n != group_end;
+ n = static_cast<node_pointer>(n->next_))
+ {
+ a.construct_node();
+ a.construct_value2(boost::move(n->value()));
+ end = a.release();
+ end->hash_ = hash;
+ add_after_node(end, first_node);
+ ++dst.size_;
+ }
+
+ prev = place_in_bucket(dst, prev, end);
+ }
+ }
+
+ // strong otherwise exception safety
+ void rehash_impl(std::size_t num_buckets)
+ {
+ BOOST_ASSERT(this->size_);
+
+ buckets dst(this->node_alloc(), num_buckets);
+ dst.create_buckets();
+
+ previous_pointer src_start = this->get_previous_start();
+ previous_pointer dst_start = dst.get_previous_start();
+
+ dst_start->next_ = src_start->next_;
+ src_start->next_ = link_pointer();
+ dst.size_ = this->size_;
+ this->size_ = 0;
+
+ previous_pointer prev = dst_start;
+ while (prev->next_)
+ prev = place_in_bucket(dst, prev,
+ static_cast<node_pointer>(
+ static_cast<node_pointer>(prev->next_)->group_prev_));
+
+ // Swap the new nodes back into the container and setup the
+ // variables.
+ dst.swap(*this); // no throw
+ }
+
+ // Iterate through the nodes placing them in the correct buckets.
+ // pre: prev->next_ is not null.
+ static previous_pointer place_in_bucket(buckets& dst,
+ previous_pointer prev, node_pointer end)
+ {
+ bucket_pointer b = dst.get_bucket(end->hash_ % dst.bucket_count_);
+
+ if (!b->next_) {
+ b->next_ = static_cast<node_pointer>(prev);
+ return static_cast<previous_pointer>(end);
+ }
+ else {
+ link_pointer next = end->next_;
+ end->next_ = b->next_->next_;
+ b->next_->next_ = prev->next_;
+ prev->next_ = next;
+ return prev;
+ }
+ }
     };
 }}}
 

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-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -33,7 +33,8 @@
         static choice1::type test(T2 const&);
         static choice2::type test(Key const&);
         
- enum { value = sizeof(test(make<T>())) == sizeof(choice2::type) };
+ enum { value = sizeof(test(boost::unordered::detail::make<T>())) ==
+ sizeof(choice2::type) };
         
         typedef typename boost::detail::if_true<value>::
             BOOST_NESTED_TEMPLATE then<Key const&, no_key>::type type;
@@ -93,7 +94,7 @@
     struct map_extractor
     {
         typedef ValueType value_type;
- typedef 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)
         {

Modified: branches/release/boost/unordered/detail/fwd.hpp
==============================================================================
--- branches/release/boost/unordered/detail/fwd.hpp (original)
+++ branches/release/boost/unordered/detail/fwd.hpp 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -21,26 +21,26 @@
 {
     template <class K,
         class T,
- class H = hash<K>,
+ class H = boost::hash<K>,
         class P = std::equal_to<K>,
         class A = std::allocator<std::pair<const K, T> > >
     class unordered_map;
 
     template <class K,
         class T,
- class H = hash<K>,
+ class H = boost::hash<K>,
         class P = std::equal_to<K>,
         class A = std::allocator<std::pair<const K, T> > >
     class unordered_multimap;
 
     template <class T,
- class H = hash<T>,
+ class H = boost::hash<T>,
         class P = std::equal_to<T>,
         class A = std::allocator<T> >
     class unordered_set;
 
     template <class T,
- class H = hash<T>,
+ class H = boost::hash<T>,
         class P = std::equal_to<T>,
         class A = std::allocator<T> >
     class unordered_multiset;

Deleted: branches/release/boost/unordered/detail/node.hpp
==============================================================================
--- branches/release/boost/unordered/detail/node.hpp 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
+++ (empty file)
@@ -1,364 +0,0 @@
-
-// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
-// Copyright (C) 2005-2011 Daniel James
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-// This contains the basic data structure, apart from the actual values. There's
-// no construction or deconstruction here. So this only depends on the pointer
-// type.
-
-#ifndef BOOST_UNORDERED_DETAIL_NODE_HPP_INCLUDED
-#define BOOST_UNORDERED_DETAIL_NODE_HPP_INCLUDED
-
-#include <boost/unordered/detail/util.hpp>
-
-#if BOOST_WORKAROUND(__BORLANDC__, <= 0X0582)
-#define BOOST_UNORDERED_BORLAND_BOOL(x) (bool)(x)
-#else
-#define BOOST_UNORDERED_BORLAND_BOOL(x) x
-#endif
-
-namespace boost { namespace unordered { namespace detail {
-
- // Some forward declarations for buckets and tables
-
- template <typename T> class table;
- template <class A, bool Unique> class buckets;
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // This section implements buckets and nodes. Here's a rough
- // inheritance diagram, to show how they pull together.
- //
- // For unordered_set/unordered_map:
- //
- // bucket<A> value_base<allocator_traits<A>::value_type>
- // | |
- // +--------------+-------------+
- // |
- // ungrouped_node<A>
- //
- // For unordered_multiset/unordered_multimap:
- //
- // bucket<A> value_base<allocator_traits<A>::value_type>
- // | |
- // +--------------+-------------+
- // |
- // grouped_node<A>
-
- // bucket
- //
- // bucket is used for both the buckets and as a base class for
- // nodes. By using 'bucket_ptr' for 'node_ptr', 'next_' can point
- // to either a bucket or a node. This is used later to implement a
- // sentinel at the end of the bucket array.
-
- template <class A>
- class bucket
- {
- bucket& operator=(bucket const&);
- public:
- typedef typename ::boost::unordered::detail::rebind_wrap<A, bucket>::type
- bucket_allocator;
- typedef typename allocator_traits<bucket_allocator>::pointer bucket_ptr;
- typedef bucket_ptr node_ptr;
-
- node_ptr next_;
-
- bucket() : next_() {}
- };
-
- // The space used to store values in a node.
-
- template <class ValueType>
- struct value_base
- {
- typedef ValueType value_type;
- typename ::boost::aligned_storage<
- sizeof(value_type),
- ::boost::alignment_of<value_type>::value>::type data_;
-
- void* address() {
- return this;
- }
- value_type& value() {
- return *(ValueType*) this;
- }
- value_type* value_ptr() {
- return (ValueType*) this;
- }
- private:
- value_base& operator=(value_base const&);
- };
-
- // In containers with equivalent keys (unordered_multimap and
- // unordered_multiset) equivalent nodes are grouped together, in
- // containers with unique keys (unordered_map and unordered_set)
- // individual nodes are treated as groups of one. The following two
- // classes implement the data structure.
-
- // This is used for containers with unique keys. There are no groups
- // so it doesn't add any extra members, and just treats individual
- // nodes as groups of one.
-
- template <class A>
- struct ungrouped_node
- : ::boost::unordered::detail::bucket<A>,
- value_base<typename allocator_traits<A>::value_type>
- {
- typedef ::boost::unordered::detail::bucket<A> bucket;
- 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_;
-
- ungrouped_node() : bucket() {}
-
- void init(node_ptr) {}
-
- static node_ptr next_group(node_ptr ptr)
- {
- return ptr->next_;
- }
-
- static node_ptr next_group2(node_ptr ptr)
- {
- return ptr->next_;
- }
-
- static std::size_t group_count(node_ptr n)
- {
- return !n ? 0 : 1;
- }
-
- static void add_after_node(node_ptr n, node_ptr position)
- {
- n->next_ = position->next_;
- position->next_ = position;
- }
-
- static node_ptr unlink_node(bucket& b, node_ptr n)
- {
- return unlink_nodes(b, n, n->next_);
- }
-
- static node_ptr unlink_nodes(bucket& b, node_ptr begin, node_ptr end)
- {
- node_ptr prev = b.next_;
- while(prev->next_ != begin) prev = prev->next_;
- prev->next_ = end;
- return prev;
- }
-
- static std::size_t get_hash(node_ptr p)
- {
- return static_cast<ungrouped_node&>(*p).hash_;
- }
-
- static void set_hash(node_ptr p, std::size_t hash)
- {
- static_cast<ungrouped_node&>(*p).hash_ = hash;
- }
-
- static value_type& get_value(node_ptr p)
- {
- return static_cast<ungrouped_node&>(*p).value();
- }
-
- static value_type* get_value_ptr(node_ptr p)
- {
- return static_cast<ungrouped_node&>(*p).value_ptr();
- }
- };
-
- // This is used for containers with equivalent keys. It implements a
- // circular list running in the opposite direction to the linked
- // list through the nodes.
-
- template <class A>
- struct grouped_node
- : ::boost::unordered::detail::bucket<A>,
- value_base<typename allocator_traits<A>::value_type>
- {
- typedef ::boost::unordered::detail::bucket<A> bucket;
- 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_;
-
- grouped_node() : bucket(), group_prev_() {}
- void init(node_ptr n)
- {
- group_prev_ = n;
- }
-
- static node_ptr next_group(node_ptr ptr)
- {
- return get(ptr).group_prev_->next_;
- }
-
- static node_ptr next_group2(node_ptr ptr)
- {
- return get(ptr->next_).group_prev_;
- }
-
- static std::size_t group_count(node_ptr ptr)
- {
- if (!ptr) return 0;
-
- node_ptr start = ptr;
- std::size_t size = 0;
- do {
- ++size;
- ptr = get(ptr).group_prev_;
- } while(ptr != start);
- return size;
- }
-
- static void add_after_node(node_ptr n, node_ptr pos)
- {
- n->next_ = get(pos).group_prev_->next_;
- get(n).group_prev_ = get(pos).group_prev_;
- get(pos).group_prev_->next_ = n;
- get(pos).group_prev_ = n;
- }
-
- static node_ptr unlink_node(bucket& b, node_ptr n)
- {
- node_ptr next = n->next_;
- node_ptr prev = get(n).group_prev_;
-
- if(prev->next_ != n) {
- // The node is at the beginning of a group.
-
- // Find the previous node pointer:
- prev = b.next_;
- while(prev->next_ != n) {
- prev = next_group2(prev);
- }
-
- // Remove from group
- if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
- get(next).group_prev_ == n)
- {
- get(next).group_prev_ = get(n).group_prev_;
- }
- }
- else if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
- get(next).group_prev_ == n)
- {
- // The deleted node is not at the end of the group, so
- // change the link from the next node.
- get(next).group_prev_ = get(n).group_prev_;
- }
- else {
- // The deleted node is at the end of the group, so the
- // first node in the group is pointing to it.
- // Find that to change its pointer.
- node_ptr x = get(n).group_prev_;
- while(get(x).group_prev_ != n) {
- x = get(x).group_prev_;
- }
- get(x).group_prev_ = get(n).group_prev_;
- }
- prev->next_ = next;
-
- return prev;
- }
-
- static node_ptr unlink_nodes(bucket& b, node_ptr begin, node_ptr end)
- {
- node_ptr prev = get(begin).group_prev_;
-
- if(prev->next_ != begin) {
- // The node is at the beginning of a group.
-
- // Find the previous node pointer:
- prev = b.next_;
- while(prev->next_ != begin) prev = next_group2(prev);
-
- if(BOOST_UNORDERED_BORLAND_BOOL(end)) split_group(end);
- }
- else {
- node_ptr group1 = split_group(begin);
- if(BOOST_UNORDERED_BORLAND_BOOL(end)) {
- node_ptr group2 = split_group(end);
-
- if(begin == group2) {
- node_ptr end1 = get(group1).group_prev_;
- node_ptr end2 = get(group2).group_prev_;
- get(group1).group_prev_ = end2;
- get(group2).group_prev_ = end1;
- }
- }
- }
-
- prev->next_ = end;
-
- return prev;
- }
-
- // Break a ciruclar list into two, with split as the beginning
- // of the second group (if split is at the beginning then don't
- // split).
- static node_ptr split_group(node_ptr split)
- {
- // Find first node in group.
- node_ptr first = split;
- while(next_group(first) == first)
- first = get(first).group_prev_;
-
- if(first == split) return split;
-
- node_ptr last = get(first).group_prev_;
- get(first).group_prev_ = get(split).group_prev_;
- get(split).group_prev_ = last;
-
- return first;
- }
-
- static std::size_t get_hash(node_ptr p) {
- return static_cast<grouped_node&>(*p).hash_;
- }
- static void set_hash(node_ptr p, std::size_t hash) {
- static_cast<grouped_node&>(*p).hash_ = hash;
- }
- static value_type& get_value(node_ptr p) {
- return static_cast<grouped_node&>(*p).value();
- }
- static value_type* get_value_ptr(node_ptr p) {
- return static_cast<grouped_node&>(*p).value_ptr();
- }
-
- static grouped_node& get(node_ptr ptr) {
- return static_cast<grouped_node&>(*ptr);
- }
- };
-
- // These two classes implement an easy way to pass around the node
- // group policy classes without the messy template parameters.
- // Whenever you see the template parameter 'G' it's one of these.
-
- struct ungrouped
- {
- template <class A>
- struct node {
- typedef ungrouped_node<A> type;
- };
- };
-
- struct grouped
- {
- template <class A>
- struct node {
- typedef grouped_node<A> type;
- };
- };
-
-}}}
-
-#endif

Modified: branches/release/boost/unordered/detail/table.hpp
==============================================================================
--- branches/release/boost/unordered/detail/table.hpp (original)
+++ branches/release/boost/unordered/detail/table.hpp 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -8,118 +8,346 @@
 #define BOOST_UNORDERED_DETAIL_ALL_HPP_INCLUDED
 
 #include <boost/unordered/detail/buckets.hpp>
+#include <boost/unordered/detail/util.hpp>
+#include <boost/type_traits/aligned_storage.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/iterator.hpp>
+#include <cmath>
 
-namespace boost { namespace unordered { namespace detail {
+namespace boost { namespace unordered { namespace iterator_detail {
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Iterators
+ //
+ // all no throw
+
+ template <typename NodePointer, typename Value> struct iterator;
+ template <typename ConstNodePointer, typename NodePointer,
+ typename Value> struct c_iterator;
+ template <typename NodePointer, typename Value> struct l_iterator;
+ template <typename ConstNodePointer, typename NodePointer,
+ typename Value> struct cl_iterator;
 
- // This implements almost all of the required functionality, apart
- // from some things that are specific to containers with unique and
- // equivalent keys which is implemented in unique_table and
- // equivalent_table. See unique.hpp and equivalent.hpp for
- // their declaration and implementation.
+ // Local Iterators
+ //
+ // all no throw
 
- template <class T>
- class table : public T::buckets, public T::functions
+ template <typename NodePointer, typename Value>
+ struct l_iterator
+ : public boost::iterator<
+ std::forward_iterator_tag, Value, std::ptrdiff_t,
+ NodePointer, Value&>
     {
- table(table const&);
- table& operator=(table const&);
+#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+ template <typename ConstNodePointer, typename NodePointer2,
+ typename Value2>
+ friend struct boost::unordered::iterator_detail::cl_iterator;
+ private:
+#endif
+ typedef NodePointer node_pointer;
+ node_pointer ptr_;
+ std::size_t bucket_;
+ std::size_t bucket_count_;
+
     public:
- 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
-
- float mlf_;
- std::size_t max_load_; // Only use if this->buckets_.
+ l_iterator() : ptr_() {}
 
- // Helper methods
+ l_iterator(node_pointer x, std::size_t b, std::size_t c)
+ : ptr_(x), bucket_(b), bucket_count_(c) {}
+
+ Value& operator*() const {
+ return ptr_->value();
+ }
+
+ Value* operator->() const {
+ return ptr_->value_ptr();
+ }
+
+ l_iterator& operator++() {
+ ptr_ = static_cast<node_pointer>(ptr_->next_);
+ if (ptr_ && ptr_->hash_ % bucket_count_ != bucket_)
+ ptr_ = node_pointer();
+ return *this;
+ }
 
- key_type const& get_key(value_type const& v) const {
- return extractor::extract(v);
+ l_iterator operator++(int) {
+ l_iterator tmp(*this);
+ ++(*this);
+ return tmp;
         }
 
+ bool operator==(l_iterator x) const {
+ return ptr_ == x.ptr_;
+ }
+
+ bool operator!=(l_iterator x) const {
+ return ptr_ != x.ptr_;
+ }
+ };
+
+ template <typename ConstNodePointer, typename NodePointer, typename Value>
+ struct cl_iterator
+ : public boost::iterator<
+ std::forward_iterator_tag, Value, std::ptrdiff_t,
+ ConstNodePointer, Value const&>
+ {
+ friend struct boost::unordered::iterator_detail::l_iterator
+ <NodePointer, Value>;
     private:
- // pre: this->buckets_ != null
- template <class Key, class Pred>
- node_ptr find_node_impl(
- std::size_t bucket_index,
- std::size_t hash,
- Key const& k,
- Pred const& eq) const
- {
- node_ptr n = this->buckets_[bucket_index].next_;
- if (!n) return n;
- n = n->next_;
-
- for (;;)
- {
- if (!n) return n;
- std::size_t node_hash = node::get_hash(n);
- if (hash == node_hash)
- {
- if (eq(k, get_key(node::get_value(n))))
- return n;
- }
- else
- {
- if (node_hash % this->bucket_count_ != bucket_index)
- return node_ptr();
- }
- n = node::next_group(n);
- }
+
+ typedef NodePointer node_pointer;
+ node_pointer ptr_;
+ std::size_t bucket_;
+ std::size_t bucket_count_;
+
+ public:
+
+ cl_iterator() : ptr_() {}
+
+ cl_iterator(node_pointer x, std::size_t b, std::size_t c) :
+ ptr_(x), bucket_(b), bucket_count_(c) {}
+
+ cl_iterator(boost::unordered::iterator_detail::l_iterator<
+ NodePointer, Value> const& x) :
+ ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
+ {}
+
+ Value const&
+ operator*() const {
+ return ptr_->value();
+ }
+
+ Value const* operator->() const {
+ return ptr_->value_ptr();
         }
 
+ cl_iterator& operator++() {
+ ptr_ = static_cast<node_pointer>(ptr_->next_);
+ if (ptr_ && ptr_->hash_ % bucket_count_ != bucket_)
+ ptr_ = node_pointer();
+ return *this;
+ }
+
+ cl_iterator operator++(int) {
+ cl_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(cl_iterator const& x, cl_iterator const& y) {
+ return x.ptr_ == y.ptr_;
+ }
+
+ friend bool operator!=(cl_iterator const& x, cl_iterator const& y) {
+ return x.ptr_ != y.ptr_;
+ }
+ };
+
+ template <typename NodePointer, typename Value>
+ struct iterator
+ : public boost::iterator<
+ std::forward_iterator_tag, Value, std::ptrdiff_t,
+ NodePointer, Value&>
+ {
+#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+ template <typename ConstNodePointer, typename NodePointer2,
+ typename Value2>
+ friend struct boost::unordered::iterator_detail::c_iterator;
+ private:
+#endif
+ typedef NodePointer node_pointer;
+ node_pointer node_;
+
     public:
- template <class Key, class Hash, class Pred>
- node_ptr generic_find_node(
- Key const& k,
- Hash const& hash_function,
- Pred const& eq) const
- {
- if (!this->size_) return node_ptr();
- std::size_t hash = hash_function(k);
- return this->find_node_impl(hash % this->bucket_count_, hash, k, eq);
+
+ iterator() : node_() {}
+
+ explicit iterator(node_pointer const& x) : node_(x) {}
+
+ Value& operator*() const {
+ return node_->value();
         }
-
- node_ptr find_node(
- std::size_t bucket_index,
- std::size_t hash,
- key_type const& k) const
- {
- if (!this->size_) return node_ptr();
- return this->find_node_impl(bucket_index, hash, k, this->key_eq());
+
+ Value* operator->() const {
+ return &node_->value();
         }
 
- node_ptr find_node(key_type const& k) const
- {
- if (!this->size_) return node_ptr();
- std::size_t hash = this->hash_function()(k);
- return this->find_node_impl(hash % this->bucket_count_, hash, k,
- this->key_eq());
+ iterator& operator++() {
+ node_ = node_ = static_cast<node_pointer>(node_->next_);
+ return *this;
         }
 
- node_ptr find_matching_node(node_ptr n) const
- {
- // For some stupid reason, I decided to support equality comparison
- // when different hash functions are used. So I can't use the hash
- // value from the node here.
-
- return find_node(get_key(node::get_value(n)));
+ iterator operator++(int) {
+ iterator tmp(node_);
+ node_ = node_ = static_cast<node_pointer>(node_->next_);
+ return tmp;
+ }
+
+ bool operator==(iterator const& x) const {
+ return node_ == x.node_;
+ }
+
+ bool operator!=(iterator const& x) const {
+ return node_ != x.node_;
+ }
+ };
+
+ template <typename ConstNodePointer, typename NodePointer, typename Value>
+ struct c_iterator
+ : public boost::iterator<
+ std::forward_iterator_tag, Value, std::ptrdiff_t,
+ ConstNodePointer, Value const&>
+ {
+ friend struct boost::unordered::iterator_detail::iterator<
+ NodePointer, Value>;
+
+#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+ template <typename K, typename T, typename H, typename P, typename A>
+ friend class boost::unordered::unordered_map;
+ template <typename K, typename T, typename H, typename P, typename A>
+ friend class boost::unordered::unordered_multimap;
+ template <typename T, typename H, typename P, typename A>
+ friend class boost::unordered::unordered_set;
+ template <typename T, typename H, typename P, typename A>
+ friend class boost::unordered::unordered_multiset;
+
+ private:
+#endif
+
+ typedef NodePointer node_pointer;
+ node_pointer node_;
+
+ public:
+
+ c_iterator() : node_() {}
+
+ explicit c_iterator(node_pointer const& x) : node_(x) {}
+
+ c_iterator(boost::unordered::iterator_detail::iterator<
+ NodePointer, Value> const& x) : node_(x.node_) {}
+
+ Value const& operator*() const {
+ return node_->value();
+ }
+
+ Value const* operator->() const {
+ return &node_->value();
+ }
+
+ c_iterator& operator++() {
+ node_ = static_cast<node_pointer>(node_->next_);
+ return *this;
         }
 
+ c_iterator operator++(int) {
+ c_iterator tmp(node_);
+ node_ = node_ = static_cast<node_pointer>(node_->next_);
+ return tmp;
+ }
+
+ friend bool operator==(c_iterator const& x, c_iterator const& y) {
+ return x.node_ == y.node_;
+ }
+
+ friend bool operator!=(c_iterator const& x, c_iterator const& y) {
+ return x.node_ != y.node_;
+ }
+ };
+}}}
+
+namespace boost { namespace unordered { namespace detail {
+
+ ////////////////////////////////////////////////////////////////////////////
+ // convert double to std::size_t
+
+ inline std::size_t double_to_size(double f)
+ {
+ return f >= static_cast<double>(
+ (std::numeric_limits<std::size_t>::max)()) ?
+ (std::numeric_limits<std::size_t>::max)() :
+ static_cast<std::size_t>(f);
+ }
+
+ // The space used to store values in a node.
+
+ template <typename ValueType>
+ struct value_base
+ {
+ typedef ValueType value_type;
+
+ typename boost::aligned_storage<
+ sizeof(value_type),
+ boost::alignment_of<value_type>::value>::type data_;
+
+ void* address() {
+ return this;
+ }
+
+ value_type& value() {
+ return *(ValueType*) this;
+ }
+
+ value_type* value_ptr() {
+ return (ValueType*) this;
+ }
+
+ private:
+
+ value_base& operator=(value_base const&);
+ };
+
+ template <typename Types>
+ struct table :
+ boost::unordered::detail::buckets<
+ typename Types::allocator,
+ typename Types::bucket,
+ typename Types::node>,
+ boost::unordered::detail::functions<
+ typename Types::hasher,
+ typename Types::key_equal>
+ {
+ private:
+ table(table const&);
+ table& operator=(table const&);
+ public:
+ typedef typename Types::hasher hasher;
+ typedef typename Types::key_equal key_equal;
+ typedef typename Types::key_type key_type;
+ typedef typename Types::extractor extractor;
+ typedef typename Types::value_type value_type;
+ typedef typename Types::table table_impl;
+ typedef typename Types::link_pointer link_pointer;
+
+ typedef boost::unordered::detail::functions<
+ typename Types::hasher,
+ typename Types::key_equal> functions;
+
+ typedef boost::unordered::detail::buckets<
+ typename Types::allocator,
+ typename Types::bucket,
+ typename Types::node> buckets;
+
+ typedef typename buckets::node_allocator node_allocator;
+ typedef typename buckets::node_allocator_traits node_allocator_traits;
+ typedef typename buckets::node_pointer node_pointer;
+ typedef typename buckets::const_node_pointer const_node_pointer;
+
+ typedef boost::unordered::iterator_detail::
+ iterator<node_pointer, value_type> iterator;
+ typedef boost::unordered::iterator_detail::
+ c_iterator<const_node_pointer, node_pointer, value_type> c_iterator;
+ typedef boost::unordered::iterator_detail::
+ l_iterator<node_pointer, value_type> l_iterator;
+ typedef boost::unordered::iterator_detail::
+ cl_iterator<const_node_pointer, node_pointer, value_type>
+ cl_iterator;
+
+ // Members
+
+ float mlf_;
+ std::size_t max_load_; // Only use if this->buckets_.
+
         ////////////////////////////////////////////////////////////////////////
         // Load methods
 
@@ -128,7 +356,7 @@
             using namespace std;
     
             // size < mlf_ * count
- return double_to_size_t(ceil(
+ return boost::unordered::detail::double_to_size(ceil(
                     static_cast<double>(this->mlf_) *
                     static_cast<double>(this->max_bucket_count())
                 )) - 1;
@@ -140,18 +368,17 @@
     
             // From 6.3.1/13:
             // Only resize when size >= mlf_ * count
- return double_to_size_t(ceil(
+ return boost::unordered::detail::double_to_size(ceil(
                     static_cast<double>(this->mlf_) *
                     static_cast<double>(this->bucket_count_)
                 ));
 
         }
-
         void max_load_factor(float z)
         {
             BOOST_ASSERT(z > 0);
             mlf_ = (std::max)(z, minimum_max_load_factor);
- if (BOOST_UNORDERED_BORLAND_BOOL(this->buckets_))
+ if (this->buckets_)
                 this->max_load_ = this->calculate_max_load();
         }
 
@@ -167,9 +394,11 @@
             //
             // Or from rehash post-condition:
             // count > size / mlf_
- return next_prime(double_to_size_t(floor(
- static_cast<double>(size) /
- static_cast<double>(mlf_))) + 1);
+
+ return boost::unordered::detail::next_prime(
+ boost::unordered::detail::double_to_size(floor(
+ static_cast<double>(size) /
+ static_cast<double>(mlf_))) + 1);
         }
 
         ////////////////////////////////////////////////////////////////////////
@@ -178,35 +407,38 @@
         table(std::size_t num_buckets,
                 hasher const& hf,
                 key_equal const& eq,
- node_allocator const& a)
- : buckets(a, next_prime(num_buckets)),
+ node_allocator const& a) :
+ buckets(a, boost::unordered::detail::next_prime(num_buckets)),
             functions(hf, eq),
             mlf_(1.0f),
             max_load_(0)
- {
- }
+ {}
 
- table(table const& x, node_allocator const& a)
- : buckets(a, x.min_buckets_for_size(x.size_)),
+ table(table const& x, node_allocator const& a) :
+ buckets(a, x.min_buckets_for_size(x.size_)),
             functions(x),
             mlf_(x.mlf_),
             max_load_(0)
         {
             if(x.size_) {
- x.copy_buckets_to(*this);
+ table_impl::copy_buckets_to(x, *this);
                 this->max_load_ = calculate_max_load();
             }
         }
 
- table(table& x, move_tag m)
- : buckets(x, m),
+ // TODO: Why calculate_max_load?
+ table(table& x, boost::unordered::detail::move_tag m) :
+ buckets(x, m),
             functions(x),
             mlf_(x.mlf_),
- max_load_(calculate_max_load()) {}
+ max_load_(calculate_max_load())
+ {}
 
+ // TODO: Why not calculate_max_load?
         // TODO: Why do I use x's bucket count?
- table(table& x, node_allocator const& a, move_tag m)
- : buckets(a, x.bucket_count_),
+ table(table& x, node_allocator const& a,
+ boost::unordered::detail::move_tag m) :
+ buckets(a, x.bucket_count_),
             functions(x),
             mlf_(x.mlf_),
             max_load_(x.max_load_)
@@ -217,27 +449,28 @@
             else if(x.size_) {
                 // Use a temporary table because move_buckets_to leaves the
                 // source container in a complete mess.
+
                 buckets tmp(x, m);
- tmp.move_buckets_to(*this);
+ table_impl::move_buckets_to(tmp, *this);
                 this->max_load_ = calculate_max_load();
             }
         }
 
- ~table()
- {}
-
         // Iterators
 
- node_ptr begin() const {
+ node_pointer begin() const {
             return !this->buckets_ ?
- node_ptr() : this->buckets_[this->bucket_count_].next_;
+ node_pointer() : this->get_start();
         }
 
+ // Assignment
+
         void assign(table const& x)
         {
- assign(x, integral_constant<bool,
- allocator_traits<node_allocator>::
- propagate_on_container_copy_assignment::value>());
+ assign(x,
+ boost::unordered::detail::integral_constant<bool,
+ allocator_traits<node_allocator>::
+ propagate_on_container_copy_assignment::value>());
         }
 
         void assign(table const& x, false_type)
@@ -259,11 +492,12 @@
 
         void move_assign(table& x)
         {
- move_assign(x, integral_constant<bool,
- allocator_traits<node_allocator>::
- propagate_on_container_move_assignment::value>());
+ move_assign(x,
+ boost::unordered::detail::integral_constant<bool,
+ allocator_traits<node_allocator>::
+ propagate_on_container_move_assignment::value>());
         }
-
+
         void move_assign(table& x, true_type)
         {
             if(this->buckets_) this->delete_buckets();
@@ -278,12 +512,14 @@
                 move_assign_no_alloc(x);
             }
             else {
- set_hash_functions<hasher, key_equal> new_func_this(*this, x);
+ boost::unordered::detail::set_hash_functions<hasher, key_equal>
+ new_func_this(*this, x);
 
                 if (x.size_) {
- buckets b(this->node_alloc(), x.min_buckets_for_size(x.size_));
+ buckets b(this->node_alloc(),
+ x.min_buckets_for_size(x.size_));
                     buckets tmp(x, move_tag());
- tmp.move_buckets_to(b);
+ table_impl::move_buckets_to(tmp, b);
                     b.swap(*this);
                 }
                 else {
@@ -298,7 +534,8 @@
         
         void move_assign_no_alloc(table& x)
         {
- set_hash_functions<hasher, key_equal> new_func_this(*this, x);
+ boost::unordered::detail::set_hash_functions<hasher, key_equal>
+ new_func_this(*this, x);
             // No throw from here.
             this->move_buckets_from(x);
             this->mlf_ = x.mlf_;
@@ -311,7 +548,8 @@
 
         void swap(table& x)
         {
- swap(x, integral_constant<bool,
+ swap(x,
+ boost::unordered::detail::integral_constant<bool,
                     allocator_traits<node_allocator>::
                     propagate_on_container_swap::value>());
         }
@@ -320,8 +558,10 @@
         template <typename Propagate>
         void swap(table& x, Propagate p)
         {
- set_hash_functions<hasher, key_equal> op1(*this, x);
- set_hash_functions<hasher, key_equal> op2(x, *this);
+ boost::unordered::detail::set_hash_functions<hasher, key_equal>
+ op1(*this, x);
+ boost::unordered::detail::set_hash_functions<hasher, key_equal>
+ op2(x, *this);
             // I think swap can throw if Propagate::value,
             // since the allocators' swap can throw. Not sure though.
             this->buckets::swap(x, p);
@@ -339,110 +579,88 @@
             std::swap(this->max_load_, x.max_load_);
         }
 
- ////////////////////////////////////////////////////////////////////////
- // Key methods
+ // Accessors
 
- std::size_t count(key_type const& k) const
+ key_type const& get_key(value_type const& x) const
         {
- if(!this->size_) return 0;
- return node::group_count(find_node(k));
+ return extractor::extract(x);
         }
 
- value_type& at(key_type const& k) const
+ // Find Node
+
+ template <typename Key, typename Hash, typename Pred>
+ node_pointer generic_find_node(
+ Key const& k,
+ Hash const& hash_function,
+ Pred const& eq) const
         {
- if (this->size_) {
- node_ptr it = find_node(k);
- if (BOOST_UNORDERED_BORLAND_BOOL(it))
- return node::get_value(it);
- }
-
- ::boost::throw_exception(
- std::out_of_range("Unable to find key in unordered_map."));
+ if (!this->size_) return node_pointer();
+ return static_cast<table_impl const*>(this)->
+ find_node_impl(hash_function(k), k, eq);
         }
 
- iterator_pair equal_range(key_type const& k) const
+ node_pointer find_node(
+ std::size_t hash,
+ key_type const& k) const
         {
- if(!this->size_)
- return iterator_pair(node_ptr(), node_ptr());
-
- node_ptr ptr = find_node(k);
- return iterator_pair(ptr, !ptr ? ptr : node::next_group(ptr));
+ if (!this->size_) return node_pointer();
+ return static_cast<table_impl const*>(this)->
+ find_node_impl(hash, k, this->key_eq());
         }
 
- // Erase
- //
- // no throw
+ node_pointer find_node(key_type const& k) const
+ {
+ if (!this->size_) return node_pointer();
+ return static_cast<table_impl const*>(this)->
+ find_node_impl(this->hash_function()(k), k, this->key_eq());
+ }
 
- std::size_t erase_key(key_type const& k)
+ node_pointer find_matching_node(node_pointer n) const
         {
- if(!this->size_) return 0;
-
- std::size_t hash = this->hash_function()(k);
- std::size_t bucket_index = hash % this->bucket_count_;
- bucket_ptr bucket = this->get_bucket(bucket_index);
-
- node_ptr prev = bucket->next_;
- if (!prev) return 0;
-
- for (;;)
- {
- if (!prev->next_) return 0;
- std::size_t node_hash = node::get_hash(prev->next_);
- if (node_hash % this->bucket_count_ != bucket_index)
- return 0;
- if (node_hash == hash &&
- this->key_eq()(k, get_key(node::get_value(prev->next_))))
- break;
- prev = node::next_group2(prev);
- }
+ // TODO: Does this apply to C++11?
+ //
+ // For some stupid reason, I decided to support equality comparison
+ // when different hash functions are used. So I can't use the hash
+ // value from the node here.
     
- node_ptr pos = prev->next_;
- node_ptr end = node::next_group(pos);
- prev->next_ = end;
- this->fix_buckets(bucket, prev, end);
- return this->delete_nodes(pos, end);
+ return find_node(get_key(n->value()));
         }
 
         // Reserve and rehash
 
- bool reserve_for_insert(std::size_t);
+ void reserve_for_insert(std::size_t);
         void rehash(std::size_t);
     };
-
+
     ////////////////////////////////////////////////////////////////////////////
     // Reserve & Rehash
 
     // basic exception safety
- template <class T>
- inline bool table<T>::reserve_for_insert(std::size_t size)
+ template <typename Types>
+ inline void table<Types>::reserve_for_insert(std::size_t size)
     {
         if (!this->buckets_) {
- std::size_t old_bucket_count = this->bucket_count_;
             this->bucket_count_ = (std::max)(this->bucket_count_,
                 this->min_buckets_for_size(size));
             this->create_buckets();
- this->max_load_ = calculate_max_load();
- return old_bucket_count != this->bucket_count_;
+ this->max_load_ = this->calculate_max_load();
         }
         else if(size >= max_load_) {
             std::size_t num_buckets
                 = this->min_buckets_for_size((std::max)(size,
                     this->size_ + (this->size_ >> 1)));
             if (num_buckets != this->bucket_count_) {
- this->rehash_impl(num_buckets);
- this->max_load_ = calculate_max_load();
- return true;
+ static_cast<table_impl*>(this)->rehash_impl(num_buckets);
+ this->max_load_ = this->calculate_max_load();
             }
         }
-
- return false;
     }
 
     // if hash function throws, basic exception safety
     // strong otherwise.
 
- template <class T>
- void table<T>::rehash(std::size_t min_buckets)
+ template <typename Types>
+ void table<Types>::rehash(std::size_t min_buckets)
     {
         using namespace std;
 
@@ -451,306 +669,17 @@
             this->bucket_count_ = next_prime(min_buckets);
         }
         else {
- // no throw:
             min_buckets = next_prime((std::max)(min_buckets,
- double_to_size_t(floor(
+ boost::unordered::detail::double_to_size(floor(
                     static_cast<double>(this->size_) /
                     static_cast<double>(mlf_))) + 1));
+
             if(min_buckets != this->bucket_count_) {
- this->rehash_impl(min_buckets);
- this->max_load_ = calculate_max_load();
+ static_cast<table_impl*>(this)->rehash_impl(min_buckets);
+ this->max_load_ = this->calculate_max_load();
             }
         }
     }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // types
- //
- // This is used to convieniently pass around a container's typedefs
- // without having 7 template parameters.
-
- template <class K, class V, class H, class P, class A, class E, bool Unique>
- struct types
- {
- public:
- typedef K key_type;
- typedef V value_type;
- typedef H hasher;
- typedef P key_equal;
- typedef A value_allocator;
- typedef E extractor;
-
- typedef ::boost::unordered::detail::node_constructor<value_allocator, Unique> node_constructor;
- typedef ::boost::unordered::detail::buckets<value_allocator, Unique> buckets;
- typedef ::boost::unordered::detail::functions<hasher, key_equal> functions;
-
- typedef 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;
- };
-}}}
-
-namespace boost { namespace unordered { namespace iterator_detail {
-
- // Iterators
- //
- // all no throw
-
- template <class A, bool Unique> class iterator;
- template <class A, bool Unique> class c_iterator;
- template <class A, bool Unique> class l_iterator;
- template <class A, bool Unique> class cl_iterator;
-
- // Local Iterators
- //
- // all no throw
-
- template <class A, bool Unique>
- class l_iterator
- : public ::boost::iterator <
- std::forward_iterator_tag,
- typename boost::unordered::detail::allocator_traits<A>::value_type,
- std::ptrdiff_t,
- typename boost::unordered::detail::allocator_traits<A>::pointer,
- typename boost::unordered::detail::allocator_traits<A>::value_type&>
- {
- public:
- typedef typename boost::unordered::detail::allocator_traits<A>::value_type value_type;
-
- private:
- typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
- 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>;
-
- node_ptr ptr_;
- std::size_t bucket_;
- std::size_t bucket_count_;
-
- public:
- l_iterator() : ptr_() {}
- l_iterator(node_ptr x, std::size_t b, std::size_t c)
- : ptr_(x), bucket_(b), bucket_count_(c) {}
- typename boost::unordered::detail::allocator_traits<A>::value_type& operator*() const {
- return node::get_value(ptr_);
- }
- value_type* operator->() const {
- return node::get_value_ptr(ptr_);
- }
- l_iterator& operator++() {
- ptr_ = ptr_->next_;
- if (ptr_ && node::get_hash(ptr_) % bucket_count_ != bucket_)
- ptr_ = node_ptr();
- return *this;
- }
- l_iterator operator++(int) {
- l_iterator tmp(*this);
- ptr_ = ptr_->next_;
- if (ptr_ && node::get_hash(ptr_) % bucket_count_ != bucket_)
- ptr_ = node_ptr();
- return tmp;
- }
- bool operator==(l_iterator x) const {
- return ptr_ == x.ptr_;
- }
- bool operator==(const_local_iterator x) const {
- return ptr_ == x.ptr_;
- }
- bool operator!=(l_iterator x) const {
- return ptr_ != x.ptr_;
- }
- bool operator!=(const_local_iterator x) const {
- return ptr_ != x.ptr_;
- }
- };
-
- template <class A, bool Unique>
- class cl_iterator
- : public ::boost::iterator <
- std::forward_iterator_tag,
- typename boost::unordered::detail::allocator_traits<A>::value_type,
- std::ptrdiff_t,
- typename boost::unordered::detail::allocator_traits<A>::const_pointer,
- typename boost::unordered::detail::allocator_traits<A>::value_type const& >
- {
- public:
- typedef typename boost::unordered::detail::allocator_traits<A>::value_type value_type;
-
- private:
- typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
- 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>;
-
- node_ptr ptr_;
- std::size_t bucket_;
- std::size_t bucket_count_;
-
- public:
- cl_iterator() : ptr_() {}
- cl_iterator(node_ptr x, std::size_t b, std::size_t c)
- : ptr_(x), bucket_(b), bucket_count_(c) {}
- cl_iterator(local_iterator x)
- : ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
- {}
- typename boost::unordered::detail::allocator_traits<A>::value_type const&
- operator*() const {
- return node::get_value(ptr_);
- }
- value_type const* operator->() const {
- return node::get_value_ptr(ptr_);
- }
- cl_iterator& operator++() {
- ptr_ = ptr_->next_;
- if (ptr_ && node::get_hash(ptr_) % bucket_count_ != bucket_)
- ptr_ = node_ptr();
- return *this;
- }
- cl_iterator operator++(int) {
- cl_iterator tmp(*this);
- ptr_ = ptr_->next_;
- if (ptr_ && node::get_hash(ptr_) % bucket_count_ != bucket_)
- ptr_ = node_ptr();
- return tmp;
- }
- bool operator==(local_iterator x) const {
- return ptr_ == x.ptr_;
- }
- bool operator==(cl_iterator x) const {
- return ptr_ == x.ptr_;
- }
- bool operator!=(local_iterator x) const {
- return ptr_ != x.ptr_;
- }
- bool operator!=(cl_iterator x) const {
- return ptr_ != x.ptr_;
- }
- };
-
- template <class A, bool Unique>
- class iterator
- : public ::boost::iterator <
- std::forward_iterator_tag,
- typename boost::unordered::detail::allocator_traits<A>::value_type,
- std::ptrdiff_t,
- typename boost::unordered::detail::allocator_traits<A>::pointer,
- typename boost::unordered::detail::allocator_traits<A>::value_type& >
- {
- public:
- typedef typename boost::unordered::detail::allocator_traits<A>::value_type value_type;
-
- private:
- typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
- 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_;
-
- public:
-
- iterator() : node_() {}
- explicit iterator(node_ptr const& x) : node_(x) {}
- typename boost::unordered::detail::allocator_traits<A>::value_type& operator*() const {
- return node::get_value(node_);
- }
- value_type* operator->() const {
- return &node::get_value(node_);
- }
- iterator& operator++() {
- node_ = node_->next_; return *this;
- }
- iterator operator++(int) {
- iterator tmp(node_); node_ = node_->next_; return tmp;
- }
- bool operator==(iterator const& x) const {
- return node_ == x.node_;
- }
- bool operator==(const_iterator const& x) const {
- return node_ == x.node_;
- }
- bool operator!=(iterator const& x) const {
- return node_ != x.node_;
- }
- bool operator!=(const_iterator const& x) const {
- return node_ != x.node_;
- }
- };
-
- template <class A, bool Unique>
- class c_iterator
- : public ::boost::iterator <
- std::forward_iterator_tag,
- typename boost::unordered::detail::allocator_traits<A>::value_type,
- std::ptrdiff_t,
- typename boost::unordered::detail::allocator_traits<A>::const_pointer,
- typename boost::unordered::detail::allocator_traits<A>::value_type const& >
- {
- public:
- typedef typename boost::unordered::detail::allocator_traits<A>::value_type value_type;
-
- private:
- typedef ::boost::unordered::detail::buckets<A, Unique> buckets;
- 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>;
-
-#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
- template <class K, class T, class H, class P, class A2>
- friend class ::boost::unordered::unordered_map;
- template <class K, class T, class H, class P, class A2>
- friend class ::boost::unordered::unordered_multimap;
- template <class T, class H, class P, class A2>
- friend class ::boost::unordered::unordered_set;
- template <class T, class H, class P, class A2>
- friend class ::boost::unordered::unordered_multiset;
-#else
- public:
-#endif
-
- node_ptr node_;
-
- public:
-
- c_iterator() : node_() {}
- explicit c_iterator(node_ptr const& x) : node_(x) {}
- c_iterator(iterator const& x) : node_(x.node_) {}
- typename boost::unordered::detail::allocator_traits<A>::value_type const& operator*() const {
- return node::get_value(node_);
- }
- value_type const* operator->() const {
- return &node::get_value(node_);
- }
- c_iterator& operator++() {
- node_ = node_->next_; return *this;
- }
- c_iterator operator++(int) {
- c_iterator tmp(node_); node_ = node_->next_; return tmp;
- }
- bool operator==(iterator const& x) const {
- return node_ == x.node_;
- }
- bool operator==(c_iterator const& x) const {
- return node_ == x.node_;
- }
- bool operator!=(iterator const& x) const {
- return node_ != x.node_;
- }
- bool operator!=(c_iterator const& x) const {
- return node_ != x.node_;
- }
- };
 }}}
 
 #endif

Modified: branches/release/boost/unordered/detail/unique.hpp
==============================================================================
--- branches/release/boost/unordered/detail/unique.hpp (original)
+++ branches/release/boost/unordered/detail/unique.hpp 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -7,66 +7,278 @@
 #ifndef BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
 #define BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
 
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/unordered/detail/table.hpp>
+#include <boost/unordered/detail/emplace_args.hpp>
 #include <boost/unordered/detail/extract_key.hpp>
+#include <boost/throw_exception.hpp>
+#include <stdexcept>
 
 namespace boost { namespace unordered { namespace detail {
 
- template <class T>
- class unique_table : public T::table_base
+ template <typename A, typename T> struct node;
+ template <typename T> struct ptr_node;
+ template <typename Types> struct table_impl;
+
+ template <typename A, typename T>
+ struct node :
+ boost::unordered::detail::value_base<T>
+ {
+ typedef typename ::boost::unordered::detail::rebind_wrap<
+ A, node<A, T> >::type::pointer link_pointer;
+
+ link_pointer next_;
+ std::size_t hash_;
+
+ node() :
+ next_(),
+ hash_(0)
+ {}
+
+ void init(link_pointer)
+ {
+ }
+ };
+
+ template <typename T>
+ struct ptr_node :
+ boost::unordered::detail::value_base<T>,
+ boost::unordered::detail::ptr_bucket
+ {
+ typedef boost::unordered::detail::ptr_bucket bucket_base;
+ typedef ptr_bucket* link_pointer;
+
+ std::size_t hash_;
+
+ ptr_node() :
+ bucket_base(),
+ hash_(0)
+ {}
+
+ void init(link_pointer)
+ {
+ }
+ };
+
+ // If the allocator uses raw pointers use ptr_node
+ // Otherwise use node.
+
+ template <typename A, typename T, typename NodePtr, typename BucketPtr>
+ struct pick_node2
+ {
+ typedef boost::unordered::detail::node<A, T> node;
+
+ typedef typename boost::unordered::detail::allocator_traits<
+ typename boost::unordered::detail::rebind_wrap<A, node>::type
+ >::pointer node_pointer;
+
+ typedef boost::unordered::detail::bucket<node_pointer> bucket;
+ typedef node_pointer link_pointer;
+ };
+
+ template <typename A, typename T>
+ struct pick_node2<A, T,
+ boost::unordered::detail::ptr_node<T>*,
+ boost::unordered::detail::ptr_bucket*>
     {
- public:
- 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;
+ typedef boost::unordered::detail::ptr_node<T> node;
+ typedef boost::unordered::detail::ptr_bucket bucket;
+ typedef bucket* link_pointer;
+ };
+
+ template <typename A, typename T>
+ struct pick_node
+ {
+ typedef boost::unordered::detail::allocator_traits<
+ typename boost::unordered::detail::rebind_wrap<A,
+ boost::unordered::detail::ptr_node<T> >::type
+ > tentative_node_traits;
+
+ typedef boost::unordered::detail::allocator_traits<
+ typename boost::unordered::detail::rebind_wrap<A,
+ boost::unordered::detail::ptr_bucket >::type
+ > tentative_bucket_traits;
+
+ typedef pick_node2<A, T,
+ typename tentative_node_traits::pointer,
+ typename tentative_bucket_traits::pointer> pick;
+
+ typedef typename pick::node node;
+ typedef typename pick::bucket bucket;
+ typedef typename pick::link_pointer link_pointer;
+ };
+
+ template <typename A, typename H, typename P>
+ struct set
+ {
+ typedef boost::unordered::detail::set<A, H, P> types;
+
+ typedef A allocator;
+ typedef H hasher;
+ typedef P key_equal;
+
+ typedef boost::unordered::detail::allocator_traits<A> traits;
+ typedef typename traits::value_type value_type;
+ typedef value_type key_type;
+
+ typedef boost::unordered::detail::pick_node<A, value_type> pick;
+ typedef typename pick::node node;
+ typedef typename pick::bucket bucket;
+ typedef typename pick::link_pointer link_pointer;
+
+ typedef boost::unordered::detail::table_impl<types> table;
+ typedef boost::unordered::detail::set_extractor<value_type> extractor;
+ };
+
+ template <typename A, typename K, typename H, typename P>
+ struct map
+ {
+ typedef boost::unordered::detail::map<A, K, H, P> types;
+
+ typedef A allocator;
+ typedef H hasher;
+ typedef P key_equal;
+ typedef K key_type;
+
+ typedef boost::unordered::detail::allocator_traits<A> traits;
+ typedef typename traits::value_type value_type;
+
+ typedef boost::unordered::detail::pick_node<A, value_type> pick;
+ typedef typename pick::node node;
+ typedef typename pick::bucket bucket;
+ typedef typename pick::link_pointer link_pointer;
+
+ typedef boost::unordered::detail::table_impl<types> table;
+ typedef boost::unordered::detail::map_extractor<key_type, value_type>
+ extractor;
+ };
+
+ template <typename Types>
+ struct table_impl : boost::unordered::detail::table<Types>
+ {
+ typedef boost::unordered::detail::table<Types> table;
+ typedef typename table::value_type value_type;
+ typedef typename table::bucket bucket;
+ typedef typename table::buckets buckets;
+ typedef typename table::node_pointer node_pointer;
+ typedef typename table::node_allocator node_allocator;
+ typedef typename table::node_allocator_traits node_allocator_traits;
+ typedef typename table::bucket_pointer bucket_pointer;
+ typedef typename table::link_pointer link_pointer;
+ typedef typename table::previous_pointer previous_pointer;
+ typedef typename table::hasher hasher;
+ typedef typename table::key_equal key_equal;
+ typedef typename table::key_type key_type;
+ typedef typename table::node_constructor node_constructor;
+ typedef typename table::extractor extractor;
+
+ typedef std::pair<node_pointer, bool> emplace_return;
 
         // Constructors
 
- unique_table(std::size_t n, hasher const& hf, key_equal const& eq,
- value_allocator const& a)
- : table_base(n, hf, eq, a) {}
- unique_table(unique_table const& x)
- : table_base(x,
- allocator_traits<node_allocator>::
+ table_impl(std::size_t n,
+ hasher const& hf,
+ key_equal const& eq,
+ node_allocator const& a)
+ : table(n, hf, eq, a)
+ {}
+
+ table_impl(table_impl const& x)
+ : table(x, node_allocator_traits::
                 select_on_container_copy_construction(x.node_alloc())) {}
- unique_table(unique_table const& x, value_allocator const& a)
- : table_base(x, a) {}
- unique_table(unique_table& x, move_tag m)
- : table_base(x, m) {}
- unique_table(unique_table& x, value_allocator const& a,
- move_tag m)
- : table_base(x, a, m) {}
- ~unique_table() {}
+
+ table_impl(table_impl const& x,
+ node_allocator const& a)
+ : table(x, a)
+ {}
+
+ table_impl(table_impl& x,
+ boost::unordered::detail::move_tag m)
+ : table(x, m)
+ {}
+
+ table_impl(table_impl& x,
+ node_allocator const& a,
+ boost::unordered::detail::move_tag m)
+ : table(x, a, m)
+ {}
+
+ // Accessors
+
+ template <class Key, class Pred>
+ node_pointer find_node_impl(
+ std::size_t hash,
+ Key const& k,
+ Pred const& eq) const
+ {
+ std::size_t bucket_index = hash % this->bucket_count_;
+ node_pointer n = this->get_start(bucket_index);
+
+ for (;;)
+ {
+ if (!n) return n;
+
+ std::size_t node_hash = n->hash_;
+ if (hash == node_hash)
+ {
+ if (eq(k, this->get_key(n->value())))
+ return n;
+ }
+ else
+ {
+ if (node_hash % this->bucket_count_ != bucket_index)
+ return node_pointer();
+ }
+
+ n = static_cast<node_pointer>(n->next_);
+ }
+ }
+
+ std::size_t count(key_type const& k) const
+ {
+ return this->find_node(k) ? 1 : 0;
+ }
+
+ value_type& at(key_type const& k) const
+ {
+ if (this->size_) {
+ node_pointer it = this->find_node(k);
+ if (it) return it->value();
+ }
+
+ boost::throw_exception(
+ std::out_of_range("Unable to find key in unordered_map."));
+ }
+
+ std::pair<node_pointer, node_pointer>
+ equal_range(key_type const& k) const
+ {
+ node_pointer n = this->find_node(k);
+ return std::make_pair(n,
+ n ? static_cast<node_pointer>(n->next_) : n);
+ }
 
         // equals
 
- bool equals(unique_table const& other) const
+ bool equals(table_impl const& other) const
         {
             if(this->size_ != other.size_) return false;
             if(!this->size_) return true;
     
- for(node_ptr n1 = this->get_bucket(this->bucket_count_)->next_;
- n1; n1 = n1->next_)
+ for(node_pointer n1 = this->get_start(); n1;
+ n1 = static_cast<node_pointer>(n1->next_))
             {
- node_ptr n2 = other.find_matching_node(n1);
+ node_pointer n2 = other.find_matching_node(n1);
 
 #if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
- if(!n2 || node::get_value(n1) != node::get_value(n2))
+ if(!n2 || n1->value() != n2->value())
                     return false;
 #else
                 if(!n2 || !extractor::compare_mapped(
- node::get_value(n1), node::get_value(n2)))
+ n1->value(), n2->value()))
                     return false;
 #endif
             }
@@ -74,248 +286,148 @@
             return true;
         }
 
- ////////////////////////////////////////////////////////////////////////
- // A convenience method for adding nodes.
+ // Emplace/Insert
 
- node_ptr add_node(
+ inline node_pointer add_node(
                 node_constructor& a,
- std::size_t bucket_index,
- std::size_t hash)
+ std::size_t hash)
         {
- bucket_ptr b = this->get_bucket(bucket_index);
- node_ptr n = a.release();
- node::set_hash(n, hash);
+ node_pointer n = a.release();
+ n->hash_ = hash;
     
+ bucket_pointer b = this->get_bucket(hash % this->bucket_count_);
+
             if (!b->next_)
             {
- bucket_ptr start_node = this->get_bucket(this->bucket_count_);
+ previous_pointer start_node = this->get_previous_start();
                 
                 if (start_node->next_) {
- this->buckets_[
- node::get_hash(start_node->next_) % this->bucket_count_
- ].next_ = n;
+ this->get_bucket(
+ static_cast<node_pointer>(start_node->next_)->hash_ %
+ this->bucket_count_)->next_ = n;
                 }
-
+
                 b->next_ = start_node;
                 n->next_ = start_node->next_;
- start_node->next_ = n;
+ start_node->next_ = static_cast<link_pointer>(n);
             }
             else
             {
                 n->next_ = b->next_->next_;
- b->next_->next_ = n;
+ b->next_->next_ = static_cast<link_pointer>(n);
             }
-
+
             ++this->size_;
             return n;
         }
 
- ////////////////////////////////////////////////////////////////////////////
- // Insert methods
-
- // if hash function throws, basic exception safety
- // strong otherwise
-
         value_type& operator[](key_type const& k)
         {
             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_;
- node_ptr pos = this->find_node(bucket_index, hash, k);
-
- if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
- return node::get_value(pos);
- }
-
- // Create the node before rehashing in case it throws an
- // exception (need strong safety in such a case).
- node_constructor a(*this);
- a.construct_pair(k, (mapped_type*) 0);
-
- // reserve has basic exception safety if the hash function
- // throws, strong otherwise.
- if(this->reserve_for_insert(this->size_ + 1))
- bucket_index = hash % this->bucket_count_;
-
- // Nothing after this point can throw.
-
- return node::get_value(add_node(a, bucket_index, hash));
- }
-
- emplace_return emplace_impl_with_node(node_constructor& a)
- {
- // No side effects in this initial code
- key_type const& k = this->get_key(a.value());
- std::size_t hash = this->hash_function()(k);
- std::size_t bucket_index = hash % this->bucket_count_;
- node_ptr pos = this->find_node(bucket_index, hash, k);
-
- if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
- // Found an existing key, return it (no throw).
- return emplace_return(pos, false);
- }
+ node_pointer pos = this->find_node(hash, k);
     
- // reserve has basic exception safety if the hash function
- // throws, strong otherwise.
- if(this->reserve_for_insert(this->size_ + 1))
- bucket_index = hash % this->bucket_count_;
-
- // Nothing after this point can throw.
-
- return emplace_return(add_node(a, bucket_index, hash), true);
- }
-
- emplace_return insert(value_type const& v)
- {
- key_type const& k = extractor::extract(v);
- std::size_t hash = this->hash_function()(k);
- std::size_t bucket_index = hash % this->bucket_count_;
- node_ptr pos = this->find_node(bucket_index, hash, k);
-
- if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
- // Found an existing key, return it (no throw).
- return emplace_return(pos, false);
- }
-
- // Isn't in table, add to bucket.
+ if (pos) return pos->value();
     
             // Create the node before rehashing in case it throws an
             // exception (need strong safety in such a case).
- node_constructor a(*this);
- a.construct(v);
-
- // reserve has basic exception safety if the hash function
- // throws, strong otherwise.
- if(this->reserve_for_insert(this->size_ + 1))
- bucket_index = hash % this->bucket_count_;
-
- // Nothing after this point can throw.
+ node_constructor a(this->node_alloc());
+ a.construct_node();
+#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+ a.construct_value(boost::unordered::piecewise_construct,
+ boost::make_tuple(k), boost::make_tuple());
+#else
+ a.construct_value(
+ boost::unordered::detail::create_emplace_args(
+ boost::unordered::piecewise_construct,
+ boost::make_tuple(k),
+ boost::make_tuple()));
+#endif
     
- return emplace_return(add_node(a, bucket_index, hash), true);
+ this->reserve_for_insert(this->size_ + 1);
+ return add_node(a, hash)->value();
         }
 
-
 #if defined(BOOST_NO_RVALUE_REFERENCES)
- emplace_return emplace(please_ignore_this_overload const&)
+ emplace_return emplace(boost::unordered::detail::emplace_args1<
+ boost::unordered::detail::please_ignore_this_overload> const&)
         {
             BOOST_ASSERT(false);
             return emplace_return(this->begin(), false);
         }
 #endif
 
+ template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ emplace_return emplace(BOOST_UNORDERED_EMPLACE_ARGS)
+ {
 #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+ return emplace_impl(
+ extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
+ BOOST_UNORDERED_EMPLACE_FORWARD);
 
- template<class... Args>
- emplace_return emplace(Args&&... args)
- {
+#else
             return emplace_impl(
- extractor::extract(std::forward<Args>(args)...),
- std::forward<Args>(args)...);
+ extractor::extract(args.a0, args.a1),
+ BOOST_UNORDERED_EMPLACE_FORWARD);
+#endif
         }
 
- template<class... Args>
- emplace_return emplace_impl(key_type const& k, Args&&... args)
+#if !defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
+ template <typename A0>
+ emplace_return emplace(
+ boost::unordered::detail::emplace_args1<A0> const& args)
+ {
+ return emplace_impl(extractor::extract(args.a0), args);
+ }
+#endif
+
+ template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ emplace_return emplace_impl(key_type const& k,
+ BOOST_UNORDERED_EMPLACE_ARGS)
         {
- // No side effects in this initial code
             std::size_t hash = this->hash_function()(k);
- std::size_t bucket_index = hash % this->bucket_count_;
- node_ptr pos = this->find_node(bucket_index, hash, k);
+ node_pointer pos = this->find_node(hash, k);
     
- if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
- // Found an existing key, return it (no throw).
- return emplace_return(pos, false);
- }
-
- // Doesn't already exist, add to bucket.
- // Side effects only in this block.
+ if (pos) return emplace_return(pos, false);
     
             // Create the node before rehashing in case it throws an
             // exception (need strong safety in such a case).
- node_constructor a(*this);
- a.construct(std::forward<Args>(args)...);
+ node_constructor a(this->node_alloc());
+ a.construct_node();
+ a.construct_value(BOOST_UNORDERED_EMPLACE_FORWARD);
     
             // reserve has basic exception safety if the hash function
             // throws, strong otherwise.
- if(this->reserve_for_insert(this->size_ + 1))
- bucket_index = hash % this->bucket_count_;
-
- // Nothing after this point can throw.
-
- return emplace_return(add_node(a, bucket_index, hash), true);
+ this->reserve_for_insert(this->size_ + 1);
+ return emplace_return(this->add_node(a, hash), true);
         }
 
- template<class... Args>
- emplace_return emplace_impl(no_key, Args&&... args)
+ emplace_return emplace_impl_with_node(node_constructor& a)
         {
- // Construct the node regardless - in order to get the key.
- // It will be discarded if it isn't used
- node_constructor a(*this);
- a.construct(std::forward<Args>(args)...);
- return emplace_impl_with_node(a);
+ key_type const& k = this->get_key(a.value());
+ std::size_t hash = this->hash_function()(k);
+ node_pointer pos = this->find_node(hash, k);
+
+ if (pos) return emplace_return(pos, false);
+
+ // reserve has basic exception safety if the hash function
+ // throws, strong otherwise.
+ this->reserve_for_insert(this->size_ + 1);
+ return emplace_return(this->add_node(a, hash), true);
         }
-#else
 
- template <class Arg0>
- emplace_return emplace(BOOST_FWD_REF(Arg0) arg0)
+ template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ emplace_return emplace_impl(no_key, BOOST_UNORDERED_EMPLACE_ARGS)
         {
- return emplace_impl(
- extractor::extract(boost::forward<Arg0>(arg0)),
- boost::forward<Arg0>(arg0));
+ // Don't have a key, so construct the node first in order
+ // to be able to lookup the position.
+ node_constructor a(this->node_alloc());
+ a.construct_node();
+ a.construct_value(BOOST_UNORDERED_EMPLACE_FORWARD);
+ return emplace_impl_with_node(a);
         }
 
-#define BOOST_UNORDERED_INSERT1_IMPL(z, n, _) \
- template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
- emplace_return emplace( \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
- { \
- return emplace_impl(extractor::extract(arg0, arg1), \
- BOOST_UNORDERED_CALL_PARAMS(z, n)); \
- }
-
-#define BOOST_UNORDERED_INSERT2_IMPL(z, n, _) \
- template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
- emplace_return emplace_impl(key_type const& k, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
- { \
- std::size_t hash = this->hash_function()(k); \
- std::size_t bucket_index = hash % this->bucket_count_; \
- node_ptr pos = this->find_node(bucket_index, hash, k); \
- \
- if (BOOST_UNORDERED_BORLAND_BOOL(pos)) { \
- return emplace_return(pos, false); \
- } else { \
- node_constructor a(*this); \
- a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
- \
- if(this->reserve_for_insert(this->size_ + 1)) \
- bucket_index = hash % this->bucket_count_; \
- \
- return emplace_return( \
- add_node(a, bucket_index, hash), \
- true); \
- } \
- } \
- \
- template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
- emplace_return emplace_impl(no_key, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
- { \
- node_constructor a(*this); \
- a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
- return emplace_impl_with_node(a); \
- }
-
- BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_INSERT1_IMPL, _)
- BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_INSERT2_IMPL, _)
-
-#undef BOOST_UNORDERED_INSERT1_IMPL
-#undef BOOST_UNORDERED_INSERT2_IMPL
-
-#endif
-
         ////////////////////////////////////////////////////////////////////////
         // Insert range methods
         //
@@ -330,25 +442,26 @@
         }
 
         template <class InputIt>
- void insert_range_impl(key_type const&, InputIt i, InputIt j)
+ void insert_range_impl(key_type const& k, InputIt i, InputIt j)
         {
- node_constructor a(*this);
+ node_constructor a(this->node_alloc());
 
             // Special case for empty buckets so that we can use
             // max_load_ (which isn't valid when buckets_ is null).
             if (!this->buckets_) {
- insert_range_empty(a, extractor::extract(*i), i, j);
+ insert_range_empty(a, k, i, j);
                 if (++i == j) return;
             }
 
             do {
                 // Note: can't use get_key as '*i' might not be value_type - it
- // could be a pair with first_types as key_type without const or a
- // different second_type.
+ // could be a pair with first_types as key_type without const or
+ // a different second_type.
                 //
- // TODO: Might be worth storing the value_type instead of the key
- // here. Could be more efficient if '*i' is expensive. Could be
- // less efficient if copying the full value_type is expensive.
+ // TODO: Might be worth storing the value_type instead of the
+ // key here. Could be more efficient if '*i' is expensive. Could
+ // be less efficient if copying the full value_type is
+ // expensive.
                 insert_range_impl2(a, extractor::extract(*i), i, j);
             } while(++i != j);
         }
@@ -358,9 +471,11 @@
             InputIt i, InputIt j)
         {
             std::size_t hash = this->hash_function()(k);
- a.construct(*i);
- this->reserve_for_insert(this->size_ + insert_size(i, j));
- add_node(a, hash % this->bucket_count_, hash);
+ a.construct_node();
+ a.construct_value2(*i);
+ this->reserve_for_insert(this->size_ +
+ boost::unordered::detail::insert_size(i, j));
+ this->add_node(a, hash);
         }
 
         template <class InputIt>
@@ -369,63 +484,221 @@
         {
             // No side effects in this initial code
             std::size_t hash = this->hash_function()(k);
- std::size_t bucket_index = hash % this->bucket_count_;
- node_ptr pos = this->find_node(bucket_index, hash, k);
+ node_pointer pos = this->find_node(hash, k);
     
- if (!BOOST_UNORDERED_BORLAND_BOOL(pos)) {
- // Doesn't already exist, add to bucket.
- // Side effects only in this block.
-
- // Create the node before rehashing in case it throws an
- // exception (need strong safety in such a case).
- a.construct(*i);
-
- // reserve has basic exception safety if the hash function
- // throws, strong otherwise.
- if(this->size_ + 1 >= this->max_load_) {
- this->reserve_for_insert(this->size_ + insert_size(i, j));
- bucket_index = hash % this->bucket_count_;
- }
+ if (!pos) {
+ a.construct_node();
+ a.construct_value2(*i);
+
+ if(this->size_ + 1 >= this->max_load_)
+ this->reserve_for_insert(this->size_ +
+ boost::unordered::detail::insert_size(i, j));
     
                 // Nothing after this point can throw.
- add_node(a, bucket_index, hash);
+ this->add_node(a, hash);
             }
         }
 
         template <class InputIt>
         void insert_range_impl(no_key, InputIt i, InputIt j)
         {
- node_constructor a(*this);
+ node_constructor a(this->node_alloc());
 
             do {
- // No side effects in this initial code
- a.construct(*i);
+ a.construct_node();
+ a.construct_value2(*i);
                 emplace_impl_with_node(a);
             } while(++i != j);
         }
- };
 
- template <class H, class P, class A>
- struct set : public types<
- typename allocator_traits<A>::value_type,
- typename allocator_traits<A>::value_type,
- H, P, A,
- set_extractor<typename allocator_traits<A>::value_type>,
- true>
- {
- typedef ::boost::unordered::detail::unique_table<set<H, P, A> > impl;
- typedef ::boost::unordered::detail::table<set<H, P, A> > table_base;
- };
+ ////////////////////////////////////////////////////////////////////////
+ // Erase
+ //
+ // no throw
 
- template <class K, class H, class P, class A>
- struct map : public types<
- K, typename allocator_traits<A>::value_type,
- H, P, A,
- map_extractor<K, typename allocator_traits<A>::value_type>,
- true>
- {
- typedef ::boost::unordered::detail::unique_table<map<K, H, P, A> > impl;
- typedef ::boost::unordered::detail::table<map<K, H, P, A> > table_base;
+ std::size_t erase_key(key_type const& k)
+ {
+ if(!this->size_) return 0;
+
+ std::size_t hash = this->hash_function()(k);
+ std::size_t bucket_index = hash % this->bucket_count_;
+ bucket_pointer bucket = this->get_bucket(bucket_index);
+
+ previous_pointer prev = bucket->next_;
+ if (!prev) return 0;
+
+ for (;;)
+ {
+ if (!prev->next_) return 0;
+ std::size_t node_hash =
+ static_cast<node_pointer>(prev->next_)->hash_;
+ if (node_hash % this->bucket_count_ != bucket_index)
+ return 0;
+ if (node_hash == hash &&
+ this->key_eq()(k, this->get_key(
+ static_cast<node_pointer>(prev->next_)->value())))
+ break;
+ prev = static_cast<previous_pointer>(prev->next_);
+ }
+
+ node_pointer pos = static_cast<node_pointer>(prev->next_);
+ node_pointer end = static_cast<node_pointer>(pos->next_);
+ prev->next_ = pos->next_;
+ this->fix_buckets(bucket, prev, end);
+ return this->delete_nodes(pos, end);
+ }
+
+ node_pointer erase(node_pointer r)
+ {
+ BOOST_ASSERT(r);
+ node_pointer next = static_cast<node_pointer>(r->next_);
+
+ bucket_pointer bucket = this->get_bucket(
+ r->hash_ % this->bucket_count_);
+ previous_pointer prev = unlink_node(*bucket, r);
+
+ this->fix_buckets(bucket, prev, next);
+
+ this->delete_node(r);
+
+ return next;
+ }
+
+ node_pointer erase_range(node_pointer r1, node_pointer r2)
+ {
+ if (r1 == r2) return r2;
+
+ std::size_t bucket_index = r1->hash_ % this->bucket_count_;
+ previous_pointer prev = unlink_nodes(
+ *this->get_bucket(bucket_index), r1, r2);
+ this->fix_buckets_range(bucket_index, prev, r1, r2);
+ this->delete_nodes(r1, r2);
+
+ return r2;
+ }
+
+ static previous_pointer unlink_node(bucket& b, node_pointer n)
+ {
+ return unlink_nodes(b, n, static_cast<node_pointer>(n->next_));
+ }
+
+ static previous_pointer unlink_nodes(bucket& b,
+ node_pointer begin, node_pointer end)
+ {
+ previous_pointer prev = b.next_;
+ link_pointer begin_void = static_cast<link_pointer>(begin);
+ while(prev->next_ != begin_void)
+ prev = static_cast<previous_pointer>(prev->next_);
+ prev->next_ = static_cast<link_pointer>(end);
+ return prev;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // copy_buckets_to
+ //
+ // Basic exception safety. If an exception is thrown this will
+ // leave dst partially filled and the buckets unset.
+
+ static void copy_buckets_to(buckets const& src, buckets& dst)
+ {
+ BOOST_ASSERT(!dst.buckets_);
+
+ dst.create_buckets();
+
+ node_constructor a(dst.node_alloc());
+
+ node_pointer n = src.get_start();
+ previous_pointer prev = dst.get_previous_start();
+
+ while(n) {
+ a.construct_node();
+ a.construct_value2(n->value());
+
+ node_pointer node = a.release();
+ node->hash_ = n->hash_;
+ prev->next_ = static_cast<link_pointer>(node);
+ ++dst.size_;
+ n = static_cast<node_pointer>(n->next_);
+
+ prev = place_in_bucket(dst, prev);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // move_buckets_to
+ //
+ // Basic exception safety. The source nodes are left in an unusable
+ // state if an exception throws.
+
+ static void move_buckets_to(buckets& src, buckets& dst)
+ {
+ BOOST_ASSERT(!dst.buckets_);
+
+ dst.create_buckets();
+
+ node_constructor a(dst.node_alloc());
+
+ node_pointer n = src.get_start();
+ previous_pointer prev = dst.get_previous_start();
+
+ while(n) {
+ a.construct_node();
+ a.construct_value2(boost::move(n->value()));
+
+ node_pointer node = a.release();
+ node->hash_ = n->hash_;
+ prev->next_ = static_cast<link_pointer>(node);
+ ++dst.size_;
+ n = static_cast<node_pointer>(n->next_);
+
+ prev = place_in_bucket(dst, prev);
+ }
+ }
+
+ // strong otherwise exception safety
+ void rehash_impl(std::size_t num_buckets)
+ {
+ BOOST_ASSERT(this->size_);
+
+ buckets dst(this->node_alloc(), num_buckets);
+ dst.create_buckets();
+
+ previous_pointer src_start = this->get_previous_start();
+ previous_pointer dst_start = dst.get_previous_start();
+
+ dst_start->next_ = src_start->next_;
+ src_start->next_ = link_pointer();
+ dst.size_ = this->size_;
+ this->size_ = 0;
+
+ previous_pointer prev = dst.get_previous_start();
+ while (prev->next_)
+ prev = place_in_bucket(dst, prev);
+
+ // Swap the new nodes back into the container and setup the
+ // variables.
+ dst.swap(*this); // no throw
+ }
+
+ // Iterate through the nodes placing them in the correct buckets.
+ // pre: prev->next_ is not null.
+ static previous_pointer place_in_bucket(buckets& dst,
+ previous_pointer prev)
+ {
+ node_pointer n = static_cast<node_pointer>(prev->next_);
+ bucket_pointer b = dst.get_bucket(n->hash_ % dst.bucket_count_);
+
+ if (!b->next_) {
+ b->next_ = prev;
+ return static_cast<previous_pointer>(n);
+ }
+ else {
+ prev->next_ = n->next_;
+ n->next_ = b->next_->next_;
+ b->next_->next_ = static_cast<link_pointer>(n);
+ return prev;
+ }
+ }
     };
 }}}
 

Modified: branches/release/boost/unordered/detail/util.hpp
==============================================================================
--- branches/release/boost/unordered/detail/util.hpp (original)
+++ branches/release/boost/unordered/detail/util.hpp 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -7,156 +7,50 @@
 #ifndef BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
 #define BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
 
-#include <algorithm>
-#include <cstddef>
-#include <stdexcept>
-#include <utility>
-#include <boost/limits.hpp>
-#include <boost/config.hpp>
-#include <boost/config/no_tr1/cmath.hpp>
-#include <boost/detail/workaround.hpp>
-#include <boost/detail/select_type.hpp>
-#include <boost/assert.hpp>
-#include <boost/iterator.hpp>
-#include <boost/iterator/iterator_categories.hpp>
-#include <boost/type_traits/aligned_storage.hpp>
-#include <boost/type_traits/alignment_of.hpp>
-#include <boost/type_traits/remove_const.hpp>
-#include <boost/type_traits/is_empty.hpp>
-#if defined(BOOST_NO_RVALUE_REFERENCES)
-#include <boost/type_traits/is_class.hpp>
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
 #endif
-#include <boost/throw_exception.hpp>
+
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_empty.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/detail/select_type.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/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:
-//
-// H = Hash Function
-// P = Predicate
-// A = Value Allocator
-// G = Bucket group policy, 'grouped' or 'ungrouped'
-// E = Key Extractor
-
-#if !defined(BOOST_NO_RVALUE_REFERENCES) && \
- !defined(BOOST_NO_VARIADIC_TEMPLATES)
-# if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
-# elif defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)
-# elif defined(_LIBCPP_VERSION)
-# define BOOST_UNORDERED_STD_FORWARD_MOVE
-# elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
-# if defined(__GLIBCXX__) && __GLIBCXX__ >= 20090804
-# define BOOST_UNORDERED_STD_FORWARD_MOVE
-# endif
-# elif defined(__STL_CONFIG_H)
-# elif defined(__MSL_CPP__)
-# elif defined(__IBMCPP__)
-# elif defined(MSIPL_COMPILE_H)
-# elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)
- // Visual C++. A version check would be a good idea.
-# define BOOST_UNORDERED_STD_FORWARD_MOVE
-# endif
-#endif
-
-#if !defined(BOOST_UNORDERED_EMPLACE_LIMIT)
-#define BOOST_UNORDERED_EMPLACE_LIMIT 10
-#endif
-
-#if defined(__SUNPRO_CC)
-#define BOOST_UNORDERED_USE_RV_REF 0
-#else
-#define BOOST_UNORDERED_USE_RV_REF 1
-#endif
-
-#if !defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
-
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/repetition/enum_binary_params.hpp>
-#include <boost/preprocessor/repetition/repeat_from_to.hpp>
-
-#define BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
- BOOST_PP_ENUM_PARAMS_Z(z, num_params, class Arg)
-
-#define BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
- BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_FUNCTION_PARAMS2, _)
-#define BOOST_UNORDERED_FUNCTION_PARAMS2(z, i, _) \
- BOOST_FWD_REF(Arg##i) arg##i
-
-#define BOOST_UNORDERED_CALL_PARAMS(z, num_params) \
- BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_PARAMS2, _)
-#define BOOST_UNORDERED_CALL_PARAMS2(z, i, _) \
- boost::forward<Arg##i>(arg##i)
-
-#endif
+#include <boost/swap.hpp>
 
 namespace boost { namespace unordered { namespace detail {
 
     static const float minimum_max_load_factor = 1e-3f;
     static const std::size_t default_bucket_count = 11;
     struct move_tag {};
-
     struct empty_emplace {};
 
- template <class T> class unique_table;
- template <class T> class equivalent_table;
- template <class Alloc, bool Unique> class node_constructor;
- template <class ValueType>
- struct set_extractor;
- template <class Key, class ValueType>
- struct map_extractor;
- struct no_key;
-
-#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;
- };
+ ////////////////////////////////////////////////////////////////////////////
+ // iterator SFINAE
 
- 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
+ template <typename I>
+ struct is_forward :
+ boost::is_convertible<
+ typename boost::iterator_traversal<I>::type,
+ boost::forward_traversal_tag>
     {};
 
-#define BOOST_UNORDERED_RV_REF(T) \
- typename ::boost::unordered::detail::rv_ref<T>::type
-
-#endif
-
- ////////////////////////////////////////////////////////////////////////////
- // convert double to std::size_t
+ template <typename I, typename ReturnType>
+ struct enable_if_forward :
+ boost::enable_if_c<
+ boost::unordered::detail::is_forward<I>::value,
+ ReturnType>
+ {};
 
- inline std::size_t double_to_size_t(double f)
- {
- return f >= static_cast<double>(
- (std::numeric_limits<std::size_t>::max)()) ?
- (std::numeric_limits<std::size_t>::max)() :
- static_cast<std::size_t>(f);
- }
+ template <typename I, typename ReturnType>
+ struct disable_if_forward :
+ boost::disable_if_c<
+ boost::unordered::detail::is_forward<I>::value,
+ ReturnType>
+ {};
 
     ////////////////////////////////////////////////////////////////////////////
     // primes
@@ -225,45 +119,49 @@
     // insert_size/initial_size
 
 #if !defined(BOOST_NO_STD_DISTANCE)
+
     using ::std::distance;
+
 #else
+
     template <class ForwardIterator>
     inline std::size_t distance(ForwardIterator i, ForwardIterator j) {
         std::size_t x;
         std::distance(i, j, x);
         return x;
     }
+
 #endif
 
     template <class I>
- inline std::size_t insert_size(I i, I j, ::boost::forward_traversal_tag)
+ inline typename
+ boost::unordered::detail::enable_if_forward<I, std::size_t>::type
+ insert_size(I i, I j)
     {
         return std::distance(i, j);
     }
 
     template <class I>
- inline std::size_t insert_size(I, I, ::boost::incrementable_traversal_tag)
+ inline typename
+ boost::unordered::detail::disable_if_forward<I, std::size_t>::type
+ insert_size(I, I)
     {
         return 1;
     }
 
     template <class I>
- inline std::size_t insert_size(I i, I j)
- {
- return insert_size(i, j,
- typename ::boost::iterator_traversal<I>::type());
- }
-
- template <class I>
     inline std::size_t initial_size(I i, I j,
- std::size_t num_buckets = ::boost::unordered::detail::default_bucket_count)
+ std::size_t num_buckets =
+ boost::unordered::detail::default_bucket_count)
     {
- return (std::max)(static_cast<std::size_t>(insert_size(i, j)) + 1,
+ // TODO: Why +1?
+ return (std::max)(
+ boost::unordered::detail::insert_size(i, j) + 1,
             num_buckets);
     }
 
     ////////////////////////////////////////////////////////////////////////////
- // compressed_pair
+ // compressed
 
     template <typename T, int Index>
     struct compressed_base : private T
@@ -292,15 +190,15 @@
       : boost::detail::if_true<
             boost::is_empty<T>::value
>:: BOOST_NESTED_TEMPLATE then<
- compressed_base<T, Index>,
- uncompressed_base<T, Index>
+ boost::unordered::detail::compressed_base<T, Index>,
+ boost::unordered::detail::uncompressed_base<T, Index>
>
     {};
     
     template <typename T1, typename T2>
- struct compressed_pair
- : private generate_base<T1, 1>::type,
- private generate_base<T2, 2>::type
+ struct compressed
+ : private boost::unordered::detail::generate_base<T1, 1>::type,
+ private boost::unordered::detail::generate_base<T2, 2>::type
     {
         typedef typename generate_base<T1, 1>::type base1;
         typedef typename generate_base<T2, 2>::type base2;
@@ -325,28 +223,28 @@
         }
 
         template <typename First, typename Second>
- compressed_pair(First const& x1, Second const& x2)
+ compressed(First const& x1, Second const& x2)
             : base1(x1), base2(x2) {}
 
- compressed_pair(compressed_pair const& x)
+ compressed(compressed const& x)
             : base1(x.first()), base2(x.second()) {}
 
- compressed_pair(compressed_pair& x, move_tag m)
+ compressed(compressed& x, move_tag m)
             : base1(x.first(), m), base2(x.second(), m) {}
 
- void assign(compressed_pair const& x)
+ void assign(compressed const& x)
         {
             first() = x.first();
             second() = x.second();
         }
 
- void move_assign(compressed_pair& x)
+ void move_assign(compressed& x)
         {
             first() = boost::move(x.first());
             second() = boost::move(x.second());
         }
         
- void swap(compressed_pair& x)
+ void swap(compressed& x)
         {
             boost::swap(first(), x.first());
             boost::swap(second(), x.second());
@@ -355,7 +253,7 @@
     private:
         // Prevent assignment just to make use of assign or
         // move_assign explicit.
- compressed_pair& operator=(compressed_pair const&);
+ compressed& operator=(compressed const&);
     };
 }}}
 

Modified: branches/release/boost/unordered/unordered_map.hpp
==============================================================================
--- branches/release/boost/unordered/unordered_map.hpp (original)
+++ branches/release/boost/unordered/unordered_map.hpp 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -14,10 +14,12 @@
 #endif
 
 #include <boost/unordered/unordered_map_fwd.hpp>
-#include <boost/functional/hash.hpp>
 #include <boost/unordered/detail/allocator_helpers.hpp>
 #include <boost/unordered/detail/equivalent.hpp>
 #include <boost/unordered/detail/unique.hpp>
+#include <boost/unordered/detail/util.hpp>
+#include <boost/functional/hash.hpp>
+#include <boost/move/move.hpp>
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
 #include <initializer_list>
@@ -40,7 +42,9 @@
     class unordered_map
     {
         BOOST_COPYABLE_AND_MOVABLE(unordered_map)
+
     public:
+
         typedef K key_type;
         typedef std::pair<const K, T> value_type;
         typedef T mapped_type;
@@ -48,20 +52,18 @@
         typedef P key_equal;
         typedef A allocator_type;
 
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
     private:
-#endif
 
- typedef 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 typename types::impl table;
+ typedef boost::unordered::detail::allocator_traits<value_allocator>
+ allocator_traits;
 
- typedef typename types::node_ptr node_ptr;
+ typedef boost::unordered::detail::map<value_allocator, K, H, P>
+ types;
+ typedef typename types::table table;
 
     public:
 
@@ -74,44 +76,36 @@
         typedef std::size_t size_type;
         typedef std::ptrdiff_t difference_type;
 
- typedef ::boost::unordered::iterator_detail::cl_iterator<
- value_allocator, true> const_local_iterator;
- typedef ::boost::unordered::iterator_detail::l_iterator<
- value_allocator, true> local_iterator;
- typedef ::boost::unordered::iterator_detail::c_iterator<
- value_allocator, true> const_iterator;
- typedef ::boost::unordered::iterator_detail::iterator<
- value_allocator, true> iterator;
+ typedef typename table::cl_iterator const_local_iterator;
+ typedef typename table::l_iterator local_iterator;
+ typedef typename table::c_iterator const_iterator;
+ typedef typename table::iterator iterator;
 
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
     private:
-#endif
 
         table table_;
         
     public:
 
- // construct/destroy/copy
+ // constructors
 
         explicit unordered_map(
- size_type = ::boost::unordered::detail::default_bucket_count,
+ size_type = boost::unordered::detail::default_bucket_count,
                 const hasher& = hasher(),
                 const key_equal& = key_equal(),
                 const allocator_type& = allocator_type());
 
         explicit unordered_map(allocator_type const&);
 
- unordered_map(unordered_map const&, allocator_type const&);
-
         template <class InputIt>
- unordered_map(InputIt f, InputIt l);
+ unordered_map(InputIt, InputIt);
 
         template <class InputIt>
         unordered_map(
                 InputIt, InputIt,
                 size_type,
                 const hasher& = hasher(),
- const key_equal& = key_equal());
+ const key_equal& = key_equal());
 
         template <class InputIt>
         unordered_map(
@@ -120,26 +114,15 @@
                 const hasher&,
                 const key_equal&,
                 const allocator_type&);
-
- ~unordered_map();
 
- unordered_map& operator=(
- BOOST_COPY_ASSIGN_REF(unordered_map) x)
- {
- table_.assign(x.table_);
- return *this;
- }
+ // copy/move constructors
 
         unordered_map(unordered_map const&);
 
- unordered_map& operator=(BOOST_RV_REF(unordered_map) x)
- {
- table_.move_assign(x.table_);
- return *this;
- }
+ unordered_map(unordered_map const&, allocator_type const&);
 
         unordered_map(BOOST_RV_REF(unordered_map) other)
- : table_(other.table_, ::boost::unordered::detail::move_tag())
+ : table_(other.table_, boost::unordered::detail::move_tag())
         {
         }
 
@@ -150,11 +133,31 @@
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
         unordered_map(
                 std::initializer_list<value_type>,
- size_type = ::boost::unordered::detail::default_bucket_count,
+ size_type = boost::unordered::detail::default_bucket_count,
                 const hasher& = hasher(),
                 const key_equal&l = key_equal(),
                 const allocator_type& = allocator_type());
+#endif
+
+ // Destructor
+
+ ~unordered_map();
+
+ // Assign
+
+ unordered_map& operator=(BOOST_COPY_ASSIGN_REF(unordered_map) x)
+ {
+ table_.assign(x.table_);
+ return *this;
+ }
 
+ unordered_map& operator=(BOOST_RV_REF(unordered_map) x)
+ {
+ table_.move_assign(x.table_);
+ return *this;
+ }
+
+#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
         unordered_map& operator=(std::initializer_list<value_type>);
 #endif
 
@@ -209,54 +212,99 @@
             return const_iterator();
         }
 
- // modifiers
+ // emplace
 
 #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
         template <class... Args>
- std::pair<iterator, bool> emplace(Args&&...);
+ std::pair<iterator, bool> emplace(Args&&... args)
+ {
+ return table_.emplace(std::forward<Args>(args)...);
+ }
+
         template <class... Args>
- iterator emplace_hint(const_iterator, Args&&...);
+ iterator emplace_hint(const_iterator, Args&&... args)
+ {
+ return iterator(table_.emplace(std::forward<Args>(args)...).first);
+ }
 #else
 
+#define BOOST_UNORDERED_EMPLACE(z, n, _) \
+ template < \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
+ > \
+ std::pair<iterator, bool> emplace( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
+ ) \
+ { \
+ return table_.emplace( \
+ boost::unordered::detail::create_emplace_args( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
+ a) \
+ )); \
+ } \
+ \
+ template < \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
+ > \
+ iterator emplace_hint( \
+ const_iterator, \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
+ ) \
+ { \
+ return iterator(table_.emplace( \
+ boost::unordered::detail::create_emplace_args( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
+ a) \
+ )).first); \
+ }
+
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
+ BOOST_UNORDERED_EMPLACE, _)
+
+#undef BOOST_UNORDERED_EMPLACE
+
 #if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
+
         std::pair<iterator, bool> emplace(
                 boost::unordered::detail::empty_emplace
                     = boost::unordered::detail::empty_emplace(),
- value_type v = value_type()
- );
- iterator emplace_hint(const_iterator,
+ value_type v = value_type())
+ {
+ return this->emplace(boost::move(v));
+ }
+
+ iterator emplace_hint(const_iterator hint,
                 boost::unordered::detail::empty_emplace
                     = boost::unordered::detail::empty_emplace(),
                 value_type v = value_type()
- );
+ )
+ {
+ return this->emplace_hint(hint, boost::move(v));
+ }
+
 #endif
 
-#define BOOST_UNORDERED_EMPLACE(z, n, _) \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- std::pair<iterator, bool> emplace( \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ); \
- \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- iterator emplace_hint(const_iterator, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- );
+#endif
 
- BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_EMPLACE, _)
+ std::pair<iterator, bool> insert(value_type const& x)
+ {
+ return this->emplace(x);
+ }
 
-#undef BOOST_UNORDERED_EMPLACE
+ std::pair<iterator, bool> insert(BOOST_RV_REF(value_type) x)
+ {
+ return this->emplace(boost::move(x));
+ }
 
-#endif
+ iterator insert(const_iterator hint, value_type const& x)
+ {
+ return this->emplace_hint(hint, x);
+ }
 
- std::pair<iterator, bool> insert(value_type const&);
- 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));
+ iterator insert(const_iterator hint, BOOST_RV_REF(value_type) x)
+ {
+ return this->emplace_hint(hint, boost::move(x));
+ }
 
         template <class InputIt> void insert(InputIt, InputIt);
 
@@ -320,7 +368,7 @@
             return table_.max_bucket_count();
         }
 
- size_type bucket_size(size_type n) const;
+ size_type bucket_size(size_type) const;
 
         size_type bucket(const key_type& k) const
         {
@@ -329,14 +377,16 @@
 
         local_iterator begin(size_type n)
         {
- return local_iterator(
- table_.bucket_begin(n), n, table_.bucket_count_);
+ return table_.size_ ? local_iterator(
+ table_.get_start(n), n, table_.bucket_count_) :
+ local_iterator();
         }
 
         const_local_iterator begin(size_type n) const
         {
- return const_local_iterator(
- table_.bucket_begin(n), n, table_.bucket_count_);
+ return table_.size_ ? const_local_iterator(
+ table_.get_start(n), n, table_.bucket_count_) :
+ const_local_iterator();
         }
 
         local_iterator end(size_type)
@@ -351,8 +401,9 @@
 
         const_local_iterator cbegin(size_type n) const
         {
- return const_local_iterator(
- table_.bucket_begin(n), n, table_.bucket_count_);
+ return table_.size_ ? const_local_iterator(
+ table_.get_start(n), n, table_.bucket_count_) :
+ const_local_iterator();
         }
 
         const_local_iterator cend(size_type) const
@@ -369,7 +420,7 @@
 
         float load_factor() const;
         void max_load_factor(float);
- void rehash(size_type n);
+ void rehash(size_type);
 
 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
         friend bool operator==<K,T,H,P,A>(
@@ -383,6 +434,7 @@
     class unordered_multimap
     {
         BOOST_COPYABLE_AND_MOVABLE(unordered_multimap)
+
     public:
 
         typedef K key_type;
@@ -392,21 +444,18 @@
         typedef P key_equal;
         typedef A allocator_type;
 
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
     private:
-#endif
 
- typedef 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::multimap<K, H, P,
- value_allocator> types;
- typedef typename types::impl table;
+ typedef boost::unordered::detail::allocator_traits<value_allocator>
+ allocator_traits;
 
- typedef typename types::node_ptr node_ptr;
+ typedef boost::unordered::detail::multimap<value_allocator, K, H, P>
+ types;
+ typedef typename types::table table;
 
     public:
 
@@ -419,35 +468,27 @@
         typedef std::size_t size_type;
         typedef std::ptrdiff_t difference_type;
 
- typedef ::boost::unordered::iterator_detail::cl_iterator<
- value_allocator, false> const_local_iterator;
- typedef ::boost::unordered::iterator_detail::l_iterator<
- value_allocator, false> local_iterator;
- typedef ::boost::unordered::iterator_detail::c_iterator<
- value_allocator, false> const_iterator;
- typedef ::boost::unordered::iterator_detail::iterator<
- value_allocator, false> iterator;
+ typedef typename table::cl_iterator const_local_iterator;
+ typedef typename table::l_iterator local_iterator;
+ typedef typename table::c_iterator const_iterator;
+ typedef typename table::iterator iterator;
 
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
     private:
-#endif
 
         table table_;
         
     public:
 
- // construct/destroy/copy
+ // constructors
 
         explicit unordered_multimap(
- size_type = ::boost::unordered::detail::default_bucket_count,
+ size_type = boost::unordered::detail::default_bucket_count,
                 const hasher& = hasher(),
                 const key_equal& = key_equal(),
                 const allocator_type& = allocator_type());
 
         explicit unordered_multimap(allocator_type const&);
 
- unordered_multimap(unordered_multimap const&, allocator_type const&);
-
         template <class InputIt>
         unordered_multimap(InputIt, InputIt);
 
@@ -466,25 +507,14 @@
                 const key_equal&,
                 const allocator_type&);
 
- ~unordered_multimap();
-
- unordered_multimap& operator=(
- BOOST_COPY_ASSIGN_REF(unordered_multimap) x)
- {
- table_.assign(x.table_);
- return *this;
- }
+ // copy/move constructors
 
         unordered_multimap(unordered_multimap const&);
 
- unordered_multimap& operator=(BOOST_RV_REF(unordered_multimap) x)
- {
- table_.move_assign(x.table_);
- return *this;
- }
+ unordered_multimap(unordered_multimap const&, allocator_type const&);
 
         unordered_multimap(BOOST_RV_REF(unordered_multimap) other)
- : table_(other.table_, ::boost::unordered::detail::move_tag())
+ : table_(other.table_, boost::unordered::detail::move_tag())
         {
         }
 
@@ -495,11 +525,32 @@
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
         unordered_multimap(
                 std::initializer_list<value_type>,
- size_type = ::boost::unordered::detail::default_bucket_count,
+ size_type = boost::unordered::detail::default_bucket_count,
                 const hasher& = hasher(),
                 const key_equal&l = key_equal(),
                 const allocator_type& = allocator_type());
+#endif
+
+ // Destructor
+
+ ~unordered_multimap();
+
+ // Assign
 
+ unordered_multimap& operator=(
+ BOOST_COPY_ASSIGN_REF(unordered_multimap) x)
+ {
+ table_.assign(x.table_);
+ return *this;
+ }
+
+ unordered_multimap& operator=(BOOST_RV_REF(unordered_multimap) x)
+ {
+ table_.move_assign(x.table_);
+ return *this;
+ }
+
+#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
         unordered_multimap& operator=(std::initializer_list<value_type>);
 #endif
 
@@ -554,54 +605,99 @@
             return const_iterator();
         }
 
- // modifiers
+ // emplace
 
 #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
         template <class... Args>
- iterator emplace(Args&&...);
+ iterator emplace(Args&&... args)
+ {
+ return iterator(table_.emplace(std::forward<Args>(args)...));
+ }
+
         template <class... Args>
- iterator emplace_hint(const_iterator, Args&&...);
+ iterator emplace_hint(const_iterator, Args&&... args)
+ {
+ return iterator(table_.emplace(std::forward<Args>(args)...));
+ }
 #else
 
+#define BOOST_UNORDERED_EMPLACE(z, n, _) \
+ template < \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
+ > \
+ iterator emplace( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
+ ) \
+ { \
+ return iterator(table_.emplace( \
+ boost::unordered::detail::create_emplace_args( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
+ a) \
+ ))); \
+ } \
+ \
+ template < \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
+ > \
+ iterator emplace_hint( \
+ const_iterator, \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
+ ) \
+ { \
+ return iterator(table_.emplace( \
+ boost::unordered::detail::create_emplace_args( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
+ a) \
+ ))); \
+ }
+
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
+ BOOST_UNORDERED_EMPLACE, _)
+
+#undef BOOST_UNORDERED_EMPLACE
+
 #if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
+
         iterator emplace(
                 boost::unordered::detail::empty_emplace
                     = boost::unordered::detail::empty_emplace(),
- value_type v = value_type()
- );
- iterator emplace_hint(const_iterator,
+ value_type v = value_type())
+ {
+ return iterator(this->emplace(boost::move(v)));
+ }
+
+ iterator emplace_hint(const_iterator hint,
                 boost::unordered::detail::empty_emplace
                     = boost::unordered::detail::empty_emplace(),
                 value_type v = value_type()
- );
+ )
+ {
+ return iterator(this->emplace_hint(hint, boost::move(v)));
+ }
+
 #endif
 
-#define BOOST_UNORDERED_EMPLACE(z, n, _) \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- iterator emplace( \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ); \
- \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- iterator emplace_hint(const_iterator, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- );
+#endif
 
- BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_EMPLACE, _)
+ iterator insert(value_type const& x)
+ {
+ return this->emplace(x);
+ }
 
-#undef BOOST_UNORDERED_EMPLACE
+ iterator insert(BOOST_RV_REF(value_type) x)
+ {
+ return this->emplace(boost::move(x));
+ }
 
-#endif
+ iterator insert(const_iterator hint, value_type const& x)
+ {
+ return this->emplace_hint(hint, x);
+ }
 
- iterator insert(value_type const&);
- iterator insert(BOOST_RV_REF(value_type));
- iterator insert(const_iterator, value_type const&);
- iterator insert(const_iterator, BOOST_RV_REF(value_type));
+ iterator insert(const_iterator hint, BOOST_RV_REF(value_type) x)
+ {
+ return this->emplace_hint(hint, boost::move(x));
+ }
 
         template <class InputIt> void insert(InputIt, InputIt);
 
@@ -612,8 +708,8 @@
         iterator erase(const_iterator);
         size_type erase(const key_type&);
         iterator erase(const_iterator, const_iterator);
- void quick_erase(const_iterator position) { erase(position); }
- void erase_return_void(const_iterator position) { erase(position); }
+ void quick_erase(const_iterator it) { erase(it); }
+ void erase_return_void(const_iterator it) { erase(it); }
 
         void clear();
         void swap(unordered_multimap&);
@@ -670,14 +766,16 @@
 
         local_iterator begin(size_type n)
         {
- return local_iterator(
- table_.bucket_begin(n), n, table_.bucket_count_);
+ return table_.size_ ? local_iterator(
+ table_.get_start(n), n, table_.bucket_count_) :
+ local_iterator();
         }
 
         const_local_iterator begin(size_type n) const
         {
- return const_local_iterator(
- table_.bucket_begin(n), n, table_.bucket_count_);
+ return table_.size_ ? const_local_iterator(
+ table_.get_start(n), n, table_.bucket_count_) :
+ const_local_iterator();
         }
 
         local_iterator end(size_type)
@@ -692,8 +790,9 @@
 
         const_local_iterator cbegin(size_type n) const
         {
- return const_local_iterator(
- table_.bucket_begin(n), n, table_.bucket_count_);
+ return table_.size_ ? const_local_iterator(
+ table_.get_start(n), n, table_.bucket_count_) :
+ const_local_iterator();
         }
 
         const_local_iterator cend(size_type) const
@@ -714,9 +813,9 @@
 
 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
         friend bool operator==<K,T,H,P,A>(
- unordered_multimap const&, unordered_multimap const&);
+ unordered_multimap const&, unordered_multimap const&);
         friend bool operator!=<K,T,H,P,A>(
- unordered_multimap const&, unordered_multimap const&);
+ unordered_multimap const&, unordered_multimap const&);
 #endif
     }; // class template unordered_multimap
 
@@ -732,7 +831,7 @@
 
     template <class K, class T, class H, class P, class A>
     unordered_map<K,T,H,P,A>::unordered_map(allocator_type const& a)
- : table_(::boost::unordered::detail::default_bucket_count,
+ : table_(boost::unordered::detail::default_bucket_count,
             hasher(), key_equal(), a)
     {
     }
@@ -747,7 +846,7 @@
     template <class K, class T, class H, class P, class A>
     template <class InputIt>
     unordered_map<K,T,H,P,A>::unordered_map(InputIt f, InputIt l)
- : table_(::boost::unordered::detail::initial_size(f, l),
+ : table_(boost::unordered::detail::initial_size(f, l),
         hasher(), key_equal(), allocator_type())
     {
         table_.insert_range(f, l);
@@ -760,7 +859,7 @@
             size_type n,
             const hasher &hf,
             const key_equal &eql)
- : table_(::boost::unordered::detail::initial_size(f, l, n),
+ : table_(boost::unordered::detail::initial_size(f, l, n),
             hf, eql, allocator_type())
     {
         table_.insert_range(f, l);
@@ -774,7 +873,7 @@
             const hasher &hf,
             const key_equal &eql,
             const allocator_type &a)
- : table_(::boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
+ : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
     {
         table_.insert_range(f, l);
     }
@@ -783,7 +882,8 @@
     unordered_map<K,T,H,P,A>::~unordered_map() {}
 
     template <class K, class T, class H, class P, class A>
- unordered_map<K,T,H,P,A>::unordered_map(unordered_map const& other)
+ unordered_map<K,T,H,P,A>::unordered_map(
+ unordered_map const& other)
       : table_(other.table_)
     {
     }
@@ -793,7 +893,7 @@
     template <class K, class T, class H, class P, class A>
     unordered_map<K,T,H,P,A>::unordered_map(
             unordered_map&& other, allocator_type const& a)
- : table_(other.table_, a, ::boost::unordered::detail::move_tag())
+ : table_(other.table_, a, boost::unordered::detail::move_tag())
     {
     }
 
@@ -806,7 +906,7 @@
             std::initializer_list<value_type> list, size_type n,
             const hasher &hf, const key_equal &eql, const allocator_type &a)
       : table_(
- ::boost::unordered::detail::initial_size(
+ boost::unordered::detail::initial_size(
                 list.begin(), list.end(), n),
             hf, eql, a)
     {
@@ -834,109 +934,6 @@
 
     // modifiers
 
-#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
- template <class K, class T, class H, class P, class A>
- template <class... Args>
- std::pair<typename unordered_map<K,T,H,P,A>::iterator, bool>
- unordered_map<K,T,H,P,A>::emplace(Args&&... args)
- {
- return table_.emplace(std::forward<Args>(args)...);
- }
-
- template <class K, class T, class H, class P, class A>
- template <class... Args>
- typename unordered_map<K,T,H,P,A>::iterator
- unordered_map<K,T,H,P,A>::emplace_hint(const_iterator, Args&&... args)
- {
- return iterator(table_.emplace(std::forward<Args>(args)...).first);
- }
-#else
-
-#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
- template <class K, class T, class H, class P, class A>
- std::pair<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 table_.emplace(boost::move(v));
- }
-
- template <class K, class T, class H, class P, class A>
- typename unordered_map<K,T,H,P,A>::iterator
- unordered_map<K,T,H,P,A>::emplace_hint(const_iterator,
- boost::unordered::detail::empty_emplace,
- value_type v
- )
- {
- return iterator(table_.emplace(boost::move(v)).first);
- }
-#endif
-
-#define BOOST_UNORDERED_EMPLACE(z, n, _) \
- template <class K, class T, class H, class P, class A> \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- std::pair<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 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) \
- > \
- typename unordered_map<K,T,H,P,A>::iterator \
- unordered_map<K,T,H,P,A>::emplace_hint( \
- const_iterator, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ) \
- { \
- return iterator(table_.emplace( \
- BOOST_UNORDERED_CALL_PARAMS(z, n)).first); \
- }
-
- BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_EMPLACE, _)
-
-#undef BOOST_UNORDERED_EMPLACE
-
-#endif
-
- template <class K, class T, class H, class P, class A>
- std::pair<typename unordered_map<K,T,H,P,A>::iterator, bool>
- unordered_map<K,T,H,P,A>::insert(value_type const& obj)
- {
- return table_.emplace(obj);
- }
-
- template <class K, class T, class H, class P, class A>
- 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);
- }
-
- template <class K, class T, class H, class P, class A>
- 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 table_.emplace(boost::move(obj));
- }
-
- template <class K, class T, class H, class P, class A>
- 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);
- }
-
     template <class K, class T, class H, class P, class A>
     template <class InputIt>
     void unordered_map<K,T,H,P,A>::insert(InputIt first, InputIt last)
@@ -1161,7 +1158,7 @@
 
     template <class K, class T, class H, class P, class A>
     unordered_multimap<K,T,H,P,A>::unordered_multimap(allocator_type const& a)
- : table_(::boost::unordered::detail::default_bucket_count,
+ : table_(boost::unordered::detail::default_bucket_count,
             hasher(), key_equal(), a)
     {
     }
@@ -1176,7 +1173,7 @@
     template <class K, class T, class H, class P, class A>
     template <class InputIt>
     unordered_multimap<K,T,H,P,A>::unordered_multimap(InputIt f, InputIt l)
- : table_(::boost::unordered::detail::initial_size(f, l),
+ : table_(boost::unordered::detail::initial_size(f, l),
         hasher(), key_equal(), allocator_type())
     {
         table_.insert_range(f, l);
@@ -1189,7 +1186,7 @@
             size_type n,
             const hasher &hf,
             const key_equal &eql)
- : table_(::boost::unordered::detail::initial_size(f, l, n),
+ : table_(boost::unordered::detail::initial_size(f, l, n),
             hf, eql, allocator_type())
     {
         table_.insert_range(f, l);
@@ -1203,7 +1200,7 @@
             const hasher &hf,
             const key_equal &eql,
             const allocator_type &a)
- : table_(::boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
+ : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
     {
         table_.insert_range(f, l);
     }
@@ -1223,19 +1220,20 @@
     template <class K, class T, class H, class P, class A>
     unordered_multimap<K,T,H,P,A>::unordered_multimap(
             unordered_multimap&& other, allocator_type const& a)
- : table_(other.table_, a, ::boost::unordered::detail::move_tag())
+ : table_(other.table_, a, boost::unordered::detail::move_tag())
     {
     }
 
 #endif
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
+
     template <class K, class T, class H, class P, class A>
     unordered_multimap<K,T,H,P,A>::unordered_multimap(
             std::initializer_list<value_type> list, size_type n,
             const hasher &hf, const key_equal &eql, const allocator_type &a)
       : table_(
- ::boost::unordered::detail::initial_size(
+ boost::unordered::detail::initial_size(
                 list.begin(), list.end(), n),
             hf, eql, a)
     {
@@ -1250,6 +1248,7 @@
         table_.insert_range(list.begin(), list.end());
         return *this;
     }
+
 #endif
 
     // size and capacity
@@ -1262,112 +1261,6 @@
 
     // modifiers
 
-#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
-
- template <class K, class T, class H, class P, class A>
- template <class... Args>
- typename unordered_multimap<K,T,H,P,A>::iterator
- unordered_multimap<K,T,H,P,A>::emplace(Args&&... args)
- {
- return iterator(table_.emplace(std::forward<Args>(args)...));
- }
-
- template <class K, class T, class H, class P, class A>
- template <class... Args>
- typename unordered_multimap<K,T,H,P,A>::iterator
- unordered_multimap<K,T,H,P,A>::emplace_hint(
- const_iterator, Args&&... args)
- {
- return iterator(table_.emplace(std::forward<Args>(args)...));
- }
-
-#else
-
-#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
- template <class K, class T, class H, class P, class A>
- typename unordered_multimap<K,T,H,P,A>::iterator
- unordered_multimap<K,T,H,P,A>::emplace(
- boost::unordered::detail::empty_emplace,
- value_type v
- )
- {
- return iterator(table_.emplace(boost::move(v)));
- }
-
- template <class K, class T, class H, class P, class A>
- typename unordered_multimap<K,T,H,P,A>::iterator
- unordered_multimap<K,T,H,P,A>::emplace_hint(const_iterator,
- boost::unordered::detail::empty_emplace,
- value_type v
- )
- {
- return iterator(table_.emplace(boost::move(v)));
- }
-#endif
-
-#define BOOST_UNORDERED_EMPLACE(z, n, _) \
- template <class K, class T, class H, class P, class A> \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- typename unordered_multimap<K,T,H,P,A>::iterator \
- unordered_multimap<K,T,H,P,A>::emplace( \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
- { \
- return iterator(table_.emplace( \
- BOOST_UNORDERED_CALL_PARAMS(z, n))); \
- } \
- \
- template <class K, class T, class H, class P, class A> \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- typename unordered_multimap<K,T,H,P,A>::iterator \
- unordered_multimap<K,T,H,P,A>::emplace_hint( \
- const_iterator, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
- { \
- return iterator(table_.emplace( \
- BOOST_UNORDERED_CALL_PARAMS(z, n))); \
- }
-
- BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_EMPLACE, _)
-
-#undef BOOST_UNORDERED_EMPLACE
-
-#endif
-
- template <class K, class T, class H, class P, class A>
- 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>
- 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));
- }
-
- template <class K, class T, class H, class P, class A>
- 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>
- 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)));
- }
-
     template <class K, class T, class H, class P, class A>
     template <class InputIt>
     void unordered_multimap<K,T,H,P,A>::insert(InputIt first, InputIt last)

Modified: branches/release/boost/unordered/unordered_map_fwd.hpp
==============================================================================
--- branches/release/boost/unordered/unordered_map_fwd.hpp (original)
+++ branches/release/boost/unordered/unordered_map_fwd.hpp 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -37,11 +37,11 @@
                 unordered_multimap<K, T, H, P, A>&);
     }
 
- using ::boost::unordered::unordered_map;
- using ::boost::unordered::unordered_multimap;
- using ::boost::unordered::swap;
- using ::boost::unordered::operator==;
- using ::boost::unordered::operator!=;
+ using boost::unordered::unordered_map;
+ using boost::unordered::unordered_multimap;
+ using boost::unordered::swap;
+ using boost::unordered::operator==;
+ using boost::unordered::operator!=;
 }
 
 #endif

Modified: branches/release/boost/unordered/unordered_set.hpp
==============================================================================
--- branches/release/boost/unordered/unordered_set.hpp (original)
+++ branches/release/boost/unordered/unordered_set.hpp 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -14,10 +14,12 @@
 #endif
 
 #include <boost/unordered/unordered_set_fwd.hpp>
-#include <boost/functional/hash.hpp>
 #include <boost/unordered/detail/allocator_helpers.hpp>
 #include <boost/unordered/detail/equivalent.hpp>
 #include <boost/unordered/detail/unique.hpp>
+#include <boost/unordered/detail/util.hpp>
+#include <boost/functional/hash.hpp>
+#include <boost/move/move.hpp>
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
 #include <initializer_list>
@@ -48,21 +50,18 @@
         typedef P key_equal;
         typedef A allocator_type;
 
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
     private:
-#endif
 
- typedef 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::set<H, P,
- value_allocator> types;
- typedef typename types::impl table;
+ typedef boost::unordered::detail::allocator_traits<value_allocator>
+ allocator_traits;
 
- typedef typename types::node_ptr node_ptr;
+ typedef boost::unordered::detail::set<value_allocator, H, P>
+ types;
+ typedef typename types::table table;
 
     public:
 
@@ -75,42 +74,36 @@
         typedef std::size_t size_type;
         typedef std::ptrdiff_t difference_type;
 
- typedef ::boost::unordered::iterator_detail::cl_iterator<
- value_allocator, true> const_local_iterator;
- typedef ::boost::unordered::iterator_detail::c_iterator<
- value_allocator, true> const_iterator;
- typedef const_local_iterator local_iterator;
- typedef const_iterator iterator;
+ typedef typename table::cl_iterator const_local_iterator;
+ typedef typename table::cl_iterator local_iterator;
+ typedef typename table::c_iterator const_iterator;
+ typedef typename table::c_iterator iterator;
 
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
     private:
-#endif
 
         table table_;
 
     public:
 
- // construct/destroy/copy
+ // constructors
 
         explicit unordered_set(
- size_type = ::boost::unordered::detail::default_bucket_count,
+ size_type = boost::unordered::detail::default_bucket_count,
                 const hasher& = hasher(),
                 const key_equal& = key_equal(),
                 const allocator_type& = allocator_type());
 
         explicit unordered_set(allocator_type const&);
 
- unordered_set(unordered_set const&, allocator_type const&);
-
         template <class InputIt>
- unordered_set(InputIt f, InputIt l);
+ unordered_set(InputIt, InputIt);
 
         template <class InputIt>
         unordered_set(
                 InputIt, InputIt,
                 size_type,
                 const hasher& = hasher(),
- const key_equal& = key_equal());
+ const key_equal& = key_equal());
 
         template <class InputIt>
         unordered_set(
@@ -119,26 +112,15 @@
                 const hasher&,
                 const key_equal&,
                 const allocator_type&);
-
- ~unordered_set();
 
- unordered_set& operator=(
- BOOST_COPY_ASSIGN_REF(unordered_set) x)
- {
- table_.assign(x.table_);
- return *this;
- }
+ // copy/move constructors
 
         unordered_set(unordered_set const&);
 
- unordered_set& operator=(BOOST_RV_REF(unordered_set) x)
- {
- table_.move_assign(x.table_);
- return *this;
- }
+ unordered_set(unordered_set const&, allocator_type const&);
 
         unordered_set(BOOST_RV_REF(unordered_set) other)
- : table_(other.table_, ::boost::unordered::detail::move_tag())
+ : table_(other.table_, boost::unordered::detail::move_tag())
         {
         }
 
@@ -149,11 +131,31 @@
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
         unordered_set(
                 std::initializer_list<value_type>,
- size_type = ::boost::unordered::detail::default_bucket_count,
+ size_type = boost::unordered::detail::default_bucket_count,
                 const hasher& = hasher(),
                 const key_equal&l = key_equal(),
                 const allocator_type& = allocator_type());
+#endif
+
+ // Destructor
+
+ ~unordered_set();
+
+ // Assign
+
+ unordered_set& operator=(BOOST_COPY_ASSIGN_REF(unordered_set) x)
+ {
+ table_.assign(x.table_);
+ return *this;
+ }
+
+ unordered_set& operator=(BOOST_RV_REF(unordered_set) x)
+ {
+ table_.move_assign(x.table_);
+ return *this;
+ }
 
+#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
         unordered_set& operator=(std::initializer_list<value_type>);
 #endif
 
@@ -208,52 +210,101 @@
             return const_iterator();
         }
 
- // modifiers
+ // emplace
 
 #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
         template <class... Args>
- std::pair<iterator, bool> emplace(Args&&...);
+ std::pair<iterator, bool> emplace(Args&&... args)
+ {
+ return table_.emplace(std::forward<Args>(args)...);
+ }
+
         template <class... Args>
- iterator emplace_hint(const_iterator, Args&&...);
+ iterator emplace_hint(const_iterator, Args&&... args)
+ {
+ return iterator(table_.emplace(std::forward<Args>(args)...).first);
+ }
 #else
 
+#define BOOST_UNORDERED_EMPLACE(z, n, _) \
+ template < \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
+ > \
+ std::pair<iterator, bool> emplace( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
+ ) \
+ { \
+ return table_.emplace( \
+ boost::unordered::detail::create_emplace_args( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
+ a) \
+ )); \
+ } \
+ \
+ template < \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
+ > \
+ iterator emplace_hint( \
+ const_iterator, \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
+ ) \
+ { \
+ return iterator(table_.emplace( \
+ boost::unordered::detail::create_emplace_args( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
+ a) \
+ )).first); \
+ }
+
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
+ BOOST_UNORDERED_EMPLACE, _)
+
+#undef BOOST_UNORDERED_EMPLACE
+
+#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
+
         std::pair<iterator, bool> emplace(
                 boost::unordered::detail::empty_emplace
                     = boost::unordered::detail::empty_emplace(),
- value_type v = value_type()
- );
- iterator emplace_hint(const_iterator,
+ value_type v = value_type())
+ {
+ return this->emplace(boost::move(v));
+ }
+
+ iterator emplace_hint(const_iterator hint,
                 boost::unordered::detail::empty_emplace
                     = boost::unordered::detail::empty_emplace(),
                 value_type v = value_type()
- );
+ )
+ {
+ return iterator(this->emplace_hint(hint, boost::move(v)));
+ }
 
-#define BOOST_UNORDERED_EMPLACE(z, n, _) \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- std::pair<iterator, bool> emplace( \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ); \
- \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- iterator emplace_hint(const_iterator, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- );
+#endif
 
- BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_EMPLACE, _)
+#endif
 
-#undef BOOST_UNORDERED_EMPLACE
+ std::pair<iterator, bool> insert(value_type const& x)
+ {
+ return this->emplace(x);
+ }
 
-#endif
+ std::pair<iterator, bool> insert(BOOST_UNORDERED_RV_REF(value_type) x)
+ {
+ return this->emplace(boost::move(x));
+ }
+
+ iterator insert(const_iterator hint, value_type const& x)
+ {
+ return this->emplace_hint(hint, x);
+ }
+
+ iterator insert(const_iterator hint,
+ BOOST_UNORDERED_RV_REF(value_type) x)
+ {
+ return this->emplace_hint(hint, boost::move(x));
+ }
 
- 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&);
- 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)
@@ -286,6 +337,7 @@
                 CompatiblePredicate const&) const;
 
         size_type count(const key_type&) const;
+
         std::pair<const_iterator, const_iterator>
         equal_range(const key_type&) const;
 
@@ -301,7 +353,7 @@
             return table_.max_bucket_count();
         }
 
- size_type bucket_size(size_type n) const;
+ size_type bucket_size(size_type) const;
 
         size_type bucket(const key_type& k) const
         {
@@ -310,14 +362,16 @@
 
         local_iterator begin(size_type n)
         {
- return local_iterator(
- table_.bucket_begin(n), n, table_.bucket_count_);
+ return table_.size_ ? local_iterator(
+ table_.get_start(n), n, table_.bucket_count_) :
+ local_iterator();
         }
 
         const_local_iterator begin(size_type n) const
         {
- return const_local_iterator(
- table_.bucket_begin(n), n, table_.bucket_count_);
+ return table_.size_ ? const_local_iterator(
+ table_.get_start(n), n, table_.bucket_count_) :
+ const_local_iterator();
         }
 
         local_iterator end(size_type)
@@ -332,8 +386,9 @@
 
         const_local_iterator cbegin(size_type n) const
         {
- return const_local_iterator(
- table_.bucket_begin(n), n, table_.bucket_count_);
+ return table_.size_ ? const_local_iterator(
+ table_.get_start(n), n, table_.bucket_count_) :
+ const_local_iterator();
         }
 
         const_local_iterator cend(size_type) const
@@ -350,7 +405,7 @@
 
         float load_factor() const;
         void max_load_factor(float);
- void rehash(size_type n);
+ void rehash(size_type);
 
 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
         friend bool operator==<T,H,P,A>(
@@ -372,21 +427,18 @@
         typedef P key_equal;
         typedef A allocator_type;
 
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
     private:
-#endif
 
- typedef 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::multiset<H, P,
- value_allocator> types;
- typedef typename types::impl table;
+ typedef boost::unordered::detail::allocator_traits<value_allocator>
+ allocator_traits;
 
- typedef typename types::node_ptr node_ptr;
+ typedef boost::unordered::detail::multiset<value_allocator, H, P>
+ types;
+ typedef typename types::table table;
 
     public:
 
@@ -399,33 +451,27 @@
         typedef std::size_t size_type;
         typedef std::ptrdiff_t difference_type;
 
- typedef ::boost::unordered::iterator_detail::cl_iterator<
- value_allocator, false> const_local_iterator;
- typedef ::boost::unordered::iterator_detail::c_iterator<
- value_allocator, false> const_iterator;
- typedef const_local_iterator local_iterator;
- typedef const_iterator iterator;
+ typedef typename table::cl_iterator const_local_iterator;
+ typedef typename table::cl_iterator local_iterator;
+ typedef typename table::c_iterator const_iterator;
+ typedef typename table::c_iterator iterator;
 
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
     private:
-#endif
 
         table table_;
 
     public:
 
- // construct/destroy/copy
+ // constructors
 
         explicit unordered_multiset(
- size_type = ::boost::unordered::detail::default_bucket_count,
+ size_type = boost::unordered::detail::default_bucket_count,
                 const hasher& = hasher(),
                 const key_equal& = key_equal(),
                 const allocator_type& = allocator_type());
 
         explicit unordered_multiset(allocator_type const&);
 
- unordered_multiset(unordered_multiset const&, allocator_type const&);
-
         template <class InputIt>
         unordered_multiset(InputIt, InputIt);
 
@@ -444,25 +490,14 @@
                 const key_equal&,
                 const allocator_type&);
 
- ~unordered_multiset();
-
- unordered_multiset& operator=(
- BOOST_COPY_ASSIGN_REF(unordered_multiset) x)
- {
- table_.assign(x.table_);
- return *this;
- }
+ // copy/move constructors
 
         unordered_multiset(unordered_multiset const&);
 
- unordered_multiset& operator=(BOOST_RV_REF(unordered_multiset) x)
- {
- table_.move_assign(x.table_);
- return *this;
- }
+ unordered_multiset(unordered_multiset const&, allocator_type const&);
 
         unordered_multiset(BOOST_RV_REF(unordered_multiset) other)
- : table_(other.table_, ::boost::unordered::detail::move_tag())
+ : table_(other.table_, boost::unordered::detail::move_tag())
         {
         }
 
@@ -473,11 +508,32 @@
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
         unordered_multiset(
                 std::initializer_list<value_type>,
- size_type = ::boost::unordered::detail::default_bucket_count,
+ size_type = boost::unordered::detail::default_bucket_count,
                 const hasher& = hasher(),
                 const key_equal&l = key_equal(),
                 const allocator_type& = allocator_type());
+#endif
 
+ // Destructor
+
+ ~unordered_multiset();
+
+ // Assign
+
+ unordered_multiset& operator=(
+ BOOST_COPY_ASSIGN_REF(unordered_multiset) x)
+ {
+ table_.assign(x.table_);
+ return *this;
+ }
+
+ unordered_multiset& operator=(BOOST_RV_REF(unordered_multiset) x)
+ {
+ table_.move_assign(x.table_);
+ return *this;
+ }
+
+#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
         unordered_multiset& operator=(std::initializer_list<value_type>);
 #endif
 
@@ -532,55 +588,102 @@
             return const_iterator();
         }
 
- // modifiers
+ // emplace
 
 #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
         template <class... Args>
- iterator emplace(Args&&...);
+ iterator emplace(Args&&... args)
+ {
+ return iterator(table_.emplace(std::forward<Args>(args)...));
+ }
+
         template <class... Args>
- iterator emplace_hint(const_iterator, Args&&...);
+ iterator emplace_hint(const_iterator, Args&&... args)
+ {
+ return iterator(table_.emplace(std::forward<Args>(args)...));
+ }
 #else
 
+#define BOOST_UNORDERED_EMPLACE(z, n, _) \
+ template < \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
+ > \
+ iterator emplace( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
+ ) \
+ { \
+ return iterator(table_.emplace( \
+ boost::unordered::detail::create_emplace_args( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
+ a) \
+ ))); \
+ } \
+ \
+ template < \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
+ > \
+ iterator emplace_hint( \
+ const_iterator, \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
+ ) \
+ { \
+ return iterator(table_.emplace( \
+ boost::unordered::detail::create_emplace_args( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
+ a) \
+ ))); \
+ }
+
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
+ BOOST_UNORDERED_EMPLACE, _)
+
+#undef BOOST_UNORDERED_EMPLACE
+
+#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
+
         iterator emplace(
                 boost::unordered::detail::empty_emplace
                     = boost::unordered::detail::empty_emplace(),
- value_type v = value_type()
- );
- iterator emplace_hint(const_iterator,
+ value_type v = value_type())
+ {
+ return this->emplace(boost::move(v));
+ }
+
+ iterator emplace_hint(const_iterator hint,
                 boost::unordered::detail::empty_emplace
                     = boost::unordered::detail::empty_emplace(),
                 value_type v = value_type()
- );
+ )
+ {
+ return this->emplace_hint(hint, boost::move(v));
+ }
 
-#define BOOST_UNORDERED_EMPLACE(z, n, _) \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- iterator emplace( \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ); \
- \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- iterator emplace_hint(const_iterator, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- );
+#endif
 
- BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_EMPLACE, _)
+#endif
 
-#undef BOOST_UNORDERED_EMPLACE
+ iterator insert(value_type const& x)
+ {
+ return this->emplace(x);
+ }
 
-#endif
+ iterator insert(BOOST_UNORDERED_RV_REF(value_type) x)
+ {
+ return this->emplace(boost::move(x));
+ }
+
+ iterator insert(const_iterator hint, value_type const& x)
+ {
+ return this->emplace_hint(hint, x);
+ }
 
- iterator insert(value_type const&);
- iterator insert(BOOST_UNORDERED_RV_REF(value_type));
- iterator insert(const_iterator, value_type const&);
- iterator insert(const_iterator, BOOST_UNORDERED_RV_REF(value_type));
+ iterator insert(const_iterator hint,
+ BOOST_UNORDERED_RV_REF(value_type) x)
+ {
+ return this->emplace_hint(hint, boost::move(x));
+ }
 
- template <class InputIt>
- void insert(InputIt, InputIt);
+ template <class InputIt> void insert(InputIt, InputIt);
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
         void insert(std::initializer_list<value_type>);
@@ -589,8 +692,8 @@
         iterator erase(const_iterator);
         size_type erase(const key_type&);
         iterator erase(const_iterator, const_iterator);
- void quick_erase(const_iterator position) { erase(position); }
- void erase_return_void(const_iterator position) { erase(position); }
+ void quick_erase(const_iterator it) { erase(it); }
+ void erase_return_void(const_iterator it) { erase(it); }
 
         void clear();
         void swap(unordered_multiset&);
@@ -612,6 +715,7 @@
                 CompatiblePredicate const&) const;
 
         size_type count(const key_type&) const;
+
         std::pair<const_iterator, const_iterator>
         equal_range(const key_type&) const;
 
@@ -636,14 +740,16 @@
 
         local_iterator begin(size_type n)
         {
- return local_iterator(
- table_.bucket_begin(n), n, table_.bucket_count_);
+ return table_.size_ ? local_iterator(
+ table_.get_start(n), n, table_.bucket_count_) :
+ local_iterator();
         }
 
         const_local_iterator begin(size_type n) const
         {
- return const_local_iterator(
- table_.bucket_begin(n), n, table_.bucket_count_);
+ return table_.size_ ? const_local_iterator(
+ table_.get_start(n), n, table_.bucket_count_) :
+ const_local_iterator();
         }
 
         local_iterator end(size_type)
@@ -658,8 +764,9 @@
 
         const_local_iterator cbegin(size_type n) const
         {
- return const_local_iterator(
- table_.bucket_begin(n), n, table_.bucket_count_);
+ return table_.size_ ? const_local_iterator(
+ table_.get_start(n), n, table_.bucket_count_) :
+ const_local_iterator();
         }
 
         const_local_iterator cend(size_type) const
@@ -698,7 +805,7 @@
 
     template <class T, class H, class P, class A>
     unordered_set<T,H,P,A>::unordered_set(allocator_type const& a)
- : table_(::boost::unordered::detail::default_bucket_count,
+ : table_(boost::unordered::detail::default_bucket_count,
             hasher(), key_equal(), a)
     {
     }
@@ -713,7 +820,7 @@
     template <class T, class H, class P, class A>
     template <class InputIt>
     unordered_set<T,H,P,A>::unordered_set(InputIt f, InputIt l)
- : table_(::boost::unordered::detail::initial_size(f, l),
+ : table_(boost::unordered::detail::initial_size(f, l),
         hasher(), key_equal(), allocator_type())
     {
         table_.insert_range(f, l);
@@ -726,7 +833,7 @@
             size_type n,
             const hasher &hf,
             const key_equal &eql)
- : table_(::boost::unordered::detail::initial_size(f, l, n),
+ : table_(boost::unordered::detail::initial_size(f, l, n),
             hf, eql, allocator_type())
     {
         table_.insert_range(f, l);
@@ -740,7 +847,7 @@
             const hasher &hf,
             const key_equal &eql,
             const allocator_type &a)
- : table_(::boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
+ : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
     {
         table_.insert_range(f, l);
     }
@@ -749,7 +856,8 @@
     unordered_set<T,H,P,A>::~unordered_set() {}
 
     template <class T, class H, class P, class A>
- unordered_set<T,H,P,A>::unordered_set(unordered_set const& other)
+ unordered_set<T,H,P,A>::unordered_set(
+ unordered_set const& other)
       : table_(other.table_)
     {
     }
@@ -759,7 +867,7 @@
     template <class T, class H, class P, class A>
     unordered_set<T,H,P,A>::unordered_set(
             unordered_set&& other, allocator_type const& a)
- : table_(other.table_, a, ::boost::unordered::detail::move_tag())
+ : table_(other.table_, a, boost::unordered::detail::move_tag())
     {
     }
 
@@ -772,7 +880,7 @@
             std::initializer_list<value_type> list, size_type n,
             const hasher &hf, const key_equal &eql, const allocator_type &a)
       : table_(
- ::boost::unordered::detail::initial_size(
+ boost::unordered::detail::initial_size(
                 list.begin(), list.end(), n),
             hf, eql, a)
     {
@@ -800,107 +908,6 @@
 
     // modifiers
 
-#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
- template <class T, class H, class P, class A>
- template <class... Args>
- std::pair<typename unordered_set<T,H,P,A>::iterator, bool>
- unordered_set<T,H,P,A>::emplace(Args&&... args)
- {
- return table_.emplace(std::forward<Args>(args)...);
- }
-
- template <class T, class H, class P, class A>
- template <class... Args>
- typename unordered_set<T,H,P,A>::iterator
- unordered_set<T,H,P,A>::emplace_hint(const_iterator, Args&&... args)
- {
- return iterator(table_.emplace(std::forward<Args>(args)...).first);
- }
-#else
-
- template <class T, class H, class P, class A>
- std::pair<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 table_.emplace(boost::move(v));
- }
-
- template <class T, class H, class P, class A>
- typename unordered_set<T,H,P,A>::iterator
- unordered_set<T,H,P,A>::emplace_hint(const_iterator,
- boost::unordered::detail::empty_emplace,
- value_type v
- )
- {
- return iterator(table_.emplace(boost::move(v)).first);
- }
-
-#define BOOST_UNORDERED_EMPLACE(z, n, _) \
- template <class T, class H, class P, class A> \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- std::pair<typename unordered_set<T,H,P,A>::iterator, bool> \
- unordered_set<T,H,P,A>::emplace( \
- BOOST_UNORDERED_FUNCTION_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) \
- > \
- typename unordered_set<T,H,P,A>::iterator \
- unordered_set<T,H,P,A>::emplace_hint( \
- const_iterator, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
- ) \
- { \
- return iterator(table_.emplace( \
- BOOST_UNORDERED_CALL_PARAMS(z, n)).first); \
- }
-
- BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_EMPLACE, _)
-
-#undef BOOST_UNORDERED_EMPLACE
-
-#endif
-
- template <class T, class H, class P, class A>
- std::pair<typename unordered_set<T,H,P,A>::iterator, bool>
- unordered_set<T,H,P,A>::insert(value_type const& obj)
- {
- return table_.emplace(obj);
- }
-
- template <class T, class H, class P, class A>
- 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);
- }
-
- template <class T, class H, class P, class A>
- 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 table_.emplace(boost::move(obj));
- }
-
- template <class T, class H, class P, class A>
- typename unordered_set<T,H,P,A>::iterator
- unordered_set<T,H,P,A>::insert(const_iterator,
- BOOST_UNORDERED_RV_REF(value_type) obj)
- {
- return iterator(table_.emplace(boost::move(obj)).first);
- }
-
     template <class T, class H, class P, class A>
     template <class InputIt>
     void unordered_set<T,H,P,A>::insert(InputIt first, InputIt last)
@@ -910,7 +917,8 @@
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
     template <class T, class H, class P, class A>
- void unordered_set<T,H,P,A>::insert(std::initializer_list<value_type> list)
+ void unordered_set<T,H,P,A>::insert(
+ std::initializer_list<value_type> list)
     {
         table_.insert_range(list.begin(), list.end());
     }
@@ -932,7 +940,8 @@
 
     template <class T, class H, class P, class A>
     typename unordered_set<T,H,P,A>::iterator
- unordered_set<T,H,P,A>::erase(const_iterator first, const_iterator last)
+ unordered_set<T,H,P,A>::erase(
+ const_iterator first, const_iterator last)
     {
         return iterator(table_.erase_range(first.node_, last.node_));
     }
@@ -1074,7 +1083,7 @@
 
     template <class T, class H, class P, class A>
     unordered_multiset<T,H,P,A>::unordered_multiset(allocator_type const& a)
- : table_(::boost::unordered::detail::default_bucket_count,
+ : table_(boost::unordered::detail::default_bucket_count,
             hasher(), key_equal(), a)
     {
     }
@@ -1089,7 +1098,7 @@
     template <class T, class H, class P, class A>
     template <class InputIt>
     unordered_multiset<T,H,P,A>::unordered_multiset(InputIt f, InputIt l)
- : table_(::boost::unordered::detail::initial_size(f, l),
+ : table_(boost::unordered::detail::initial_size(f, l),
         hasher(), key_equal(), allocator_type())
     {
         table_.insert_range(f, l);
@@ -1102,7 +1111,7 @@
             size_type n,
             const hasher &hf,
             const key_equal &eql)
- : table_(::boost::unordered::detail::initial_size(f, l, n),
+ : table_(boost::unordered::detail::initial_size(f, l, n),
             hf, eql, allocator_type())
     {
         table_.insert_range(f, l);
@@ -1116,7 +1125,7 @@
             const hasher &hf,
             const key_equal &eql,
             const allocator_type &a)
- : table_(::boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
+ : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
     {
         table_.insert_range(f, l);
     }
@@ -1136,19 +1145,20 @@
     template <class T, class H, class P, class A>
     unordered_multiset<T,H,P,A>::unordered_multiset(
             unordered_multiset&& other, allocator_type const& a)
- : table_(other.table_, a, ::boost::unordered::detail::move_tag())
+ : table_(other.table_, a, boost::unordered::detail::move_tag())
     {
     }
 
 #endif
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
+
     template <class T, class H, class P, class A>
     unordered_multiset<T,H,P,A>::unordered_multiset(
             std::initializer_list<value_type> list, size_type n,
             const hasher &hf, const key_equal &eql, const allocator_type &a)
       : table_(
- ::boost::unordered::detail::initial_size(
+ boost::unordered::detail::initial_size(
                 list.begin(), list.end(), n),
             hf, eql, a)
     {
@@ -1163,6 +1173,7 @@
         table_.insert_range(list.begin(), list.end());
         return *this;
     }
+
 #endif
 
     // size and capacity
@@ -1175,110 +1186,6 @@
 
     // modifiers
 
-#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
-
- template <class T, class H, class P, class A>
- template <class... Args>
- typename unordered_multiset<T,H,P,A>::iterator
- unordered_multiset<T,H,P,A>::emplace(Args&&... args)
- {
- return iterator(table_.emplace(std::forward<Args>(args)...));
- }
-
- template <class T, class H, class P, class A>
- template <class... Args>
- typename unordered_multiset<T,H,P,A>::iterator
- unordered_multiset<T,H,P,A>::emplace_hint(
- const_iterator, Args&&... args)
- {
- return iterator(table_.emplace(std::forward<Args>(args)...));
- }
-
-#else
-
- template <class T, class H, class P, class A>
- typename unordered_multiset<T,H,P,A>::iterator
- unordered_multiset<T,H,P,A>::emplace(
- boost::unordered::detail::empty_emplace,
- value_type v
- )
- {
- return iterator(table_.emplace(boost::move(v)));
- }
-
- template <class T, class H, class P, class A>
- typename unordered_multiset<T,H,P,A>::iterator
- unordered_multiset<T,H,P,A>::emplace_hint(const_iterator,
- boost::unordered::detail::empty_emplace,
- value_type v
- )
- {
- return iterator(table_.emplace(boost::move(v)));
- }
-
-#define BOOST_UNORDERED_EMPLACE(z, n, _) \
- template <class T, class H, class P, class A> \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- typename unordered_multiset<T,H,P,A>::iterator \
- unordered_multiset<T,H,P,A>::emplace( \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
- { \
- return iterator(table_.emplace( \
- BOOST_UNORDERED_CALL_PARAMS(z, n))); \
- } \
- \
- template <class T, class H, class P, class A> \
- template < \
- BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
- > \
- typename unordered_multiset<T,H,P,A>::iterator \
- unordered_multiset<T,H,P,A>::emplace_hint( \
- const_iterator, \
- BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
- { \
- return iterator(table_.emplace( \
- BOOST_UNORDERED_CALL_PARAMS(z, n))); \
- }
-
- BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_EMPLACE, _)
-
-#undef BOOST_UNORDERED_EMPLACE
-
-#endif
-
- template <class T, class H, class P, class A>
- 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>
- 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));
- }
-
- template <class T, class H, class P, class A>
- 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>
- typename unordered_multiset<T,H,P,A>::iterator
- unordered_multiset<T,H,P,A>::insert(const_iterator,
- BOOST_UNORDERED_RV_REF(value_type) obj)
- {
- return iterator(table_.emplace(boost::move(obj)));
- }
-
     template <class T, class H, class P, class A>
     template <class InputIt>
     void unordered_multiset<T,H,P,A>::insert(InputIt first, InputIt last)
@@ -1288,7 +1195,8 @@
 
 #if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
     template <class T, class H, class P, class A>
- void unordered_multiset<T,H,P,A>::insert(std::initializer_list<value_type> list)
+ void unordered_multiset<T,H,P,A>::insert(
+ std::initializer_list<value_type> list)
     {
         table_.insert_range(list.begin(), list.end());
     }
@@ -1310,7 +1218,8 @@
 
     template <class T, class H, class P, class A>
     typename unordered_multiset<T,H,P,A>::iterator
- unordered_multiset<T,H,P,A>::erase(const_iterator first, const_iterator last)
+ unordered_multiset<T,H,P,A>::erase(
+ const_iterator first, const_iterator last)
     {
         return iterator(table_.erase_range(first.node_, last.node_));
     }
@@ -1439,7 +1348,6 @@
 #endif
         m1.swap(m2);
     }
-
 } // namespace unordered
 } // namespace boost
 

Modified: branches/release/boost/unordered/unordered_set_fwd.hpp
==============================================================================
--- branches/release/boost/unordered/unordered_set_fwd.hpp (original)
+++ branches/release/boost/unordered/unordered_set_fwd.hpp 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -37,11 +37,11 @@
                 unordered_multiset<T, H, P, A> &m2);
     }
 
- using ::boost::unordered::unordered_set;
- using ::boost::unordered::unordered_multiset;
- using ::boost::unordered::swap;
- using ::boost::unordered::operator==;
- using ::boost::unordered::operator!=;
+ using boost::unordered::unordered_set;
+ using boost::unordered::unordered_multiset;
+ using boost::unordered::swap;
+ using boost::unordered::operator==;
+ using boost::unordered::operator!=;
 }
 
 #endif

Modified: branches/release/libs/unordered/doc/ref.php
==============================================================================
--- branches/release/libs/unordered/doc/ref.php (original)
+++ branches/release/libs/unordered/doc/ref.php 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -418,7 +418,7 @@
                 <para>In version of Boost before 1.48 this emulated the variadic pair
                       constructor from older C++0x drafts. For backwards compatability
                       this can be enabled by defining the macro
- <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
+ <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
               </notes>
             </method>
             <method name="emplace_hint">
@@ -459,12 +459,11 @@
                       for rvalue references or move semantics.</para>
                 <para>Since existing <code>std::pair</code> implementations don't support
                       <code>std::piecewise_construct</code> this emulates it,
- but using <code>boost::unordered::piecewise_construct</code>.
+ but using <code>boost::unordered::piecewise_construct</code>.</para>
                 <para>In version of Boost before 1.48 this emulated the variadic pair
                       constructor from older C++0x drafts. For backwards compatability
                       this can be enabled by defining the macro
- <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
- </para>
+ <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
               </notes>
             </method>
             <method name="insert">
@@ -811,10 +810,6 @@
               <throws>
                 <para>An exception object of type <code>std::out_of_range</code> if no such element is present.</para>
               </throws>
- <notes>
- <para>This is not specified in the draft standard, but that is probably an oversight. The issue has been raised in
- <ulink url="http://groups.google.com/group/comp.std.c++/browse_thread/thread/ab7c22a868fd370b">comp.std.c++</ulink>.</para>
- </notes>
             </overloaded-method>
 <?php endif; ?>
           </method-group>

Modified: branches/release/libs/unordered/doc/ref.xml
==============================================================================
--- branches/release/libs/unordered/doc/ref.xml (original)
+++ branches/release/libs/unordered/doc/ref.xml 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -356,7 +356,7 @@
                 <para>In version of Boost before 1.48 this emulated the variadic pair
                       constructor from older C++0x drafts. For backwards compatability
                       this can be enabled by defining the macro
- <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
+ <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
               </notes>
             </method>
             <method name="emplace_hint">
@@ -390,12 +390,11 @@
                       for rvalue references or move semantics.</para>
                 <para>Since existing <code>std::pair</code> implementations don't support
                       <code>std::piecewise_construct</code> this emulates it,
- but using <code>boost::unordered::piecewise_construct</code>.
+ but using <code>boost::unordered::piecewise_construct</code>.</para>
                 <para>In version of Boost before 1.48 this emulated the variadic pair
                       constructor from older C++0x drafts. For backwards compatability
                       this can be enabled by defining the macro
- <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
- </para>
+ <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
               </notes>
             </method>
             <method name="insert">
@@ -1296,7 +1295,7 @@
                 <para>In version of Boost before 1.48 this emulated the variadic pair
                       constructor from older C++0x drafts. For backwards compatability
                       this can be enabled by defining the macro
- <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
+ <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
               </notes>
             </method>
             <method name="emplace_hint">
@@ -1330,12 +1329,11 @@
                       for rvalue references or move semantics.</para>
                 <para>Since existing <code>std::pair</code> implementations don't support
                       <code>std::piecewise_construct</code> this emulates it,
- but using <code>boost::unordered::piecewise_construct</code>.
+ but using <code>boost::unordered::piecewise_construct</code>.</para>
                 <para>In version of Boost before 1.48 this emulated the variadic pair
                       constructor from older C++0x drafts. For backwards compatability
                       this can be enabled by defining the macro
- <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
- </para>
+ <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
               </notes>
             </method>
             <method name="insert">
@@ -2248,7 +2246,7 @@
                 <para>In version of Boost before 1.48 this emulated the variadic pair
                       constructor from older C++0x drafts. For backwards compatability
                       this can be enabled by defining the macro
- <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
+ <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
               </notes>
             </method>
             <method name="emplace_hint">
@@ -2282,12 +2280,11 @@
                       for rvalue references or move semantics.</para>
                 <para>Since existing <code>std::pair</code> implementations don't support
                       <code>std::piecewise_construct</code> this emulates it,
- but using <code>boost::unordered::piecewise_construct</code>.
+ but using <code>boost::unordered::piecewise_construct</code>.</para>
                 <para>In version of Boost before 1.48 this emulated the variadic pair
                       constructor from older C++0x drafts. For backwards compatability
                       this can be enabled by defining the macro
- <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
- </para>
+ <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
               </notes>
             </method>
             <method name="insert">
@@ -2618,10 +2615,6 @@
               <throws>
                 <para>An exception object of type <code>std::out_of_range</code> if no such element is present.</para>
               </throws>
- <notes>
- <para>This is not specified in the draft standard, but that is probably an oversight. The issue has been raised in
- <ulink url="http://groups.google.com/group/comp.std.c++/browse_thread/thread/ab7c22a868fd370b">comp.std.c++</ulink>.</para>
- </notes>
             </overloaded-method>
           </method-group>
           <method-group name="bucket interface">
@@ -3237,7 +3230,7 @@
                 <para>In version of Boost before 1.48 this emulated the variadic pair
                       constructor from older C++0x drafts. For backwards compatability
                       this can be enabled by defining the macro
- <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
+ <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
               </notes>
             </method>
             <method name="emplace_hint">
@@ -3271,12 +3264,11 @@
                       for rvalue references or move semantics.</para>
                 <para>Since existing <code>std::pair</code> implementations don't support
                       <code>std::piecewise_construct</code> this emulates it,
- but using <code>boost::unordered::piecewise_construct</code>.
+ but using <code>boost::unordered::piecewise_construct</code>.</para>
                 <para>In version of Boost before 1.48 this emulated the variadic pair
                       constructor from older C++0x drafts. For backwards compatability
                       this can be enabled by defining the macro
- <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
- </para>
+ <code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
               </notes>
             </method>
             <method name="insert">

Modified: branches/release/libs/unordered/test/exception/Jamfile.v2
==============================================================================
--- branches/release/libs/unordered/test/exception/Jamfile.v2 (original)
+++ branches/release/libs/unordered/test/exception/Jamfile.v2 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -14,9 +14,9 @@
         <toolset>intel:<warnings>on
         <toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
         <toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
- <toolset>gcc:<define>_GLIBCXX_DEBUG
+ #<toolset>gcc:<define>_GLIBCXX_DEBUG
         #<toolset>darwin:<define>_GLIBCXX_DEBUG
- <toolset>msvc:<warnings-as-errors>on
+ #<toolset>msvc:<warnings-as-errors>on
         #<toolset>gcc:<warnings-as-errors>on
         #<toolset>darwin:<warnings-as-errors>on
     ;

Modified: branches/release/libs/unordered/test/objects/minimal.hpp
==============================================================================
--- branches/release/libs/unordered/test/objects/minimal.hpp (original)
+++ branches/release/libs/unordered/test/objects/minimal.hpp 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -202,17 +202,67 @@
     template <class T> class ptr;
     template <class T> class const_ptr;
 
+ struct void_ptr
+ {
+#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+ template <typename T>
+ friend class ptr;
+ private:
+#endif
+
+ void* ptr_;
+
+ public:
+ void_ptr() : ptr_(0) {}
+
+ template <typename T>
+ explicit void_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
+
+ // I'm not using the safe bool idiom because the containers should be
+ // able to cope with bool conversions.
+ operator bool() const { return !!ptr_; }
+
+ bool operator==(void_ptr const& x) const { return ptr_ == x.ptr_; }
+ bool operator!=(void_ptr const& x) const { return ptr_ != x.ptr_; }
+ };
+
+ class void_const_ptr
+ {
+#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+ template <typename T>
+ friend class const_ptr;
+ private:
+#endif
+
+ void* ptr_;
+
+ public:
+ void_const_ptr() : ptr_(0) {}
+
+ template <typename T>
+ explicit void_const_ptr(const_ptr<T> const& x) : ptr_(x.ptr_) {}
+
+ // I'm not using the safe bool idiom because the containers should be
+ // able to cope with bool conversions.
+ operator bool() const { return !!ptr_; }
+
+ bool operator==(void_const_ptr const& x) const { return ptr_ == x.ptr_; }
+ bool operator!=(void_const_ptr const& x) const { return ptr_ != x.ptr_; }
+ };
+
     template <class T>
     class ptr
     {
         friend class allocator<T>;
         friend class const_ptr<T>;
+ friend struct void_ptr;
 
         T* ptr_;
 
         ptr(T* x) : ptr_(x) {}
     public:
         ptr() : ptr_(0) {}
+ explicit ptr(void_ptr const& x) : ptr_((T*) x.ptr_) {}
 
         T& operator*() const { return *ptr_; }
         T* operator->() const { return ptr_; }
@@ -234,13 +284,6 @@
         bool operator>(ptr const& x) const { return ptr_ > x.ptr_; }
         bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; }
         bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; }
-
- bool operator==(const_ptr<T> const& x) const { return ptr_ == x.ptr_; }
- bool operator!=(const_ptr<T> const& x) const { return ptr_ != x.ptr_; }
- bool operator<(const_ptr<T> const& x) const { return ptr_ < x.ptr_; }
- bool operator>(const_ptr<T> const& x) const { return ptr_ > x.ptr_; }
- bool operator<=(const_ptr<T> const& x) const { return ptr_ <= x.ptr_; }
- bool operator>=(const_ptr<T> const& x) const { return ptr_ >= x.ptr_; }
     private:
         // TODO:
         //ampersand_operator_used operator&() const { return ampersand_operator_used(); }
@@ -250,6 +293,7 @@
     class const_ptr
     {
         friend class allocator<T>;
+ friend struct const_void_ptr;
 
         T const* ptr_;
 
@@ -257,6 +301,7 @@
     public:
         const_ptr() : ptr_(0) {}
         const_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
+ explicit const_ptr(void_const_ptr const& x) : ptr_((T const*) x.ptr_) {}
 
         T const& operator*() const { return *ptr_; }
         T const* operator->() const { return ptr_; }
@@ -270,13 +315,6 @@
         bool operator!() const { return !ptr_; }
         operator bool() const { return !!ptr_; }
 
- bool operator==(ptr<T> const& x) const { return ptr_ == x.ptr_; }
- bool operator!=(ptr<T> const& x) const { return ptr_ != x.ptr_; }
- bool operator<(ptr<T> const& x) const { return ptr_ < x.ptr_; }
- bool operator>(ptr<T> const& x) const { return ptr_ > x.ptr_; }
- bool operator<=(ptr<T> const& x) const { return ptr_ <= x.ptr_; }
- bool operator>=(ptr<T> const& x) const { return ptr_ >= x.ptr_; }
-
         bool operator==(const_ptr const& x) const { return ptr_ == x.ptr_; }
         bool operator!=(const_ptr const& x) const { return ptr_ != x.ptr_; }
         bool operator<(const_ptr const& x) const { return ptr_ < x.ptr_; }
@@ -294,6 +332,8 @@
     public:
         typedef std::size_t size_type;
         typedef std::ptrdiff_t difference_type;
+ typedef void_ptr void_pointer;
+ typedef void_const_ptr void_const_pointer;
         typedef ptr<T> pointer;
         typedef const_ptr<T> const_pointer;
         typedef T& reference;

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-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -11,9 +11,9 @@
         <toolset>intel:<warnings>on
         <toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion"
         <toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion"
- <toolset>gcc:<define>_GLIBCXX_DEBUG
+ #<toolset>gcc:<define>_GLIBCXX_DEBUG
         #<toolset>darwin:<define>_GLIBCXX_DEBUG
- <toolset>msvc:<warnings-as-errors>on
+ #<toolset>msvc:<warnings-as-errors>on
         #<toolset>gcc:<warnings-as-errors>on
         #<toolset>darwin:<warnings-as-errors>on
     ;

Modified: branches/release/libs/unordered/test/unordered/allocator_traits.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/allocator_traits.cpp (original)
+++ branches/release/libs/unordered/test/unordered/allocator_traits.cpp 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -136,8 +136,17 @@
 
 // allocator 2
 
+template <typename Alloc>
+struct allocator2_base
+{
+ Alloc select_on_container_copy_construction() const {
+ ++selected;
+ return Alloc();
+ }
+};
+
 template <typename T>
-struct allocator2
+struct allocator2 : allocator2_base<allocator2<T> >
 {
     typedef T value_type;
     typedef T* pointer;
@@ -149,12 +158,6 @@
     typedef no_type propagate_on_container_copy_assignment;
     typedef no_type propagate_on_container_move_assignment;
     typedef no_type propagate_on_container_swap;
-
- // Note: Not const - so it shouldn't be called.
- allocator2<T> select_on_container_copy_construction() {
- ++selected;
- return allocator2<T>();
- }
 };
 
 void test_allocator2()
@@ -169,7 +172,7 @@
     BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
     BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
     BOOST_TEST(!traits::propagate_on_container_swap::value);
- BOOST_TEST(call_select<allocator>() == 0);
+ BOOST_TEST(call_select<allocator>() == 1);
 }
 
 // allocator 3

Modified: branches/release/libs/unordered/test/unordered/assign_tests.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/assign_tests.cpp (original)
+++ branches/release/libs/unordered/test/unordered/assign_tests.cpp 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -57,9 +57,12 @@
 
         T y;
         y.max_load_factor(x.max_load_factor() / 20);
+ float mlf = x.max_load_factor();
         y = x;
+ tracker.compare(x);
         tracker.compare(y);
- BOOST_TEST(x.max_load_factor() == y.max_load_factor());
+ BOOST_TEST(x.max_load_factor() == mlf);
+ BOOST_TEST(y.max_load_factor() == mlf);
     }
 }
 

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-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -128,7 +128,7 @@
     std::equal_to<int> equal_to;
     int value = 0;
 
- std::cout<<"Test unordered_set.\n";
+ std::cout<<"Test unordered_set." << std::endl;
 
     boost::unordered_set<int> set;
     
@@ -145,7 +145,7 @@
     unordered_set_test(set2, value);
     unordered_copyable_test(set2, value, value, hash, equal_to);
 
- std::cout<<"Test unordered_multiset.\n";
+ std::cout<<"Test unordered_multiset." << std::endl;
 
     boost::unordered_multiset<int> multiset;
     

Modified: branches/release/libs/unordered/test/unordered/compile_tests.hpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/compile_tests.hpp (original)
+++ branches/release/libs/unordered/test/unordered/compile_tests.hpp 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -413,6 +413,7 @@
     BOOST_DEDUCED_TYPENAME X::value_type* j = 0;
 
     X(i, j, 10, hf, eq);
+
     X a5(i, j, 10, hf, eq);
     X(i, j, 10, hf);
     X a6(i, j, 10, hf);

Modified: branches/release/libs/unordered/test/unordered/constructor_tests.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/constructor_tests.cpp (original)
+++ branches/release/libs/unordered/test/unordered/constructor_tests.cpp 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -15,8 +15,6 @@
 #include "../helpers/input_iterator.hpp"
 #include "../helpers/invariants.hpp"
 
-#include <iostream>
-
 namespace constructor_tests {
 
 test::seed_t seed(356730);

Modified: branches/release/libs/unordered/test/unordered/incomplete_test.cpp
==============================================================================
--- branches/release/libs/unordered/test/unordered/incomplete_test.cpp (original)
+++ branches/release/libs/unordered/test/unordered/incomplete_test.cpp 2011-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -5,6 +5,7 @@
 
 #include "../helpers/prefix.hpp"
 
+#include <utility>
 #include <boost/unordered_map.hpp>
 #include <boost/unordered_set.hpp>
 

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-10-09 14:30:10 EDT (Sun, 09 Oct 2011)
@@ -245,9 +245,11 @@
         x.emplace();
 #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
         COPY_COUNT(1); MOVE_COUNT(0);
-#else
+#elif !defined(BOOST_NO_RVALUE_REFERENCES)
         // source_cost doesn't make much sense here, but it seems to fit.
         COPY_COUNT(1); MOVE_COUNT(source_cost);
+#else
+ COPY_COUNT(1); MOVE_COUNT(1 + source_cost);
 #endif
 #endif
 
@@ -355,9 +357,7 @@
 
 #if (defined(__GNUC__) && __GNUC__ > 4) || \
     (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 2) || \
- (defined(BOOST_MSVC) && BOOST_MSVC >= 1600 ) || \
- (!defined(__GNUC__) && !defined(BOOST_MSVC))
-
+ (defined(BOOST_MSVC) && BOOST_MSVC >= 1600 )
         count_copies part;
         reset();
         std::pair<count_copies const&, count_copies const&> a_ref(part, part);


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