diff --git a/doc/changes.qbk b/doc/changes.qbk
index abe2b812..c5cb963c 100644
--- a/doc/changes.qbk
+++ b/doc/changes.qbk
@@ -178,10 +178,14 @@ C++11 support has resulted in some breaking changes:
[h2 Boost 1.50.0]
* Fix equality for `unordered_multiset` and `unordered_multimap`.
-* [@http://svn.boost.org/trac/boost/ticket/6771 Ticket 6771]:
+* [@https://svn.boost.org/trac/boost/ticket/6857 Ticket 6857]:
+ Implement `reserve`.
+* [@https://svn.boost.org/trac/boost/ticket/6771 Ticket 6771]:
Avoid gcc's `-Wfloat-equal` warning.
-* [@http://svn.boost.org/trac/boost/ticket/6784 Ticket 6784]:
+* [@https://svn.boost.org/trac/boost/ticket/6784 Ticket 6784]:
Fix some Sun specific code.
+* [@https://svn.boost.org/trac/boost/ticket/6190 Ticket 6190]:
+ Avoid gcc's `-Wshadow` warning.
* Remove some of the smaller prime number of buckets, as they may make
collisions quite probable (e.g. multiples of 5 are very common because
we used base 10).
diff --git a/doc/ref.php b/doc/ref.php
index cc871be5..e014555c 100644
--- a/doc/ref.php
+++ b/doc/ref.php
@@ -963,6 +963,18 @@ EOL;
The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.
+
+
+ size_type
+
+ void
+
+ Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.
+
+
+ The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.
+
+
diff --git a/doc/ref.xml b/doc/ref.xml
index aecfd0af..9e4e399e 100644
--- a/doc/ref.xml
+++ b/doc/ref.xml
@@ -846,6 +846,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.
+
+
+ size_type
+
+ void
+
+ Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.
+
+
+ The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.
+
+
@@ -1797,6 +1809,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.
+
+
+ size_type
+
+ void
+
+ Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.
+
+
+ The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.
+
+
@@ -2793,6 +2817,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.
+
+
+ size_type
+
+ void
+
+ Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.
+
+
+ The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.
+
+
@@ -3758,6 +3794,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.
+
+
+ size_type
+
+ void
+
+ Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.
+
+
+ The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.
+
+
diff --git a/include/boost/unordered/detail/allocator_helpers.hpp b/include/boost/unordered/detail/allocator_helpers.hpp
index 4f2e13d8..d77aa6a1 100644
--- a/include/boost/unordered/detail/allocator_helpers.hpp
+++ b/include/boost/unordered/detail/allocator_helpers.hpp
@@ -15,47 +15,41 @@
# pragma once
#endif
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
+#include
#include
#include
-#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
-// An allocator_traits test is currently failing for gcc 4.7 on mingw. I think
-// this is because it's an older development version. Temporarily disabling
-// std::allocator_traits in order ot get clean test results. Will reactivate
-// later.
+////////////////////////////////////////////////////////////////////////////////
+//
+// Pick which version of allocator_traits to use
+//
+// 0 = Own partial implementation
+// 1 = std::allocator_traits
+// 2 = boost::container::allocator_traits
-/*
+#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
# if defined(__GXX_EXPERIMENTAL_CXX0X__) && \
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
+# elif defined(BOOST_MSVC)
+# if BOOST_MSVC < 1400
+ // Use container's allocator_traits for older versions of Visual
+ // C++ as I don't test with them.
+# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 2
+# elif BOOST_MSVC >= 1700
+# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
+# endif
# endif
-*/
-
-// Use container's allocator_traits for older versions of Visual C++ as I don't
-// test with them.
-# if defined(BOOST_MSVC) && BOOST_MSVC < 1400
-# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 2
-# endif
-
#endif
#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
#endif
-#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
-# include
-#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
-# include
-#endif
+////////////////////////////////////////////////////////////////////////////////
+//
+// Some utilities for implementing allocator_traits, but useful elsewhere so
+// they're always defined.
#if !defined(BOOST_NO_0X_HDR_TYPE_TRAITS)
# include
@@ -102,48 +96,22 @@ namespace boost { namespace unordered { namespace detail {
#endif
////////////////////////////////////////////////////////////////////////////
- // Bits and pieces for implementing traits
+ // Expression test mechanism
//
- // Some of these are also used elsewhere
-
- template typename boost::add_lvalue_reference::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
- no_type is_private_type(T const&);
- yes_type is_private_type(private_type const&);
-
- struct convert_from_anything {
- template
- convert_from_anything(T const&);
- };
+ // When SFINAE expressions are available, define
+ // BOOST_UNORDERED_HAS_FUNCTION which can check if a function call is
+ // supported by a class, otherwise define BOOST_UNORDERED_HAS_MEMBER which
+ // can detect if a class has the specified member, but not that it has the
+ // correct type, this is good enough for a passable impression of
+ // allocator_traits.
#if !defined(BOOST_NO_SFINAE_EXPR)
-# define BOOST_UNORDERED_HAVE_CALL_DETECTION 1
-
template struct expr_test;
template struct expr_test : T {};
template static char for_expr_test(U const&);
-#define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
+# define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
template \
static typename boost::unordered::detail::expr_test< \
BOOST_PP_CAT(choice, result), \
@@ -152,12 +120,12 @@ namespace boost { namespace unordered { namespace detail {
0)))>::type test( \
BOOST_PP_CAT(choice, count))
-#define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \
+# define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \
template \
static BOOST_PP_CAT(choice, result)::type test( \
BOOST_PP_CAT(choice, count))
-#define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
+# define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
struct BOOST_PP_CAT(has_, name) \
{ \
BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \
@@ -169,11 +137,9 @@ namespace boost { namespace unordered { namespace detail {
#else
-# define BOOST_UNORDERED_HAVE_CALL_DETECTION 0
-
template struct identity { typedef T type; };
-#define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
+# define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
\
typedef typename boost::unordered::detail::identity::type \
BOOST_PP_CAT(check, count); \
@@ -187,11 +153,11 @@ namespace boost { namespace unordered { namespace detail {
BOOST_PP_CAT(test, count)<&U::name>::type \
test(BOOST_PP_CAT(choice, count))
-#define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \
+# define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \
template static BOOST_PP_CAT(choice, result)::type \
test(BOOST_PP_CAT(choice, count))
-#define BOOST_UNORDERED_HAS_MEMBER(name) \
+# define BOOST_UNORDERED_HAS_MEMBER(name) \
struct BOOST_PP_CAT(has_, name) \
{ \
struct impl { \
@@ -211,97 +177,90 @@ namespace boost { namespace unordered { namespace detail {
#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 == 1
+////////////////////////////////////////////////////////////////////////////////
+//
+// Allocator traits
+//
+// First our implementation, then later light wrappers around the alternatives
- template
- struct allocator_traits : std::allocator_traits {};
+#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0
- template
- struct rebind_wrap
- {
- typedef typename std::allocator_traits::
- template rebind_alloc type;
- };
+# include
+# include
+# include
+# if defined(BOOST_NO_SFINAE_EXPR)
+# include
+# endif
-#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
+# if defined(BOOST_UNORDERED_VARIADIC_MOVE) && \
+ !defined(BOOST_NO_SFINAE_EXPR)
+# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
+# else
+# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
+# endif
- template
- struct allocator_traits :
- boost::container::allocator_traits {};
-
- template
- struct rebind_wrap :
- boost::container::allocator_traits::
- template portable_rebind_alloc
- {};
-
-#else
+namespace boost { namespace unordered { namespace detail {
// TODO: Does this match std::allocator_traits::rebind_alloc?
template
struct rebind_wrap
{
- typedef typename Alloc::BOOST_NESTED_TEMPLATE rebind::other
- type;
+ typedef typename Alloc::BOOST_NESTED_TEMPLATE rebind::other type;
};
-#if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
+# if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
- #define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
- template \
- struct default_type_ ## tname { \
+# define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
+ template \
+ struct default_type_ ## tname { \
\
- template \
- static choice1::type test(choice1, typename X::tname* = 0); \
+ template \
+ static choice1::type test(choice1, typename X::tname* = 0); \
\
- template \
- static choice2::type test(choice2, void* = 0); \
+ template \
+ static choice2::type test(choice2, void* = 0); \
\
- struct DefaultWrap { typedef Default tname; }; \
+ struct DefaultWrap { typedef Default tname; }; \
\
- enum { value = (1 == sizeof(test(choose()))) }; \
+ enum { value = (1 == sizeof(test(choose()))) }; \
\
- typedef typename boost::detail::if_true:: \
- BOOST_NESTED_TEMPLATE then \
- ::type::tname type; \
- }
+ typedef typename boost::detail::if_true:: \
+ BOOST_NESTED_TEMPLATE then \
+ ::type::tname type; \
+ }
-#else
+# else
template
struct sfinae : T2 {};
- #define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
- template \
- struct default_type_ ## tname { \
+# define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
+ template \
+ struct default_type_ ## tname { \
\
- template \
- static typename boost::unordered::detail::sfinae< \
- typename X::tname, choice1>::type \
- test(choice1); \
+ template \
+ static typename boost::unordered::detail::sfinae< \
+ typename X::tname, choice1>::type \
+ test(choice1); \
\
- template \
- static choice2::type test(choice2); \
+ template \
+ static choice2::type test(choice2); \
\
- struct DefaultWrap { typedef Default tname; }; \
+ struct DefaultWrap { typedef Default tname; }; \
\
- enum { value = (1 == sizeof(test(choose()))) }; \
+ enum { value = (1 == sizeof(test(choose()))) }; \
\
- typedef typename boost::detail::if_true:: \
- BOOST_NESTED_TEMPLATE then \
- ::type::tname type; \
- }
+ typedef typename boost::detail::if_true:: \
+ BOOST_NESTED_TEMPLATE then \
+ ::type::tname type; \
+ }
-#endif
+# endif
- #define BOOST_UNORDERED_DEFAULT_TYPE(T,tname, arg) \
- typename default_type_ ## tname::type
+# define BOOST_UNORDERED_DEFAULT_TYPE(T,tname, arg) \
+ typename default_type_ ## tname::type
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(pointer);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_pointer);
@@ -313,7 +272,8 @@ namespace boost { namespace unordered { namespace detail {
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
-#if BOOST_UNORDERED_HAVE_CALL_DETECTION
+# if !defined(BOOST_NO_SFINAE_EXPR)
+
template
BOOST_UNORDERED_HAS_FUNCTION(
select_on_container_copy_construction, U const, (), 0
@@ -324,18 +284,33 @@ namespace boost { namespace unordered { namespace detail {
max_size, U const, (), 0
);
+# if defined(BOOST_UNORDERED_VARIADIC_MOVE)
+
+ template
+ BOOST_UNORDERED_HAS_FUNCTION(
+ construct, U, (
+ boost::unordered::detail::make(),
+ boost::unordered::detail::make()...), 2
+ );
+
+# else
+
template
BOOST_UNORDERED_HAS_FUNCTION(
- construct, U, (
- boost::unordered::detail::make(),
- boost::unordered::detail::make()), 2
+ construct, U, (
+ boost::unordered::detail::make(),
+ boost::unordered::detail::make()), 2
);
+# endif
+
template
BOOST_UNORDERED_HAS_FUNCTION(
destroy, U, (boost::unordered::detail::make()), 1
);
-#else
+
+# else
+
template
BOOST_UNORDERED_HAS_MEMBER(select_on_container_copy_construction);
@@ -347,7 +322,8 @@ namespace boost { namespace unordered { namespace detail {
template
BOOST_UNORDERED_HAS_MEMBER(destroy);
-#endif
+
+# endif
template
inline typename boost::enable_if_c<
@@ -415,7 +391,7 @@ namespace boost { namespace unordered { namespace detail {
// TODO: rebind_alloc and rebind_traits
- static pointer allocate(Alloc& a, size_type n)
+ static pointer allocate(Alloc& a, size_type n)
{ return a.allocate(n); }
// I never use this, so I'll just comment it out for now.
@@ -423,13 +399,49 @@ namespace boost { namespace unordered { namespace detail {
//static pointer allocate(Alloc& a, size_type n,
// const_void_pointer hint)
// { return DEFAULT_FUNC(allocate, pointer)(a, n, hint); }
-
+
static void deallocate(Alloc& a, pointer p, size_type n)
{ a.deallocate(p, n); }
public:
- // Only supporting the basic copy constructor for now.
+# if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+
+ template
+ static typename boost::enable_if_c<
+ boost::unordered::detail::has_construct
+ ::value>::type
+ construct(Alloc& a, T* p, Args&&... x)
+ {
+ a.construct(p, boost::forward(x)...);
+ }
+
+ template
+ static typename boost::disable_if_c<
+ boost::unordered::detail::has_construct
+ ::value>::type
+ construct(Alloc&, T* p, Args&&... x)
+ {
+ new ((void*) p) T(boost::forward(x)...);
+ }
+
+ template
+ static typename boost::enable_if_c<
+ boost::unordered::detail::has_destroy::value>::type
+ destroy(Alloc& a, T* p)
+ {
+ a.destroy(p);
+ }
+
+ template
+ static typename boost::disable_if_c<
+ boost::unordered::detail::has_destroy::value>::type
+ destroy(Alloc&, T* p)
+ {
+ boost::unordered::detail::destroy(p);
+ }
+
+# elif !defined(BOOST_NO_SFINAE_EXPR)
template
static typename boost::enable_if_c<
@@ -463,19 +475,67 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::destroy(p);
}
+# else
+
+ // If we don't have SFINAE expressions, only call construct for the
+ // copy constructor for the allocator's value_type - as that's
+ // the only construct method that old fashioned allocators support.
+
+ template
+ static typename boost::enable_if_c<
+ boost::unordered::detail::has_construct::value &&
+ boost::is_same::value
+ >::type
+ construct(Alloc& a, T* p, T const& x)
+ {
+ a.construct(p, x);
+ }
+
+ template
+ static typename boost::disable_if_c<
+ boost::unordered::detail::has_construct::value &&
+ boost::is_same::value
+ >::type
+ construct(Alloc&, T* p, T const& x)
+ {
+ new ((void*) p) T(x);
+ }
+
+ template
+ static typename boost::enable_if_c<
+ boost::unordered::detail::has_destroy::value &&
+ boost::is_same::value
+ >::type
+ destroy(Alloc& a, T* p)
+ {
+ a.destroy(p);
+ }
+
+ template
+ static typename boost::disable_if_c<
+ boost::unordered::detail::has_destroy::value &&
+ boost::is_same::value
+ >::type
+ destroy(Alloc&, T* p)
+ {
+ boost::unordered::detail::destroy(p);
+ }
+
+# endif
+
static size_type max_size(const Alloc& a)
{
return boost::unordered::detail::call_max_size(a);
}
// Allocator propagation on construction
-
+
static Alloc select_on_container_copy_construction(Alloc const& rhs)
{
return boost::unordered::detail::
call_select_on_container_copy_construction(rhs);
}
-
+
// Allocator propagation on assignment and swap.
// Return true if lhs is modified.
typedef BOOST_UNORDERED_DEFAULT_TYPE(
@@ -488,12 +548,117 @@ namespace boost { namespace unordered { namespace detail {
Alloc,propagate_on_container_swap,false_type)
propagate_on_container_swap;
};
+}}}
-#undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
-#undef BOOST_UNORDERED_DEFAULT_TYPE
+# undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
+# undef BOOST_UNORDERED_DEFAULT_TYPE
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// std::allocator_traits
+
+#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
+
+# include
+
+# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
+
+namespace boost { namespace unordered { namespace detail {
+
+ template
+ struct allocator_traits : std::allocator_traits {};
+
+ template
+ struct rebind_wrap
+ {
+ typedef typename std::allocator_traits::
+ template rebind_alloc type;
+ };
+}}}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// boost::container::allocator_traits
+
+#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
+
+# include
+
+# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
+
+namespace boost { namespace unordered { namespace detail {
+
+ template
+ struct allocator_traits :
+ boost::container::allocator_traits {};
+
+ template
+ struct rebind_wrap :
+ boost::container::allocator_traits::
+ template portable_rebind_alloc
+ {};
+
+}}}
+
+#else
+
+#error "Invalid BOOST_UNORDERED_USE_ALLOCATOR_TRAITS value."
#endif
+////////////////////////////////////////////////////////////////////////////////
+//
+// Some helper functions for allocating & constructing
+
+namespace boost { namespace unordered { namespace detail {
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // construct_node/destroy_node
+ //
+ // Construct a node using the best available method.
+
+#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+
+ template
+ inline void construct_node(Alloc& a, T* p, BOOST_UNORDERED_EMPLACE_ARGS)
+ {
+ boost::unordered::detail::allocator_traits::construct(
+ a, p, BOOST_UNORDERED_EMPLACE_FORWARD);
+ }
+
+ template
+ inline void destroy_node(Alloc& a, T* p)
+ {
+ boost::unordered::detail::allocator_traits::destroy(a, p);
+ }
+
+#else
+
+ template
+ inline void construct_node(Alloc& a, T* p, BOOST_UNORDERED_EMPLACE_ARGS)
+ {
+ boost::unordered::detail::allocator_traits::construct(a, p, T());
+ try {
+ boost::unordered::detail::construct_impl(
+ p->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
+ } catch(...) {
+ boost::unordered::detail::allocator_traits::destroy(a, p);
+ throw;
+ }
+ }
+
+ template
+ inline void destroy_node(Alloc& a, T* p)
+ {
+ boost::unordered::detail::destroy(p->value_ptr());
+ boost::unordered::detail::allocator_traits::destroy(a, p);
+ }
+
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
// array_constructor
//
// Allocate and construct an array in an exception safe manner, and
@@ -549,7 +714,9 @@ namespace boost { namespace unordered { namespace detail {
ptr_ = pointer();
return p;
}
+
private:
+
array_constructor(array_constructor const&);
array_constructor& operator=(array_constructor const&);
};
diff --git a/include/boost/unordered/detail/buckets.hpp b/include/boost/unordered/detail/buckets.hpp
index 9ee1343c..8f0054f3 100644
--- a/include/boost/unordered/detail/buckets.hpp
+++ b/include/boost/unordered/detail/buckets.hpp
@@ -13,7 +13,6 @@
#include
#include
-#include
#include
#include
#include
@@ -54,16 +53,14 @@ namespace boost { namespace unordered { namespace detail {
node_allocator& alloc_;
node_pointer node_;
- bool node_constructed_;
- bool value_constructed_;
+ bool constructed_;
public:
node_constructor(node_allocator& n) :
alloc_(n),
node_(),
- node_constructed_(false),
- value_constructed_(false)
+ constructed_(false)
{
}
@@ -74,26 +71,40 @@ namespace boost { namespace unordered { namespace detail {
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;
+ BOOST_ASSERT(node_ && !constructed_);
+ boost::unordered::detail::construct_node(alloc_,
+ boost::addressof(*node_), BOOST_UNORDERED_EMPLACE_FORWARD);
+ node_->init(static_cast(node_));
+ constructed_ = true;
}
template
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));
- value_constructed_ = true;
+ BOOST_ASSERT(node_ && !constructed_);
+# if defined(BOOST_UNORDERED_VARIADIC_MOVE)
+ boost::unordered::detail::construct_node(alloc_,
+ boost::addressof(*node_), boost::forward(a0));
+# else
+ boost::unordered::detail::construct_node(alloc_,
+ boost::addressof(*node_),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward(a0)));
+# endif
+ constructed_ = true;
+ node_->init(static_cast(node_));
}
value_type const& value() const {
- BOOST_ASSERT(node_ && node_constructed_ && value_constructed_);
+ BOOST_ASSERT(node_ && constructed_);
return node_->value();
}
+ node_pointer get()
+ {
+ return node_;
+ }
+
// no throw
node_pointer release()
{
@@ -111,12 +122,8 @@ namespace boost { namespace unordered { namespace detail {
node_constructor::~node_constructor()
{
if (node_) {
- if (value_constructed_) {
- boost::unordered::detail::destroy(node_->value_ptr());
- }
-
- if (node_constructed_) {
- node_allocator_traits::destroy(alloc_,
+ if (constructed_) {
+ boost::unordered::detail::destroy_node(alloc_,
boost::addressof(*node_));
}
@@ -128,24 +135,13 @@ namespace boost { namespace unordered { namespace detail {
void node_constructor::construct_node()
{
if(!node_) {
- node_constructed_ = false;
- value_constructed_ = false;
-
+ constructed_ = false;
node_ = node_allocator_traits::allocate(alloc_, 1);
-
- node_allocator_traits::construct(alloc_,
- boost::addressof(*node_), node());
- node_->init(static_cast(node_));
- node_constructed_ = true;
}
- else {
- BOOST_ASSERT(node_constructed_);
-
- if (value_constructed_)
- {
- boost::unordered::detail::destroy(node_->value_ptr());
- value_constructed_ = false;
- }
+ else if (constructed_) {
+ boost::unordered::detail::destroy_node(alloc_,
+ boost::addressof(*node_));
+ constructed_ = false;
}
}
@@ -183,6 +179,16 @@ namespace boost { namespace unordered { namespace detail {
enum { extra_node = false };
};
+
+ template
+ struct node_base
+ {
+ typedef LinkPointer link_pointer;
+ link_pointer next_;
+
+ node_base() : next_() {}
+ };
+
}}}
namespace boost { namespace unordered { namespace iterator_detail {
@@ -718,6 +724,14 @@ namespace boost { namespace unordered { namespace detail {
node_constructor a(this->node_alloc());
a.construct_node();
+ // Since this node is just to mark the beginning it doesn't
+ // contain a value, so just construct node::node_base
+ // which containers the pointer to the next element.
+ node_allocator_traits::construct(node_alloc(),
+ static_cast(
+ boost::addressof(*a.get())),
+ typename node::node_base());
+
(constructor.get() +
static_cast(this->bucket_count_))->next_ =
a.release();
@@ -762,9 +776,8 @@ namespace boost { namespace unordered { namespace detail {
inline void delete_node(c_iterator n)
{
- boost::unordered::detail::destroy(n.node_->value_ptr());
- node_allocator_traits::destroy(node_alloc(),
- boost::addressof(*n.node_));
+ boost::unordered::detail::destroy_node(
+ node_alloc(), boost::addressof(*n.node_));
node_allocator_traits::deallocate(node_alloc(), n.node_, 1);
--size_;
}
@@ -786,7 +799,8 @@ namespace boost { namespace unordered { namespace detail {
inline void delete_extra_node(bucket_pointer) {}
inline void delete_extra_node(node_pointer n) {
- node_allocator_traits::destroy(node_alloc(), boost::addressof(*n));
+ node_allocator_traits::destroy(node_alloc(),
+ static_cast(boost::addressof(*n)));
node_allocator_traits::deallocate(node_alloc(), n, 1);
}
@@ -847,22 +861,24 @@ namespace boost { namespace unordered { namespace detail {
// This is called after erasing a node or group of nodes to fix up
// the bucket pointers.
- void fix_buckets(bucket_pointer bucket,
+ void fix_buckets(bucket_pointer this_bucket,
previous_pointer prev, node_pointer next)
{
if (!next)
{
- if (bucket->next_ == prev) bucket->next_ = node_pointer();
+ if (this_bucket->next_ == prev)
+ this_bucket->next_ = node_pointer();
}
else
{
bucket_pointer next_bucket = this->get_bucket(
policy::to_bucket(this->bucket_count_, next->hash_));
- if (next_bucket != bucket)
+ if (next_bucket != this_bucket)
{
next_bucket->next_ = prev;
- if (bucket->next_ == prev) bucket->next_ = node_pointer();
+ if (this_bucket->next_ == prev)
+ this_bucket->next_ = node_pointer();
}
}
}
diff --git a/include/boost/unordered/detail/emplace_args.hpp b/include/boost/unordered/detail/emplace_args.hpp
index be2339fe..60b6cb9c 100644
--- a/include/boost/unordered/detail/emplace_args.hpp
+++ b/include/boost/unordered/detail/emplace_args.hpp
@@ -12,6 +12,7 @@
# pragma once
#endif
+#include
#include
#include
#include
@@ -21,7 +22,10 @@
#include
#include
#include
+#include
#include
+#include
+#include
#include
#if !defined(BOOST_NO_0X_HDR_TUPLE)
@@ -45,6 +49,38 @@
namespace boost { namespace unordered { namespace detail {
+ ////////////////////////////////////////////////////////////////////////////
+ // Bits and pieces for implementing traits
+
+ template typename boost::add_lvalue_reference::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
+ no_type is_private_type(T const&);
+ yes_type is_private_type(private_type const&);
+
+ struct convert_from_anything {
+ template
+ convert_from_anything(T const&);
+ };
+
////////////////////////////////////////////////////////////////////////////
// emplace_args
//
@@ -75,7 +111,7 @@ namespace boost { namespace unordered { namespace detail {
{ \
BOOST_PP_REPEAT_##z(n, BOOST_UNORDERED_EARGS_MEMBER, _) \
BOOST_PP_CAT(emplace_args, n) ( \
- BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, a) \
+ BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, b) \
) : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_EARGS_INIT, _) \
{} \
\
@@ -85,12 +121,12 @@ namespace boost { namespace unordered { namespace detail {
inline BOOST_PP_CAT(emplace_args, n) < \
BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
> create_emplace_args( \
- BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, b) \
) \
{ \
BOOST_PP_CAT(emplace_args, n) < \
BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
- > e(BOOST_PP_ENUM_PARAMS_Z(z, n, a)); \
+ > e(BOOST_PP_ENUM_PARAMS_Z(z, n, b)); \
return e; \
}
@@ -102,7 +138,7 @@ namespace boost { namespace unordered { namespace detail {
#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
BOOST_PP_CAT(a, n)( \
- boost::forward(BOOST_PP_CAT(a, n)))
+ boost::forward(BOOST_PP_CAT(b, n)))
#else
@@ -112,7 +148,7 @@ namespace boost { namespace unordered { namespace detail {
BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
- BOOST_PP_CAT(a, n)(BOOST_PP_CAT(a, n))
+ BOOST_PP_CAT(a, n)(BOOST_PP_CAT(b, n))
#endif
diff --git a/include/boost/unordered/detail/equivalent.hpp b/include/boost/unordered/detail/equivalent.hpp
index ba58c8a2..6df3c03a 100644
--- a/include/boost/unordered/detail/equivalent.hpp
+++ b/include/boost/unordered/detail/equivalent.hpp
@@ -12,7 +12,6 @@
#endif
#include
-#include
#include
namespace boost { namespace unordered { namespace detail {
@@ -23,20 +22,40 @@ namespace boost { namespace unordered { namespace detail {
template
struct grouped_node :
+ boost::unordered::detail::node_base<
+ typename ::boost::unordered::detail::rebind_wrap<
+ A, grouped_node >::type::pointer
+ >,
boost::unordered::detail::value_base
{
typedef typename ::boost::unordered::detail::rebind_wrap<
A, grouped_node >::type::pointer link_pointer;
+ typedef boost::unordered::detail::node_base node_base;
- link_pointer next_;
link_pointer group_prev_;
std::size_t hash_;
+#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+ template
+ grouped_node(BOOST_UNORDERED_EMPLACE_ARGS) :
+ node_base(),
+ group_prev_(),
+ hash_(0)
+ {
+ boost::unordered::detail::construct_impl(
+ this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
+ }
+
+ ~grouped_node() {
+ boost::unordered::detail::destroy(this->value_ptr());
+ }
+#else
grouped_node() :
- next_(),
+ node_base(),
group_prev_(),
hash_(0)
{}
+#endif
void init(link_pointer self)
{
@@ -50,16 +69,33 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::ptr_bucket
{
typedef boost::unordered::detail::ptr_bucket bucket_base;
+ typedef bucket_base node_base;
typedef ptr_bucket* link_pointer;
link_pointer group_prev_;
std::size_t hash_;
+#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+ template
+ grouped_ptr_node(BOOST_UNORDERED_EMPLACE_ARGS) :
+ bucket_base(),
+ group_prev_(0),
+ hash_(0)
+ {
+ boost::unordered::detail::construct_impl(
+ this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
+ }
+
+ ~grouped_ptr_node() {
+ boost::unordered::detail::destroy(this->value_ptr());
+ }
+#else
grouped_ptr_node() :
bucket_base(),
group_prev_(0),
hash_(0)
{}
+#endif
void init(link_pointer self)
{
@@ -221,12 +257,12 @@ namespace boost { namespace unordered { namespace detail {
template
iterator find_node_impl(
- std::size_t hash,
+ std::size_t key_hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index =
- policy::to_bucket(this->bucket_count_, hash);
+ policy::to_bucket(this->bucket_count_, key_hash);
iterator n = this->get_start(bucket_index);
for (;;)
@@ -234,7 +270,7 @@ namespace boost { namespace unordered { namespace detail {
if (!n.node_) return n;
std::size_t node_hash = n.node_->hash_;
- if (hash == node_hash)
+ if (key_hash == node_hash)
{
if (eq(k, this->get_key(*n)))
return n;
@@ -256,14 +292,14 @@ namespace boost { namespace unordered { namespace detail {
iterator n = this->find_node(k);
if (!n.node_) return 0;
- std::size_t count = 0;
+ std::size_t x = 0;
node_pointer it = n.node_;
do {
it = static_cast(it->group_prev_);
- ++count;
+ ++x;
} while(it != n.node_);
- return count;
+ return x;
}
std::pair
@@ -396,11 +432,11 @@ namespace boost { namespace unordered { namespace detail {
inline iterator add_node(
node_constructor& a,
- std::size_t hash,
+ std::size_t key_hash,
iterator pos)
{
node_pointer n = a.release();
- n->hash_ = hash;
+ n->hash_ = key_hash;
if (pos.node_) {
this->add_after_node(n, pos.node_);
if (n->next_) {
@@ -408,14 +444,14 @@ namespace boost { namespace unordered { namespace detail {
this->bucket_count_,
static_cast(n->next_)->hash_);
if (next_bucket !=
- policy::to_bucket(this->bucket_count_, hash)) {
+ policy::to_bucket(this->bucket_count_, key_hash)) {
this->get_bucket(next_bucket)->next_ = n;
}
}
}
else {
bucket_pointer b = this->get_bucket(
- policy::to_bucket(this->bucket_count_, hash));
+ policy::to_bucket(this->bucket_count_, key_hash));
if (!b->next_)
{
@@ -444,20 +480,20 @@ namespace boost { namespace unordered { namespace detail {
iterator emplace_impl(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
- std::size_t hash = this->hash(k);
- iterator position = this->find_node(hash, k);
+ std::size_t key_hash = this->hash(k);
+ iterator position = this->find_node(key_hash, k);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
- return this->add_node(a, hash, position);
+ return this->add_node(a, key_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(k);
- this->add_node(a, hash, this->find_node(hash, k));
+ std::size_t key_hash = this->hash(k);
+ this->add_node(a, key_hash, this->find_node(key_hash, k));
}
#if defined(BOOST_NO_RVALUE_REFERENCES)
@@ -531,12 +567,12 @@ namespace boost { namespace unordered { namespace detail {
{
if(!this->size_) return 0;
- std::size_t hash = this->hash(k);
+ std::size_t key_hash = this->hash(k);
std::size_t bucket_index =
- policy::to_bucket(this->bucket_count_, hash);
- bucket_pointer bucket = this->get_bucket(bucket_index);
+ policy::to_bucket(this->bucket_count_, key_hash);
+ bucket_pointer this_bucket = this->get_bucket(bucket_index);
- previous_pointer prev = bucket->next_;
+ previous_pointer prev = this_bucket->next_;
if (!prev) return 0;
for (;;)
@@ -547,7 +583,7 @@ namespace boost { namespace unordered { namespace detail {
if (policy::to_bucket(this->bucket_count_, node_hash)
!= bucket_index)
return 0;
- if (node_hash == hash &&
+ if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(
static_cast(prev->next_)->value())))
break;
@@ -560,7 +596,7 @@ namespace boost { namespace unordered { namespace detail {
static_cast(pos->group_prev_)->next_;
node_pointer end = static_cast(end1);
prev->next_ = end1;
- this->fix_buckets(bucket, prev, end);
+ this->fix_buckets(this_bucket, prev, end);
return this->delete_nodes(c_iterator(pos), c_iterator(end));
}
@@ -570,11 +606,11 @@ namespace boost { namespace unordered { namespace detail {
iterator next(r.node_);
++next;
- bucket_pointer bucket = this->get_bucket(
+ bucket_pointer this_bucket = this->get_bucket(
policy::to_bucket(this->bucket_count_, r.node_->hash_));
- previous_pointer prev = unlink_node(*bucket, r.node_);
+ previous_pointer prev = unlink_node(*this_bucket, r.node_);
- this->fix_buckets(bucket, prev, next.node_);
+ this->fix_buckets(this_bucket, prev, next.node_);
this->delete_node(r);
@@ -713,7 +749,7 @@ namespace boost { namespace unordered { namespace detail {
previous_pointer prev = dst.get_previous_start();
while (n.node_) {
- std::size_t hash = n.node_->hash_;
+ std::size_t key_hash = n.node_->hash_;
iterator group_end(
static_cast(
static_cast(n.node_->group_prev_)->next_
@@ -724,7 +760,7 @@ namespace boost { namespace unordered { namespace detail {
node_pointer first_node = a.release();
node_pointer end = first_node;
- first_node->hash_ = hash;
+ first_node->hash_ = key_hash;
prev->next_ = static_cast(first_node);
++dst.size_;
@@ -733,7 +769,7 @@ namespace boost { namespace unordered { namespace detail {
a.construct_node();
a.construct_value2(*n);
end = a.release();
- end->hash_ = hash;
+ end->hash_ = key_hash;
add_after_node(end, first_node);
++dst.size_;
}
@@ -760,7 +796,7 @@ namespace boost { namespace unordered { namespace detail {
previous_pointer prev = dst.get_previous_start();
while (n.node_) {
- std::size_t hash = n.node_->hash_;
+ std::size_t key_hash = n.node_->hash_;
iterator group_end(
static_cast(
static_cast(n.node_->group_prev_)->next_
@@ -771,7 +807,7 @@ namespace boost { namespace unordered { namespace detail {
node_pointer first_node = a.release();
node_pointer end = first_node;
- first_node->hash_ = hash;
+ first_node->hash_ = key_hash;
prev->next_ = static_cast(first_node);
++dst.size_;
@@ -780,7 +816,7 @@ namespace boost { namespace unordered { namespace detail {
a.construct_node();
a.construct_value2(boost::move(*n));
end = a.release();
- end->hash_ = hash;
+ end->hash_ = key_hash;
add_after_node(end, first_node);
++dst.size_;
}
diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp
index 9e2f13c5..cbf62195 100644
--- a/include/boost/unordered/detail/table.hpp
+++ b/include/boost/unordered/detail/table.hpp
@@ -348,21 +348,21 @@ namespace boost { namespace unordered { namespace detail {
template
iterator generic_find_node(
Key const& k,
- Hash const& hash_function,
+ Hash const& hf,
Pred const& eq) const
{
if (!this->size_) return iterator();
return static_cast(this)->
- find_node_impl(policy::apply_hash(hash_function, k), k, eq);
+ find_node_impl(policy::apply_hash(hf, k), k, eq);
}
iterator find_node(
- std::size_t hash,
+ std::size_t key_hash,
key_type const& k) const
{
if (!this->size_) return iterator();
return static_cast(this)->
- find_node_impl(hash, k, this->key_eq());
+ find_node_impl(key_hash, k, this->key_eq());
}
iterator find_node(key_type const& k) const
@@ -387,6 +387,7 @@ namespace boost { namespace unordered { namespace detail {
void reserve_for_insert(std::size_t);
void rehash(std::size_t);
+ void reserve(std::size_t);
};
////////////////////////////////////////////////////////////////////////////
@@ -402,7 +403,9 @@ namespace boost { namespace unordered { namespace detail {
this->create_buckets();
this->max_load_ = this->calculate_max_load();
}
- else if(size >= max_load_) {
+ // According to the standard this should be 'size >= max_load_',
+ // but I think this is better, defect report filed.
+ else if(size > max_load_) {
std::size_t num_buckets
= this->min_buckets_for_size((std::max)(size,
this->size_ + (this->size_ >> 1)));
@@ -417,7 +420,7 @@ namespace boost { namespace unordered { namespace detail {
// strong otherwise.
template
- void table::rehash(std::size_t min_buckets)
+ inline void table::rehash(std::size_t min_buckets)
{
using namespace std;
@@ -437,6 +440,13 @@ namespace boost { namespace unordered { namespace detail {
}
}
}
+
+ template
+ inline void table::reserve(std::size_t num_elements)
+ {
+ rehash(static_cast(
+ std::ceil(static_cast(num_elements) / this->mlf_)));
+ }
}}}
#endif
diff --git a/include/boost/unordered/detail/unique.hpp b/include/boost/unordered/detail/unique.hpp
index 84fef433..8628591e 100644
--- a/include/boost/unordered/detail/unique.hpp
+++ b/include/boost/unordered/detail/unique.hpp
@@ -12,31 +12,49 @@
#endif
#include
-#include
#include
#include
#include
namespace boost { namespace unordered { namespace detail {
- template struct node;
+ template struct unique_node;
template struct ptr_node;
template struct table_impl;
template
- struct node :
+ struct unique_node :
+ boost::unordered::detail::node_base<
+ typename ::boost::unordered::detail::rebind_wrap<
+ A, unique_node >::type::pointer
+ >,
boost::unordered::detail::value_base
{
typedef typename ::boost::unordered::detail::rebind_wrap<
- A, node >::type::pointer link_pointer;
+ A, unique_node >::type::pointer link_pointer;
+ typedef boost::unordered::detail::node_base node_base;
- link_pointer next_;
std::size_t hash_;
- node() :
- next_(),
+#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+ template
+ unique_node(BOOST_UNORDERED_EMPLACE_ARGS) :
+ node_base(),
+ hash_(0)
+ {
+ boost::unordered::detail::construct_impl(
+ this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
+ }
+
+ ~unique_node() {
+ boost::unordered::detail::destroy(this->value_ptr());
+ }
+#else
+ unique_node() :
+ node_base(),
hash_(0)
{}
+#endif
void init(link_pointer)
{
@@ -49,14 +67,30 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::ptr_bucket
{
typedef boost::unordered::detail::ptr_bucket bucket_base;
+ typedef bucket_base node_base;
typedef ptr_bucket* link_pointer;
std::size_t hash_;
+#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+ template
+ ptr_node(BOOST_UNORDERED_EMPLACE_ARGS) :
+ bucket_base(),
+ hash_(0)
+ {
+ boost::unordered::detail::construct_impl(
+ this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
+ }
+
+ ~ptr_node() {
+ boost::unordered::detail::destroy(this->value_ptr());
+ }
+#else
ptr_node() :
bucket_base(),
hash_(0)
{}
+#endif
void init(link_pointer)
{
@@ -69,7 +103,7 @@ namespace boost { namespace unordered { namespace detail {
template
struct pick_node2
{
- typedef boost::unordered::detail::node node;
+ typedef boost::unordered::detail::unique_node node;
typedef typename boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap::type
@@ -219,12 +253,12 @@ namespace boost { namespace unordered { namespace detail {
template
iterator find_node_impl(
- std::size_t hash,
+ std::size_t key_hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index =
- policy::to_bucket(this->bucket_count_, hash);
+ policy::to_bucket(this->bucket_count_, key_hash);
iterator n = this->get_start(bucket_index);
for (;;)
@@ -232,7 +266,7 @@ namespace boost { namespace unordered { namespace detail {
if (!n.node_) return n;
std::size_t node_hash = n.node_->hash_;
- if (hash == node_hash)
+ if (key_hash == node_hash)
{
if (eq(k, this->get_key(*n)))
return n;
@@ -300,13 +334,13 @@ namespace boost { namespace unordered { namespace detail {
inline iterator add_node(
node_constructor& a,
- std::size_t hash)
+ std::size_t key_hash)
{
node_pointer n = a.release();
- n->hash_ = hash;
+ n->hash_ = key_hash;
bucket_pointer b = this->get_bucket(
- policy::to_bucket(this->bucket_count_, hash));
+ policy::to_bucket(this->bucket_count_, key_hash));
if (!b->next_)
{
@@ -336,8 +370,8 @@ namespace boost { namespace unordered { namespace detail {
{
typedef typename value_type::second_type mapped_type;
- std::size_t hash = this->hash(k);
- iterator pos = this->find_node(hash, k);
+ std::size_t key_hash = this->hash(k);
+ iterator pos = this->find_node(key_hash, k);
if (pos.node_) return *pos;
@@ -357,7 +391,7 @@ namespace boost { namespace unordered { namespace detail {
#endif
this->reserve_for_insert(this->size_ + 1);
- return *add_node(a, hash);
+ return *add_node(a, key_hash);
}
#if defined(BOOST_NO_RVALUE_REFERENCES)
@@ -397,8 +431,8 @@ namespace boost { namespace unordered { namespace detail {
emplace_return emplace_impl(key_type const& k,
BOOST_UNORDERED_EMPLACE_ARGS)
{
- std::size_t hash = this->hash(k);
- iterator pos = this->find_node(hash, k);
+ std::size_t key_hash = this->hash(k);
+ iterator pos = this->find_node(key_hash, k);
if (pos.node_) return emplace_return(pos, false);
@@ -411,21 +445,21 @@ namespace boost { namespace unordered { namespace detail {
// 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);
+ return emplace_return(this->add_node(a, key_hash), true);
}
emplace_return emplace_impl_with_node(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
- std::size_t hash = this->hash(k);
- iterator pos = this->find_node(hash, k);
+ std::size_t key_hash = this->hash(k);
+ iterator pos = this->find_node(key_hash, k);
if (pos.node_) 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);
+ return emplace_return(this->add_node(a, key_hash), true);
}
template
@@ -481,12 +515,12 @@ namespace boost { namespace unordered { namespace detail {
void insert_range_empty(node_constructor& a, key_type const& k,
InputIt i, InputIt j)
{
- std::size_t hash = this->hash(k);
+ std::size_t key_hash = this->hash(k);
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);
+ this->add_node(a, key_hash);
}
template
@@ -494,19 +528,19 @@ namespace boost { namespace unordered { namespace detail {
InputIt i, InputIt j)
{
// No side effects in this initial code
- std::size_t hash = this->hash(k);
- iterator pos = this->find_node(hash, k);
+ std::size_t key_hash = this->hash(k);
+ iterator pos = this->find_node(key_hash, k);
if (!pos.node_) {
a.construct_node();
a.construct_value2(*i);
- if(this->size_ + 1 >= this->max_load_)
+ 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.
- this->add_node(a, hash);
+ this->add_node(a, key_hash);
}
}
@@ -531,12 +565,12 @@ namespace boost { namespace unordered { namespace detail {
{
if(!this->size_) return 0;
- std::size_t hash = this->hash(k);
+ std::size_t key_hash = this->hash(k);
std::size_t bucket_index =
- policy::to_bucket(this->bucket_count_, hash);
- bucket_pointer bucket = this->get_bucket(bucket_index);
+ policy::to_bucket(this->bucket_count_, key_hash);
+ bucket_pointer this_bucket = this->get_bucket(bucket_index);
- previous_pointer prev = bucket->next_;
+ previous_pointer prev = this_bucket->next_;
if (!prev) return 0;
for (;;)
@@ -547,7 +581,7 @@ namespace boost { namespace unordered { namespace detail {
if (policy::to_bucket(this->bucket_count_, node_hash)
!= bucket_index)
return 0;
- if (node_hash == hash &&
+ if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(
static_cast(prev->next_)->value())))
break;
@@ -557,7 +591,7 @@ namespace boost { namespace unordered { namespace detail {
node_pointer pos = static_cast(prev->next_);
node_pointer end = static_cast(pos->next_);
prev->next_ = pos->next_;
- this->fix_buckets(bucket, prev, end);
+ this->fix_buckets(this_bucket, prev, end);
return this->delete_nodes(c_iterator(pos), c_iterator(end));
}
@@ -567,11 +601,11 @@ namespace boost { namespace unordered { namespace detail {
iterator next(r.node_);
++next;
- bucket_pointer bucket = this->get_bucket(
+ bucket_pointer this_bucket = this->get_bucket(
policy::to_bucket(this->bucket_count_, r.node_->hash_));
- previous_pointer prev = unlink_node(*bucket, r.node_);
+ previous_pointer prev = unlink_node(*this_bucket, r.node_);
- this->fix_buckets(bucket, prev, next.node_);
+ this->fix_buckets(this_bucket, prev, next.node_);
this->delete_node(r);
diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp
index 7378b913..8e6621d4 100644
--- a/include/boost/unordered/unordered_map.hpp
+++ b/include/boost/unordered/unordered_map.hpp
@@ -515,6 +515,7 @@ namespace unordered
float load_factor() const;
void max_load_factor(float);
void rehash(size_type);
+ void reserve(size_type);
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
friend bool operator==(
@@ -997,6 +998,7 @@ namespace unordered
float load_factor() const;
void max_load_factor(float);
void rehash(size_type);
+ void reserve(size_type);
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
friend bool operator==(
@@ -1300,6 +1302,12 @@ namespace unordered
table_.rehash(n);
}
+ template
+ void unordered_map::reserve(size_type n)
+ {
+ table_.reserve(n);
+ }
+
template
inline bool operator==(
unordered_map const& m1,
@@ -1606,6 +1614,12 @@ namespace unordered
table_.rehash(n);
}
+ template
+ void unordered_multimap::reserve(size_type n)
+ {
+ table_.reserve(n);
+ }
+
template
inline bool operator==(
unordered_multimap const& m1,
diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp
index 1d56c777..a85a1676 100644
--- a/include/boost/unordered/unordered_set.hpp
+++ b/include/boost/unordered/unordered_set.hpp
@@ -500,6 +500,7 @@ namespace unordered
float load_factor() const;
void max_load_factor(float);
void rehash(size_type);
+ void reserve(size_type);
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
friend bool operator==(
@@ -972,6 +973,7 @@ namespace unordered
float load_factor() const;
void max_load_factor(float);
void rehash(size_type);
+ void reserve(size_type);
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
friend bool operator==(
@@ -1226,6 +1228,12 @@ namespace unordered
table_.rehash(n);
}
+ template
+ void unordered_set::reserve(size_type n)
+ {
+ table_.reserve(n);
+ }
+
template
inline bool operator==(
unordered_set const& m1,
@@ -1504,6 +1512,12 @@ namespace unordered
table_.rehash(n);
}
+ template
+ void unordered_multiset