summaryrefslogtreecommitdiff
path: root/boost/unordered
diff options
context:
space:
mode:
authorChanho Park <chanho61.park@samsung.com>2014-12-11 18:55:56 +0900
committerChanho Park <chanho61.park@samsung.com>2014-12-11 18:55:56 +0900
commit08c1e93fa36a49f49325a07fe91ff92c964c2b6c (patch)
tree7a7053ceb8874b28ec4b868d4c49b500008a102e /boost/unordered
parentbb4dd8289b351fae6b55e303f189127a394a1edd (diff)
downloadboost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.gz
boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.bz2
boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.zip
Imported Upstream version 1.57.0upstream/1.57.0
Diffstat (limited to 'boost/unordered')
-rw-r--r--boost/unordered/detail/allocate.hpp698
-rw-r--r--boost/unordered/detail/buckets.hpp1124
-rw-r--r--boost/unordered/detail/equivalent.hpp479
-rw-r--r--boost/unordered/detail/extract_key.hpp80
-rw-r--r--boost/unordered/detail/fwd.hpp6
-rw-r--r--boost/unordered/detail/table.hpp731
-rw-r--r--boost/unordered/detail/unique.hpp326
-rw-r--r--boost/unordered/detail/util.hpp10
-rw-r--r--boost/unordered/unordered_map.hpp147
-rw-r--r--boost/unordered/unordered_map_fwd.hpp6
-rw-r--r--boost/unordered/unordered_set.hpp147
-rw-r--r--boost/unordered/unordered_set_fwd.hpp6
12 files changed, 1779 insertions, 1981 deletions
diff --git a/boost/unordered/detail/allocate.hpp b/boost/unordered/detail/allocate.hpp
index 5574c15855..4c20b168ab 100644
--- a/boost/unordered/detail/allocate.hpp
+++ b/boost/unordered/detail/allocate.hpp
@@ -9,8 +9,9 @@
#ifndef BOOST_UNORDERED_ALLOCATE_HPP
#define BOOST_UNORDERED_ALLOCATE_HPP
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
+#include <boost/config.hpp>
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#pragma once
#endif
#include <boost/unordered/detail/fwd.hpp>
@@ -85,7 +86,7 @@ namespace boost { namespace unordered { namespace detail {
// Either forwarding variadic arguments, or storing the arguments in
// emplace_args##n
-#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename... Args
#define BOOST_UNORDERED_EMPLACE_ARGS BOOST_FWD_REF(Args)... args
@@ -136,7 +137,7 @@ namespace boost { namespace unordered { namespace detail {
#define BOOST_UNORDERED_EMPLACE_ARGS2 create_emplace_args
#define BOOST_UNORDERED_EMPLACE_ARGS3 create_emplace_args
-#if defined(BOOST_NO_RVALUE_REFERENCES)
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(Arg, n); \
@@ -167,347 +168,6 @@ BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS,
#endif
- ////////////////////////////////////////////////////////////////////////////
- // rvalue parameters when type can't be a BOOST_RV_REF(T) parameter
- // e.g. for int
-
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
-# define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T)
-#else
- struct please_ignore_this_overload {
- typedef please_ignore_this_overload type;
- };
-
- template <typename T>
- struct rv_ref_impl {
- typedef BOOST_RV_REF(T) type;
- };
-
- template <typename T>
- struct rv_ref :
- boost::detail::if_true<
- boost::is_class<T>::value
- >::BOOST_NESTED_TEMPLATE then <
- boost::unordered::detail::rv_ref_impl<T>,
- please_ignore_this_overload
- >::type
- {};
-
-# define BOOST_UNORDERED_RV_REF(T) \
- typename boost::unordered::detail::rv_ref<T>::type
-#endif
-
- ////////////////////////////////////////////////////////////////////////////
- // Construct from tuple
- //
- // Used for piecewise construction.
-
-#if !defined(__SUNPRO_CC)
-
-# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
- template<typename T> \
- void construct_from_tuple(T* ptr, namespace_ tuple<>) \
- { \
- new ((void*) ptr) T(); \
- } \
- \
- BOOST_PP_REPEAT_FROM_TO(1, n, \
- BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
-
-# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
- template<typename T, BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
- void construct_from_tuple(T* ptr, \
- namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
- { \
- new ((void*) ptr) T( \
- BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
- ); \
- }
-
-# define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
- namespace_ get<n>(x)
-
-#else
-
- template <int N> struct length {};
-
-# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
- template<typename T> \
- void construct_from_tuple_impl( \
- boost::unordered::detail::length<0>, T* ptr, \
- namespace_ tuple<>) \
- { \
- new ((void*) ptr) T(); \
- } \
- \
- BOOST_PP_REPEAT_FROM_TO(1, n, \
- BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
-
-# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
- template<typename T, BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
- void construct_from_tuple_impl( \
- boost::unordered::detail::length<n>, T* ptr, \
- namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
- { \
- new ((void*) ptr) T( \
- BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
- ); \
- }
-
-# define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
- namespace_ get<n>(x)
-
-#endif
-
-BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
-
-#if !defined(__SUNPRO_CC) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
- BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::)
-#endif
-
-#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
-#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL
-#undef BOOST_UNORDERED_GET_TUPLE_ARG
-
-#if defined(__SUNPRO_CC)
-
- template <typename T, typename Tuple>
- void construct_from_tuple(T* ptr, Tuple const& x)
- {
- construct_from_tuple_impl(
- boost::unordered::detail::length<
- boost::tuples::length<Tuple>::value>(),
- ptr, x);
- }
-
-#endif
-
- ////////////////////////////////////////////////////////////////////////////
- // SFINAE traits for construction.
-
- // Decide which construction method to use for a three argument
- // call. Note that this is difficult to do using overloads because
- // the arguments are packed into 'emplace_args3'.
- //
- // The decision is made on the first argument.
-
-
-#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
- template <typename A, typename B, typename A0>
- struct emulation1 {
- static choice1::type test(choice1, std::pair<A, B> const&);
- static choice2::type test(choice2, A const&);
- static choice3::type test(choice3, convert_from_anything const&);
-
- enum { value =
- sizeof(test(choose(), boost::unordered::detail::make<A0>())) ==
- sizeof(choice2::type) };
- };
-#endif
-
- template <typename A, typename B, typename A0>
- struct check3_base {
- static choice1::type test(choice1,
- boost::unordered::piecewise_construct_t);
-
-#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
- static choice2::type test(choice2, A const&);
-#endif
-
- static choice3::type test(choice3, ...);
-
- enum { value =
- sizeof(test(choose(), boost::unordered::detail::make<A0>())) };
- };
-
- template <typename A, typename B, typename A0>
- struct piecewise3 {
- enum { value = check3_base<A,B,A0>::value == sizeof(choice1::type) };
- };
-
-#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
- template <typename A, typename B, typename A0>
- struct emulation3 {
- enum { value = check3_base<A,B,A0>::value == sizeof(choice2::type) };
- };
-
-#endif
-
-#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
-
- ////////////////////////////////////////////////////////////////////////////
- // Construct from variadic parameters
-
- template <typename T, typename... Args>
- inline void construct_impl(T* address, BOOST_FWD_REF(Args)... args)
- {
- new((void*) address) T(boost::forward<Args>(args)...);
- }
-
- template <typename A, typename B, typename A0, typename A1, typename A2>
- inline typename enable_if<piecewise3<A, B, A0>, void>::type
- construct_impl(std::pair<A, B>* address,
- BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
- {
- boost::unordered::detail::construct_from_tuple(
- boost::addressof(address->first), boost::forward<A1>(a1));
- boost::unordered::detail::construct_from_tuple(
- boost::addressof(address->second), boost::forward<A2>(a2));
- }
-
-#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
-
- template <typename A, typename B, typename A0>
- inline typename enable_if<emulation1<A, B, A0>, void>::type
- construct_impl(std::pair<A, B>* address, BOOST_FWD_REF(A0) a0)
- {
- new((void*) boost::addressof(address->first)) A(boost::forward<A0>(a0));
- new((void*) boost::addressof(address->second)) B();
- }
-
- template <typename A, typename B, typename A0, typename A1, typename A2>
- inline typename enable_if<emulation3<A, B, A0>, void>::type
- construct_impl(std::pair<A, B>* address,
- BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
- {
- new((void*) boost::addressof(address->first)) A(boost::forward<A0>(a0));
- new((void*) boost::addressof(address->second)) B(
- boost::forward<A1>(a1),
- boost::forward<A2>(a2));
- }
-
- template <typename A, typename B,
- typename A0, typename A1, typename A2, typename A3,
- typename... Args>
- inline void construct_impl(std::pair<A, B>* address,
- BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2,
- BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(Args)... args)
- {
- new((void*) boost::addressof(address->first)) A(boost::forward<A0>(a0));
-
- new((void*) boost::addressof(address->second)) B(
- boost::forward<A1>(a1),
- boost::forward<A2>(a2),
- boost::forward<A3>(a3),
- boost::forward<Args>(args)...);
- }
-
-#endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
-
-#else // BOOST_NO_VARIADIC_TEMPLATES
-
-////////////////////////////////////////////////////////////////////////////////
-// Construct from emplace_args
-
-#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
- template < \
- typename T, \
- BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
- > \
- inline void construct_impl(T* address, \
- boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \
- BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
- > const& args) \
- { \
- new((void*) address) T( \
- BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD, \
- args.a)); \
- }
-
- template <typename T, typename A0>
- inline void construct_impl(T* address, emplace_args1<A0> const& args)
- {
- new((void*) address) T(boost::forward<A0>(args.a0));
- }
-
- template <typename T, typename A0, typename A1>
- inline void construct_impl(T* address, emplace_args2<A0, A1> const& args)
- {
- new((void*) address) T(
- boost::forward<A0>(args.a0),
- boost::forward<A1>(args.a1)
- );
- }
-
- template <typename T, typename A0, typename A1, typename A2>
- inline void construct_impl(T* address, emplace_args3<A0, A1, A2> const& args)
- {
- new((void*) address) T(
- boost::forward<A0>(args.a0),
- boost::forward<A1>(args.a1),
- boost::forward<A2>(args.a2)
- );
- }
-
- BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_CONSTRUCT_IMPL, _)
-
-#undef BOOST_UNORDERED_CONSTRUCT_IMPL
-
- template <typename A, typename B, typename A0, typename A1, typename A2>
- inline void construct_impl(std::pair<A, B>* address,
- boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
- typename enable_if<piecewise3<A, B, A0>, void*>::type = 0)
- {
- boost::unordered::detail::construct_from_tuple(
- boost::addressof(address->first), args.a1);
- boost::unordered::detail::construct_from_tuple(
- boost::addressof(address->second), args.a2);
- }
-
-#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
-
- template <typename A, typename B, typename A0>
- inline void construct_impl(std::pair<A, B>* address,
- boost::unordered::detail::emplace_args1<A0> const& args,
- typename enable_if<emulation1<A, B, A0>, void*>::type = 0)
- {
- new((void*) boost::addressof(address->first)) A(
- boost::forward<A0>(args.a0));
- new((void*) boost::addressof(address->second)) B();
- }
-
- template <typename A, typename B, typename A0, typename A1, typename A2>
- inline void construct_impl(std::pair<A, B>* address,
- boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
- typename enable_if<emulation3<A, B, A0>, void*>::type = 0)
- {
- new((void*) boost::addressof(address->first)) A(
- boost::forward<A0>(args.a0));
- new((void*) boost::addressof(address->second)) B(
- boost::forward<A1>(args.a1),
- boost::forward<A2>(args.a2));
- }
-
-#define BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(z, num_params, _) \
- template <typename A, typename B, \
- BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
- > \
- inline void construct_impl(std::pair<A, B>* address, \
- boost::unordered::detail::BOOST_PP_CAT(emplace_args, num_params) < \
- BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
- > const& args) \
- { \
- new((void*) boost::addressof(address->first)) A( \
- boost::forward<A0>(args.a0)); \
- new((void*) boost::addressof(address->second)) B( \
- BOOST_PP_ENUM_##z(BOOST_PP_DEC(num_params), \
- BOOST_UNORDERED_CALL_FORWARD2, args.a)); \
- }
-
-#define BOOST_UNORDERED_CALL_FORWARD2(z, i, a) \
- BOOST_UNORDERED_CALL_FORWARD(z, BOOST_PP_INC(i), a)
-
- BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(1, 2, _)
- BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
- BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL, _)
-
-#undef BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL
-#undef BOOST_UNORDERED_CALL_FORWARD2
-
-#endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
-#endif // BOOST_NO_VARIADIC_TEMPLATES
-
}}}
////////////////////////////////////////////////////////////////////////////////
@@ -575,9 +235,11 @@ namespace boost { namespace unordered { namespace detail {
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
- template <class T>
- inline void destroy(T* x) {
- x->~T();
+ namespace func {
+ template <class T>
+ inline void destroy(T* x) {
+ x->~T();
+ }
}
#if defined(BOOST_MSVC)
@@ -598,13 +260,12 @@ namespace boost { namespace unordered { namespace detail {
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(( \
+ sizeof(for_expr_test(( \
(expression), \
0)))>::type test( \
BOOST_PP_CAT(choice, count))
@@ -617,6 +278,7 @@ namespace boost { namespace unordered { namespace detail {
# define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
struct BOOST_PP_CAT(has_, name) \
{ \
+ template <typename U> static char for_expr_test(U const&); \
BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \
boost::unordered::detail::make< thing >().name args); \
BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
@@ -683,7 +345,7 @@ namespace boost { namespace unordered { namespace detail {
# include <boost/type_traits/is_same.hpp>
# endif
-# if !defined(BOOST_NO_VARIADIC_TEMPLATES) && \
+# if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_NO_SFINAE_EXPR)
# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
# else
@@ -773,7 +435,7 @@ namespace boost { namespace unordered { namespace detail {
max_size, U const, (), 0
);
-# if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+# if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename T, typename ValueType, typename... Args>
BOOST_UNORDERED_HAS_FUNCTION(
@@ -814,6 +476,9 @@ namespace boost { namespace unordered { namespace detail {
# endif
+ namespace func
+ {
+
template <typename Alloc>
inline Alloc call_select_on_container_copy_construction(const Alloc& rhs,
typename boost::enable_if_c<
@@ -851,6 +516,8 @@ namespace boost { namespace unordered { namespace detail {
return (std::numeric_limits<SizeType>::max)();
}
+ } // namespace func.
+
template <typename Alloc>
struct allocator_traits
{
@@ -930,7 +597,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
destroy(Alloc&, T* p)
{
- boost::unordered::detail::destroy(p);
+ boost::unordered::detail::func::destroy(p);
}
# elif !defined(BOOST_NO_SFINAE_EXPR)
@@ -964,7 +631,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
destroy(Alloc&, T* p)
{
- boost::unordered::detail::destroy(p);
+ boost::unordered::detail::func::destroy(p);
}
# else
@@ -1010,21 +677,22 @@ namespace boost { namespace unordered { namespace detail {
boost::is_same<T, value_type>::value,
void*>::type = 0)
{
- boost::unordered::detail::destroy(p);
+ boost::unordered::detail::func::destroy(p);
}
# endif
static size_type max_size(const Alloc& a)
{
- return boost::unordered::detail::call_max_size<size_type>(a);
+ return boost::unordered::detail::func::
+ call_max_size<size_type>(a);
}
// Allocator propagation on construction
static Alloc select_on_container_copy_construction(Alloc const& rhs)
{
- return boost::unordered::detail::
+ return boost::unordered::detail::func::
call_select_on_container_copy_construction(rhs);
}
@@ -1098,81 +766,292 @@ namespace boost { namespace unordered { namespace detail {
#endif
-////////////////////////////////////////////////////////////////////////////////
-//
-// Some helper functions for allocating & constructing
-namespace boost { namespace unordered { namespace detail {
+namespace boost { namespace unordered { namespace detail { namespace func {
////////////////////////////////////////////////////////////////////////////
- //
- // construct_node/destroy_node
- //
- // Construct a node using the best available method.
+ // call_construct
-#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- template <typename Alloc, typename T, BOOST_UNORDERED_EMPLACE_TEMPLATE>
- inline void construct_node(Alloc& a, T* p, BOOST_UNORDERED_EMPLACE_ARGS)
+# if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+
+ template <typename Alloc, typename T, typename... Args>
+ inline void call_construct(Alloc& alloc, T* address,
+ BOOST_FWD_REF(Args)... args)
{
- boost::unordered::detail::allocator_traits<Alloc>::construct(
- a, p, BOOST_UNORDERED_EMPLACE_FORWARD);
+ boost::unordered::detail::allocator_traits<Alloc>::construct(alloc,
+ address, boost::forward<Args>(args)...);
}
template <typename Alloc, typename T>
- inline void destroy_node(Alloc& a, T* p)
+ inline void destroy_value_impl(Alloc& alloc, T* x) {
+ boost::unordered::detail::allocator_traits<Alloc>::destroy(alloc, x);
+ }
+
+
+# else
+
+ template <typename Alloc, typename T, typename... Args>
+ inline void call_construct(Alloc&, T* address,
+ BOOST_FWD_REF(Args)... args)
{
- boost::unordered::detail::allocator_traits<Alloc>::destroy(a, p);
+ new((void*) address) T(boost::forward<Args>(args)...);
+ }
+
+ template <typename Alloc, typename T>
+ inline void destroy_value_impl(Alloc&, T* x) {
+ boost::unordered::detail::func::destroy(x);
+ }
+
+
+# endif
+
+#else
+
+ template <typename Alloc, typename T>
+ inline void destroy_value_impl(Alloc&, T* x) {
+ boost::unordered::detail::func::destroy(x);
+ }
+
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Construct from tuple
+ //
+ // Used for piecewise construction.
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
+ template<typename Alloc, typename T> \
+ void construct_from_tuple(Alloc& alloc, T* ptr, namespace_ tuple<>) \
+ { \
+ boost::unordered::detail::func::call_construct(alloc, ptr); \
+ } \
+ \
+ BOOST_PP_REPEAT_FROM_TO(1, n, \
+ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
+
+# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
+ template<typename Alloc, typename T, \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
+ void construct_from_tuple(Alloc& alloc, T* ptr, \
+ namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
+ { \
+ boost::unordered::detail::func::call_construct(alloc, ptr, \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
+ ); \
}
+# define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
+ namespace_ get<n>(x)
+
+#elif !defined(__SUNPRO_CC)
+
+# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
+ template<typename Alloc, typename T> \
+ void construct_from_tuple(Alloc&, T* ptr, namespace_ tuple<>) \
+ { \
+ new ((void*) ptr) T(); \
+ } \
+ \
+ BOOST_PP_REPEAT_FROM_TO(1, n, \
+ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
+
+# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
+ template<typename Alloc, typename T, \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
+ void construct_from_tuple(Alloc&, T* ptr, \
+ namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
+ { \
+ new ((void*) ptr) T( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
+ ); \
+ }
+
+# define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
+ namespace_ get<n>(x)
+
#else
- template <typename AllocTraits, typename T>
- struct value_construct
+ template <int N> struct length {};
+
+# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
+ template<typename Alloc, typename T> \
+ void construct_from_tuple_impl( \
+ boost::unordered::detail::func::length<0>, Alloc&, T* ptr, \
+ namespace_ tuple<>) \
+ { \
+ new ((void*) ptr) T(); \
+ } \
+ \
+ BOOST_PP_REPEAT_FROM_TO(1, n, \
+ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
+
+# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
+ template<typename Alloc, typename T, \
+ BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
+ void construct_from_tuple_impl( \
+ boost::unordered::detail::func::length<n>, Alloc&, T* ptr, \
+ namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
+ { \
+ new ((void*) ptr) T( \
+ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
+ ); \
+ }
+
+# define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
+ namespace_ get<n>(x)
+
+#endif
+
+BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
+
+#if !defined(__SUNPRO_CC) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
+ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::)
+#endif
+
+#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
+#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL
+#undef BOOST_UNORDERED_GET_TUPLE_ARG
+
+#if defined(__SUNPRO_CC)
+
+ template <typename Alloc, typename T, typename Tuple>
+ void construct_from_tuple(Alloc& alloc, T* ptr, Tuple const& x)
{
- typedef BOOST_DEDUCED_TYPENAME AllocTraits::allocator_type allocator;
+ construct_from_tuple_impl(
+ boost::unordered::detail::func::length<
+ boost::tuples::length<Tuple>::value>(),
+ alloc, ptr, x);
+ }
- allocator& alloc;
- T* ptr;
+#endif
- value_construct(allocator& a, T* p) : alloc(a), ptr(p)
- {
- AllocTraits::construct(alloc, ptr, T());
- }
+ ////////////////////////////////////////////////////////////////////////////
+ // Trait to check for piecewise construction.
- void release()
- {
- ptr = 0;
- }
+ template <typename A0>
+ struct use_piecewise {
+ static choice1::type test(choice1,
+ boost::unordered::piecewise_construct_t);
- ~value_construct()
- {
- if (ptr) AllocTraits::destroy(alloc, ptr);
- }
+ static choice2::type test(choice2, ...);
- private:
- value_construct(value_construct const&);
- value_construct& operator=(value_construct const&);
+ enum { value = sizeof(choice1::type) ==
+ sizeof(test(choose(), boost::unordered::detail::make<A0>())) };
};
- template <typename Alloc, typename T, BOOST_UNORDERED_EMPLACE_TEMPLATE>
- inline void construct_node(Alloc& a, T* p, BOOST_UNORDERED_EMPLACE_ARGS)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Construct from variadic parameters
+
+ // For the standard pair constructor.
+
+ template <typename Alloc, typename T, typename... Args>
+ inline void construct_value_impl(Alloc& alloc, T* address,
+ BOOST_FWD_REF(Args)... args)
{
- value_construct<boost::unordered::detail::allocator_traits<Alloc>, T>
- construct_guard(a, p);
- boost::unordered::detail::construct_impl(
- p->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
- construct_guard.release();
+ boost::unordered::detail::func::call_construct(alloc,
+ address, boost::forward<Args>(args)...);
}
- template <typename Alloc, typename T>
- inline void destroy_node(Alloc& a, T* p)
+ // Special case for piece_construct
+ //
+ // TODO: When possible, it might be better to use std::pair's
+ // constructor for std::piece_construct with std::tuple.
+
+ template <typename Alloc, typename A, typename B,
+ typename A0, typename A1, typename A2>
+ inline typename enable_if<use_piecewise<A0>, void>::type
+ construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
+ BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
- boost::unordered::detail::destroy(p->value_ptr());
- boost::unordered::detail::allocator_traits<Alloc>::destroy(a, p);
+ boost::unordered::detail::func::construct_from_tuple(alloc,
+ boost::addressof(address->first), boost::forward<A1>(a1));
+ boost::unordered::detail::func::construct_from_tuple(alloc,
+ boost::addressof(address->second), boost::forward<A2>(a2));
}
-#endif
+#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+////////////////////////////////////////////////////////////////////////////////
+// Construct from emplace_args
+
+ // Explicitly write out first three overloads for the sake of sane
+ // error messages.
+
+ template <typename Alloc, typename T, typename A0>
+ inline void construct_value_impl(Alloc&, T* address,
+ emplace_args1<A0> const& args)
+ {
+ new((void*) address) T(boost::forward<A0>(args.a0));
+ }
+
+ template <typename Alloc, typename T, typename A0, typename A1>
+ inline void construct_value_impl(Alloc&, T* address,
+ emplace_args2<A0, A1> const& args)
+ {
+ new((void*) address) T(
+ boost::forward<A0>(args.a0),
+ boost::forward<A1>(args.a1)
+ );
+ }
+
+ template <typename Alloc, typename T, typename A0, typename A1, typename A2>
+ inline void construct_value_impl(Alloc&, T* address,
+ emplace_args3<A0, A1, A2> const& args)
+ {
+ new((void*) address) T(
+ boost::forward<A0>(args.a0),
+ boost::forward<A1>(args.a1),
+ boost::forward<A2>(args.a2)
+ );
+ }
+
+ // Use a macro for the rest.
+
+#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
+ template < \
+ typename Alloc, typename T, \
+ BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
+ > \
+ inline void construct_value_impl(Alloc&, T* address, \
+ boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \
+ BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
+ > const& args) \
+ { \
+ new((void*) address) T( \
+ BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD, \
+ args.a)); \
+ }
+
+ BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
+ BOOST_UNORDERED_CONSTRUCT_IMPL, _)
+
+#undef BOOST_UNORDERED_CONSTRUCT_IMPL
+
+ // Construct with piece_construct
+
+ template <typename Alloc, typename A, typename B,
+ typename A0, typename A1, typename A2>
+ inline void construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
+ boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
+ typename enable_if<use_piecewise<A0>, void*>::type = 0)
+ {
+ boost::unordered::detail::func::construct_from_tuple(alloc,
+ boost::addressof(address->first), args.a1);
+ boost::unordered::detail::func::construct_from_tuple(alloc,
+ boost::addressof(address->second), args.a2);
+ }
+
+#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+}}}}
+
+namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////////
//
@@ -1202,8 +1081,10 @@ namespace boost { namespace unordered { namespace detail {
~array_constructor() {
if (ptr_) {
- for(pointer p = ptr_; p != constructed_; ++p)
- traits::destroy(alloc_, boost::addressof(*p));
+ for(pointer p = ptr_; p != constructed_; ++p) {
+ boost::unordered::detail::func::destroy(
+ boost::addressof(*p));
+ }
traits::deallocate(alloc_, ptr_, length_);
}
@@ -1216,8 +1097,9 @@ namespace boost { namespace unordered { namespace detail {
length_ = l;
ptr_ = traits::allocate(alloc_, length_);
pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
- for(constructed_ = ptr_; constructed_ != end; ++constructed_)
- traits::construct(alloc_, boost::addressof(*constructed_), v);
+ for(constructed_ = ptr_; constructed_ != end; ++constructed_) {
+ new ((void*) boost::addressof(*constructed_)) V(v);
+ }
}
pointer get() const
diff --git a/boost/unordered/detail/buckets.hpp b/boost/unordered/detail/buckets.hpp
index 85681a685c..7de4317b5a 100644
--- a/boost/unordered/detail/buckets.hpp
+++ b/boost/unordered/detail/buckets.hpp
@@ -7,186 +7,36 @@
#ifndef BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
+#include <boost/config.hpp>
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#pragma once
#endif
#include <boost/unordered/detail/util.hpp>
#include <boost/unordered/detail/allocate.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/is_nothrow_move_constructible.hpp>
+#include <boost/type_traits/is_nothrow_move_assignable.hpp>
#include <boost/swap.hpp>
#include <boost/assert.hpp>
#include <boost/limits.hpp>
#include <boost/iterator.hpp>
-#if defined(BOOST_MSVC)
-#pragma warning(push)
-#pragma warning(disable:4127) // conditional expression is constant
-#endif
-
namespace boost { namespace unordered { namespace detail {
template <typename Types> struct table;
template <typename NodePointer> struct bucket;
struct ptr_bucket;
- template <typename A, typename Bucket, typename Node, typename Policy>
- struct buckets;
template <typename Types> struct table_impl;
template <typename Types> struct grouped_table_impl;
- ///////////////////////////////////////////////////////////////////
- //
- // 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 constructed_;
-
- public:
-
- node_constructor(node_allocator& n) :
- alloc_(n),
- node_(),
- constructed_(false)
- {
- }
-
- ~node_constructor();
-
- void construct_node();
-
- template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
- void construct_value(BOOST_UNORDERED_EMPLACE_ARGS)
- {
- BOOST_ASSERT(node_ && !constructed_);
- boost::unordered::detail::construct_node(alloc_,
- boost::addressof(*node_), BOOST_UNORDERED_EMPLACE_FORWARD);
- node_->init(static_cast<typename node::link_pointer>(node_));
- constructed_ = true;
- }
-
- template <typename A0>
- void construct_value2(BOOST_FWD_REF(A0) a0)
- {
- BOOST_ASSERT(node_ && !constructed_);
-
- boost::unordered::detail::construct_node(alloc_,
- boost::addressof(*node_),
- BOOST_UNORDERED_EMPLACE_ARGS1(boost::forward<A0>(a0)));
-
- constructed_ = true;
- node_->init(static_cast<typename node::link_pointer>(node_));
- }
-
- value_type const& value() const {
- BOOST_ASSERT(node_ && constructed_);
- return node_->value();
- }
-
- node_pointer get()
- {
- return node_;
- }
-
- // 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&);
- };
-
- template <typename Alloc>
- node_constructor<Alloc>::~node_constructor()
- {
- if (node_) {
- if (constructed_) {
- boost::unordered::detail::destroy_node(alloc_,
- boost::addressof(*node_));
- }
-
- node_allocator_traits::deallocate(alloc_, node_, 1);
- }
- }
-
- template <typename Alloc>
- void node_constructor<Alloc>::construct_node()
- {
- if(!node_) {
- constructed_ = false;
- node_ = node_allocator_traits::allocate(alloc_, 1);
- }
- else if (constructed_) {
- boost::unordered::detail::destroy_node(alloc_,
- boost::addressof(*node_));
- constructed_ = false;
- }
- }
-
- ///////////////////////////////////////////////////////////////////
- //
- // 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 };
- };
-
- template <typename LinkPointer>
- struct node_base
- {
- typedef LinkPointer link_pointer;
- link_pointer next_;
-
- node_base() : next_() {}
- };
-
}}}
+// The 'iterator_detail' namespace was a misguided attempt at avoiding ADL
+// in the detail namespace. It didn't work because the template parameters
+// were in detail. I'm not changing it at the moment to be safe. I might
+// do in the future if I change the iterator types.
namespace boost { namespace unordered { namespace iterator_detail {
////////////////////////////////////////////////////////////////////////////
@@ -194,49 +44,50 @@ namespace boost { namespace unordered { namespace iterator_detail {
//
// 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, typename Policy>
- struct l_iterator;
- template <typename ConstNodePointer, typename NodePointer,
- typename Value, typename Policy> struct cl_iterator;
+ template <typename Node> struct iterator;
+ template <typename Node, typename ConstNodePointer> struct c_iterator;
+ template <typename Node, typename Policy> struct l_iterator;
+ template <typename Node, typename ConstNodePointer, typename Policy>
+ struct cl_iterator;
// Local Iterators
//
// all no throw
- template <typename NodePointer, typename Value, typename Policy>
+ template <typename Node, typename Policy>
struct l_iterator
: public boost::iterator<
- std::forward_iterator_tag, Value, std::ptrdiff_t,
- NodePointer, Value&>
+ std::forward_iterator_tag,
+ typename Node::value_type,
+ std::ptrdiff_t,
+ typename Node::value_type*,
+ typename Node::value_type&>
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
- template <typename ConstNodePointer, typename NodePointer2,
- typename Value2, typename Policy2>
+ template <typename Node2, typename ConstNodePointer, typename Policy2>
friend struct boost::unordered::iterator_detail::cl_iterator;
private:
#endif
- typedef NodePointer node_pointer;
- typedef boost::unordered::iterator_detail::iterator<NodePointer, Value>
- iterator;
+ typedef typename Node::node_pointer node_pointer;
+ typedef boost::unordered::iterator_detail::iterator<Node> iterator;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
public:
- l_iterator() : ptr_() {}
+ typedef typename Node::value_type value_type;
+
+ l_iterator() BOOST_NOEXCEPT : ptr_() {}
- l_iterator(iterator x, std::size_t b, std::size_t c)
+ l_iterator(iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT
: ptr_(x.node_), bucket_(b), bucket_count_(c) {}
- Value& operator*() const {
+ value_type& operator*() const {
return ptr_->value();
}
- Value* operator->() const {
+ value_type* operator->() const {
return ptr_->value_ptr();
}
@@ -254,51 +105,53 @@ namespace boost { namespace unordered { namespace iterator_detail {
return tmp;
}
- bool operator==(l_iterator x) const {
+ bool operator==(l_iterator x) const BOOST_NOEXCEPT {
return ptr_ == x.ptr_;
}
- bool operator!=(l_iterator x) const {
+ bool operator!=(l_iterator x) const BOOST_NOEXCEPT {
return ptr_ != x.ptr_;
}
};
- template <typename ConstNodePointer, typename NodePointer, typename Value,
- typename Policy>
+ template <typename Node, typename ConstNodePointer, typename Policy>
struct cl_iterator
: public boost::iterator<
- std::forward_iterator_tag, Value, std::ptrdiff_t,
- ConstNodePointer, Value const&>
+ std::forward_iterator_tag,
+ typename Node::value_type,
+ std::ptrdiff_t,
+ typename Node::value_type const*,
+ typename Node::value_type const&>
{
friend struct boost::unordered::iterator_detail::l_iterator
- <NodePointer, Value, Policy>;
+ <Node, Policy>;
private:
- typedef NodePointer node_pointer;
- typedef boost::unordered::iterator_detail::iterator<NodePointer, Value>
- iterator;
+ typedef typename Node::node_pointer node_pointer;
+ typedef boost::unordered::iterator_detail::iterator<Node> iterator;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
public:
- cl_iterator() : ptr_() {}
+ typedef typename Node::value_type value_type;
+
+ cl_iterator() BOOST_NOEXCEPT : ptr_() {}
- cl_iterator(iterator x, std::size_t b, std::size_t c) :
+ cl_iterator(iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT :
ptr_(x.node_), bucket_(b), bucket_count_(c) {}
cl_iterator(boost::unordered::iterator_detail::l_iterator<
- NodePointer, Value, Policy> const& x) :
+ Node, Policy> const& x) BOOST_NOEXCEPT :
ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
{}
- Value const&
- operator*() const {
+ value_type const& operator*() const {
return ptr_->value();
}
- Value const* operator->() const {
+ value_type const* operator->() const {
return ptr_->value_ptr();
}
@@ -316,52 +169,60 @@ namespace boost { namespace unordered { namespace iterator_detail {
return tmp;
}
- friend bool operator==(cl_iterator const& x, cl_iterator const& y) {
+ friend bool operator==(cl_iterator const& x, cl_iterator const& y)
+ BOOST_NOEXCEPT
+ {
return x.ptr_ == y.ptr_;
}
- friend bool operator!=(cl_iterator const& x, cl_iterator const& y) {
+ friend bool operator!=(cl_iterator const& x, cl_iterator const& y)
+ BOOST_NOEXCEPT
+ {
return x.ptr_ != y.ptr_;
}
};
- template <typename NodePointer, typename Value>
+ template <typename Node>
struct iterator
: public boost::iterator<
- std::forward_iterator_tag, Value, std::ptrdiff_t,
- NodePointer, Value&>
+ std::forward_iterator_tag,
+ typename Node::value_type,
+ std::ptrdiff_t,
+ typename Node::value_type*,
+ typename Node::value_type&>
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
- template <typename, typename, typename>
+ template <typename, typename>
friend struct boost::unordered::iterator_detail::c_iterator;
- template <typename, typename, typename>
+ template <typename, typename>
friend struct boost::unordered::iterator_detail::l_iterator;
- template <typename, typename, typename, typename>
+ template <typename, typename, typename>
friend struct boost::unordered::iterator_detail::cl_iterator;
template <typename>
friend struct boost::unordered::detail::table;
- template <typename, typename, typename, typename>
- friend struct boost::unordered::detail::buckets;
template <typename>
friend struct boost::unordered::detail::table_impl;
template <typename>
friend struct boost::unordered::detail::grouped_table_impl;
private:
#endif
- typedef NodePointer node_pointer;
+ typedef typename Node::node_pointer node_pointer;
node_pointer node_;
public:
- iterator() : node_() {}
+ typedef typename Node::value_type value_type;
+
+ iterator() BOOST_NOEXCEPT : node_() {}
- explicit iterator(node_pointer const& x) : node_(x) {}
+ explicit iterator(typename Node::link_pointer x) BOOST_NOEXCEPT :
+ node_(static_cast<node_pointer>(x)) {}
- Value& operator*() const {
+ value_type& operator*() const {
return node_->value();
}
- Value* operator->() const {
+ value_type* operator->() const {
return &node_->value();
}
@@ -376,29 +237,29 @@ namespace boost { namespace unordered { namespace iterator_detail {
return tmp;
}
- bool operator==(iterator const& x) const {
+ bool operator==(iterator const& x) const BOOST_NOEXCEPT {
return node_ == x.node_;
}
- bool operator!=(iterator const& x) const {
+ bool operator!=(iterator const& x) const BOOST_NOEXCEPT {
return node_ != x.node_;
}
};
- template <typename ConstNodePointer, typename NodePointer, typename Value>
+ template <typename Node, typename ConstNodePointer>
struct c_iterator
: public boost::iterator<
- std::forward_iterator_tag, Value, std::ptrdiff_t,
- ConstNodePointer, Value const&>
+ std::forward_iterator_tag,
+ typename Node::value_type,
+ std::ptrdiff_t,
+ typename Node::value_type const*,
+ typename Node::value_type const&>
{
- friend struct boost::unordered::iterator_detail::iterator<
- NodePointer, Value>;
+ friend struct boost::unordered::iterator_detail::iterator<Node>;
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename>
friend struct boost::unordered::detail::table;
- template <typename, typename, typename, typename>
- friend struct boost::unordered::detail::buckets;
template <typename>
friend struct boost::unordered::detail::table_impl;
template <typename>
@@ -406,26 +267,26 @@ namespace boost { namespace unordered { namespace iterator_detail {
private:
#endif
-
- typedef NodePointer node_pointer;
- typedef boost::unordered::iterator_detail::iterator<NodePointer, Value>
- iterator;
+ typedef typename Node::node_pointer node_pointer;
+ typedef boost::unordered::iterator_detail::iterator<Node> iterator;
node_pointer node_;
public:
- c_iterator() : node_() {}
+ typedef typename Node::value_type value_type;
+
+ c_iterator() BOOST_NOEXCEPT : node_() {}
- explicit c_iterator(node_pointer const& x) : node_(x) {}
+ explicit c_iterator(typename Node::link_pointer x) BOOST_NOEXCEPT :
+ node_(static_cast<node_pointer>(x)) {}
- c_iterator(boost::unordered::iterator_detail::iterator<
- NodePointer, Value> const& x) : node_(x.node_) {}
+ c_iterator(iterator const& x) BOOST_NOEXCEPT : node_(x.node_) {}
- Value const& operator*() const {
+ value_type const& operator*() const {
return node_->value();
}
- Value const* operator->() const {
+ value_type const* operator->() const {
return &node_->value();
}
@@ -440,11 +301,15 @@ namespace boost { namespace unordered { namespace iterator_detail {
return tmp;
}
- friend bool operator==(c_iterator const& x, c_iterator const& y) {
+ friend bool operator==(c_iterator const& x, c_iterator const& y)
+ BOOST_NOEXCEPT
+ {
return x.node_ == y.node_;
}
- friend bool operator!=(c_iterator const& x, c_iterator const& y) {
+ friend bool operator!=(c_iterator const& x, c_iterator const& y)
+ BOOST_NOEXCEPT
+ {
return x.node_ != y.node_;
}
};
@@ -454,479 +319,397 @@ namespace boost { namespace unordered { namespace detail {
///////////////////////////////////////////////////////////////////
//
- // Hash Policy
- //
- // Don't really want buckets to derive from this, but will for now.
+ // Node construction
- template <typename SizeT>
- struct prime_policy
+ template <typename NodeAlloc>
+ struct node_constructor
{
- template <typename Hash, typename T>
- static inline SizeT apply_hash(Hash const& hf, T const& x) {
- return hf(x);
+ 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;
+
+ protected:
+
+ 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)
+ {
}
- static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) {
- return hash % bucket_count;
+ ~node_constructor();
+
+ void construct();
+
+ template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ void construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS)
+ {
+ construct();
+ boost::unordered::detail::func::construct_value_impl(
+ alloc_, node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
+ value_constructed_ = true;
}
- static inline SizeT new_bucket_count(SizeT min) {
- return boost::unordered::detail::next_prime(min);
+ template <typename A0>
+ void construct_with_value2(BOOST_FWD_REF(A0) a0)
+ {
+ construct();
+ boost::unordered::detail::func::construct_value_impl(
+ alloc_, node_->value_ptr(),
+ BOOST_UNORDERED_EMPLACE_ARGS1(boost::forward<A0>(a0)));
+ value_constructed_ = true;
}
- static inline SizeT prev_bucket_count(SizeT max) {
- return boost::unordered::detail::prev_prime(max);
+ value_type const& value() const {
+ BOOST_ASSERT(node_ && node_constructed_ && value_constructed_);
+ return node_->value();
+ }
+
+ // no throw
+ node_pointer release()
+ {
+ BOOST_ASSERT(node_ && node_constructed_);
+ node_pointer p = node_;
+ node_ = node_pointer();
+ return p;
}
+
+ private:
+ node_constructor(node_constructor const&);
+ node_constructor& operator=(node_constructor const&);
};
- template <typename SizeT>
- struct mix64_policy
+ template <typename Alloc>
+ node_constructor<Alloc>::~node_constructor()
{
- template <typename Hash, typename T>
- static inline SizeT apply_hash(Hash const& hf, T const& x) {
- SizeT key = hf(x);
- key = (~key) + (key << 21); // key = (key << 21) - key - 1;
- key = key ^ (key >> 24);
- key = (key + (key << 3)) + (key << 8); // key * 265
- key = key ^ (key >> 14);
- key = (key + (key << 2)) + (key << 4); // key * 21
- key = key ^ (key >> 28);
- key = key + (key << 31);
- return key;
- }
+ if (node_) {
+ if (value_constructed_) {
+ boost::unordered::detail::func::destroy_value_impl(alloc_,
+ node_->value_ptr());
+ }
- static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) {
- return hash & (bucket_count - 1);
- }
+ if (node_constructed_) {
+ boost::unordered::detail::func::destroy(
+ boost::addressof(*node_));
+ }
- static inline SizeT new_bucket_count(SizeT min) {
- if (min <= 4) return 4;
- --min;
- min |= min >> 1;
- min |= min >> 2;
- min |= min >> 4;
- min |= min >> 8;
- min |= min >> 16;
- min |= min >> 32;
- return min + 1;
+ node_allocator_traits::deallocate(alloc_, node_, 1);
}
+ }
- static inline SizeT prev_bucket_count(SizeT max) {
- max |= max >> 1;
- max |= max >> 2;
- max |= max >> 4;
- max |= max >> 8;
- max |= max >> 16;
- max |= max >> 32;
- return (max >> 1) + 1;
- }
- };
+ template <typename Alloc>
+ void node_constructor<Alloc>::construct()
+ {
+ if(!node_) {
+ node_constructed_ = false;
+ value_constructed_ = false;
- template <int digits, int radix>
- struct pick_policy_impl {
- typedef prime_policy<std::size_t> type;
- };
+ node_ = node_allocator_traits::allocate(alloc_, 1);
- template <>
- struct pick_policy_impl<64, 2> {
- typedef mix64_policy<std::size_t> type;
- };
+ new ((void*) boost::addressof(*node_)) node();
+ node_->init(node_);
+ node_constructed_ = true;
+ }
+ else {
+ BOOST_ASSERT(node_constructed_);
- struct pick_policy :
- pick_policy_impl<
- std::numeric_limits<std::size_t>::digits,
- std::numeric_limits<std::size_t>::radix> {};
+ if (value_constructed_)
+ {
+ boost::unordered::detail::func::destroy_value_impl(alloc_,
+ node_->value_ptr());
+ value_constructed_ = false;
+ }
+ }
+ }
///////////////////////////////////////////////////////////////////
//
- // Buckets
+ // Node Holder
+ //
+ // Temporary store for nodes. Deletes any that aren't used.
- template <typename A, typename Bucket, typename Node, typename Policy>
- struct buckets : Policy
+ template <typename NodeAlloc>
+ struct node_holder : private node_constructor<NodeAlloc>
{
private:
- buckets(buckets const&);
- buckets& operator=(buckets const&);
- public:
- typedef boost::unordered::detail::allocator_traits<A> traits;
- typedef typename traits::value_type value_type;
-
- typedef Policy policy;
- typedef Node node;
- typedef Bucket bucket;
- typedef typename boost::unordered::detail::rebind_wrap<A, node>::type
- node_allocator;
- typedef typename boost::unordered::detail::rebind_wrap<A, bucket>::type
- bucket_allocator;
- typedef boost::unordered::detail::allocator_traits<node_allocator>
+ typedef node_constructor<NodeAlloc> base;
+
+ typedef NodeAlloc node_allocator;
+ typedef boost::unordered::detail::allocator_traits<NodeAlloc>
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;
-
- 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, policy> l_iterator;
- typedef boost::unordered::iterator_detail::
- cl_iterator<const_node_pointer, node_pointer, value_type, policy>
- cl_iterator;
-
- // Members
-
- bucket_pointer buckets_;
- std::size_t bucket_count_;
- std::size_t size_;
- boost::unordered::detail::compressed<bucket_allocator, node_allocator>
- allocators_;
+ typedef typename node_allocator_traits::value_type node;
+ typedef typename node_allocator_traits::pointer node_pointer;
+ typedef typename node::value_type value_type;
+ typedef typename node::link_pointer link_pointer;
+ typedef boost::unordered::iterator_detail::iterator<node> iterator;
- // Data access
+ node_pointer nodes_;
- bucket_allocator const& bucket_alloc() const
- {
- return allocators_.first();
- }
+ public:
- node_allocator const& node_alloc() const
+ template <typename Table>
+ explicit node_holder(Table& b) :
+ base(b.node_alloc()),
+ nodes_()
{
- return allocators_.second();
+ if (b.size_) {
+ typename Table::link_pointer prev = b.get_previous_start();
+ nodes_ = static_cast<node_pointer>(prev->next_);
+ prev->next_ = link_pointer();
+ b.size_ = 0;
+ }
}
- bucket_allocator& bucket_alloc()
- {
- return allocators_.first();
- }
+ ~node_holder();
- node_allocator& node_alloc()
+ void node_for_assignment()
{
- return allocators_.second();
- }
+ if (!this->node_ && nodes_) {
+ this->node_ = nodes_;
+ nodes_ = static_cast<node_pointer>(nodes_->next_);
+ this->node_->init(this->node_);
+ this->node_->next_ = link_pointer();
- std::size_t max_bucket_count() const
- {
- // -1 to account for the start bucket.
- return policy::prev_bucket_count(
- bucket_allocator_traits::max_size(bucket_alloc()) - 1);
+ this->node_constructed_ = true;
+ this->value_constructed_ = true;
+ }
}
- bucket_pointer get_bucket(std::size_t bucket_index) const
- {
- return buckets_ + static_cast<std::ptrdiff_t>(bucket_index);
+ template <typename T>
+ inline void assign_impl(T const& v) {
+ if (this->node_ && this->value_constructed_) {
+ this->node_->value() = v;
+ }
+ else {
+ this->construct_with_value2(v);
+ }
}
- previous_pointer get_previous_start() const
- {
- return this->get_bucket(this->bucket_count_)->first_from_start();
+ template <typename T1, typename T2>
+ inline void assign_impl(std::pair<T1 const, T2> const& v) {
+ this->construct_with_value2(v);
}
- previous_pointer get_previous_start(std::size_t bucket_index) const
- {
- return this->get_bucket(bucket_index)->next_;
+ template <typename T>
+ inline void move_assign_impl(T& v) {
+ if (this->node_ && this->value_constructed_) {
+ this->node_->value() = boost::move(v);
+ }
+ else {
+ this->construct_with_value2(boost::move(v));
+ }
}
- iterator get_start() const
- {
- return iterator(static_cast<node_pointer>(
- this->get_previous_start()->next_));
+ template <typename T1, typename T2>
+ inline void move_assign_impl(std::pair<T1 const, T2>& v) {
+ this->construct_with_value2(boost::move(v));
}
- iterator get_start(std::size_t bucket_index) const
+ node_pointer copy_of(value_type const& v)
{
- previous_pointer prev = this->get_previous_start(bucket_index);
- return prev ? iterator(static_cast<node_pointer>(prev->next_)) :
- iterator();
+ node_for_assignment();
+ assign_impl(v);
+ return base::release();
}
- float load_factor() const
+ node_pointer move_copy_of(value_type& v)
{
- BOOST_ASSERT(this->bucket_count_ != 0);
- return static_cast<float>(this->size_)
- / static_cast<float>(this->bucket_count_);
+ node_for_assignment();
+ move_assign_impl(v);
+ return base::release();
}
- std::size_t bucket_size(std::size_t index) const
+ iterator begin() const
{
- if (!this->size_) return 0;
- iterator it = this->get_start(index);
- if (!it.node_) return 0;
+ return iterator(nodes_);
+ }
+ };
- std::size_t count = 0;
- while(it.node_ && policy::to_bucket(
- this->bucket_count_, it.node_->hash_) == index)
- {
- ++count;
- ++it;
- }
+ template <typename Alloc>
+ node_holder<Alloc>::~node_holder()
+ {
+ while (nodes_) {
+ node_pointer p = nodes_;
+ nodes_ = static_cast<node_pointer>(p->next_);
- return count;
+ boost::unordered::detail::func::destroy_value_impl(this->alloc_,
+ p->value_ptr());
+ boost::unordered::detail::func::destroy(boost::addressof(*p));
+ node_allocator_traits::deallocate(this->alloc_, p, 1);
}
+ }
- ////////////////////////////////////////////////////////////////////////
- // Constructors
+ ///////////////////////////////////////////////////////////////////
+ //
+ // Bucket
- buckets(node_allocator const& a, std::size_t bucket_count) :
- buckets_(),
- bucket_count_(bucket_count),
- size_(),
- allocators_(a,a)
- {
- }
+ template <typename NodePointer>
+ struct bucket
+ {
+ typedef NodePointer link_pointer;
+ link_pointer next_;
- buckets(buckets& b, boost::unordered::detail::move_tag m) :
- buckets_(),
- bucket_count_(b.bucket_count_),
- size_(),
- allocators_(b.allocators_, m)
- {
- swap(b);
- }
+ bucket() : next_() {}
- 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)
+ link_pointer first_from_start()
{
- swap(x);
+ return next_;
}
- ////////////////////////////////////////////////////////////////////////
- // Create buckets
- // (never called in constructor to avoid exception issues)
-
- void create_buckets()
- {
- 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);
-
- if (bucket::extra_node)
- {
- node_constructor a(this->node_alloc());
- a.construct_node();
-
- // Since this node is just to mark the beginning it doesn't
- // contain a value, so just construct node::node_base
- // which containers the pointer to the next element.
- node_allocator_traits::construct(node_alloc(),
- static_cast<typename node::node_base*>(
- boost::addressof(*a.get())),
- typename node::node_base());
-
- (constructor.get() +
- static_cast<std::ptrdiff_t>(this->bucket_count_))->next_ =
- a.release();
- }
+ enum { extra_node = true };
+ };
- this->buckets_ = constructor.release();
- }
+ struct ptr_bucket
+ {
+ typedef ptr_bucket* link_pointer;
+ link_pointer next_;
- ////////////////////////////////////////////////////////////////////////
- // Swap and Move
+ ptr_bucket() : next_(0) {}
- void swap(buckets& other, false_type = false_type())
+ link_pointer first_from_start()
{
- BOOST_ASSERT(node_alloc() == other.node_alloc());
- boost::swap(buckets_, other.buckets_);
- boost::swap(bucket_count_, other.bucket_count_);
- boost::swap(size_, other.size_);
+ return this;
}
- void swap(buckets& other, true_type)
- {
- allocators_.swap(other.allocators_);
- boost::swap(buckets_, other.buckets_);
- boost::swap(bucket_count_, other.bucket_count_);
- boost::swap(size_, other.size_);
- }
+ enum { extra_node = false };
+ };
- void move_buckets_from(buckets& other)
- {
- BOOST_ASSERT(node_alloc() == other.node_alloc());
- BOOST_ASSERT(!this->buckets_);
- this->buckets_ = other.buckets_;
- this->bucket_count_ = other.bucket_count_;
- this->size_ = other.size_;
- other.buckets_ = bucket_pointer();
- other.bucket_count_ = 0;
- other.size_ = 0;
- }
+ ///////////////////////////////////////////////////////////////////
+ //
+ // Hash Policy
- ////////////////////////////////////////////////////////////////////////
- // Delete/destruct
+ template <typename SizeT>
+ struct prime_policy
+ {
+ template <typename Hash, typename T>
+ static inline SizeT apply_hash(Hash const& hf, T const& x) {
+ return hf(x);
+ }
- inline void delete_node(c_iterator n)
- {
- boost::unordered::detail::destroy_node(
- node_alloc(), boost::addressof(*n.node_));
- node_allocator_traits::deallocate(node_alloc(), n.node_, 1);
- --size_;
+ static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) {
+ return hash % bucket_count;
}
- std::size_t delete_nodes(c_iterator begin, c_iterator end)
- {
- std::size_t count = 0;
+ static inline SizeT new_bucket_count(SizeT min) {
+ return boost::unordered::detail::next_prime(min);
+ }
- while(begin != end) {
- c_iterator n = begin;
- ++begin;
- delete_node(n);
- ++count;
- }
+ static inline SizeT prev_bucket_count(SizeT max) {
+ return boost::unordered::detail::prev_prime(max);
+ }
+ };
- return count;
+ template <typename SizeT>
+ struct mix64_policy
+ {
+ template <typename Hash, typename T>
+ static inline SizeT apply_hash(Hash const& hf, T const& x) {
+ SizeT key = hf(x);
+ key = (~key) + (key << 21); // key = (key << 21) - key - 1;
+ key = key ^ (key >> 24);
+ key = (key + (key << 3)) + (key << 8); // key * 265
+ key = key ^ (key >> 14);
+ key = (key + (key << 2)) + (key << 4); // key * 21
+ key = key ^ (key >> 28);
+ key = key + (key << 31);
+ return key;
}
- inline void delete_extra_node(bucket_pointer) {}
+ static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) {
+ return hash & (bucket_count - 1);
+ }
- inline void delete_extra_node(node_pointer n) {
- node_allocator_traits::destroy(node_alloc(),
- static_cast<typename node::node_base*>(boost::addressof(*n)));
- node_allocator_traits::deallocate(node_alloc(), n, 1);
+ static inline SizeT new_bucket_count(SizeT min) {
+ if (min <= 4) return 4;
+ --min;
+ min |= min >> 1;
+ min |= min >> 2;
+ min |= min >> 4;
+ min |= min >> 8;
+ min |= min >> 16;
+ min |= min >> 32;
+ return min + 1;
}
- inline ~buckets()
- {
- this->delete_buckets();
+ static inline SizeT prev_bucket_count(SizeT max) {
+ max |= max >> 1;
+ max |= max >> 2;
+ max |= max >> 4;
+ max |= max >> 8;
+ max |= max >> 16;
+ max |= max >> 32;
+ return (max >> 1) + 1;
}
+ };
- void delete_buckets()
- {
- if(this->buckets_) {
- 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(iterator(n));
- }
-
- delete_extra_node(prev);
-
- 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);
-
- this->buckets_ = bucket_pointer();
- }
+ template <int digits, int radix>
+ struct pick_policy_impl {
+ typedef prime_policy<std::size_t> type;
+ };
- BOOST_ASSERT(!this->size_);
- }
+ template <>
+ struct pick_policy_impl<64, 2> {
+ typedef mix64_policy<std::size_t> type;
+ };
- void clear()
- {
- if(!this->size_) return;
+ template <typename T>
+ struct pick_policy :
+ pick_policy_impl<
+ std::numeric_limits<std::size_t>::digits,
+ std::numeric_limits<std::size_t>::radix> {};
- previous_pointer prev = this->get_previous_start();
+ // While the mix policy is generally faster, the prime policy is a lot
+ // faster when a large number consecutive integers are used, because
+ // there are no collisions. Since that is probably quite common, use
+ // prime policy for integeral types. But not the smaller ones, as they
+ // don't have enough unique values for this to be an issue.
- while(prev->next_) {
- node_pointer n = static_cast<node_pointer>(prev->next_);
- prev->next_ = n->next_;
- delete_node(iterator(n));
- }
+ template <>
+ struct pick_policy<int> {
+ typedef prime_policy<std::size_t> type;
+ };
- bucket_pointer end = this->get_bucket(this->bucket_count_);
- for(bucket_pointer it = this->buckets_; it != end; ++it)
- {
- it->next_ = node_pointer();
- }
+ template <>
+ struct pick_policy<unsigned int> {
+ typedef prime_policy<std::size_t> type;
+ };
- BOOST_ASSERT(!this->size_);
- }
+ template <>
+ struct pick_policy<long> {
+ typedef prime_policy<std::size_t> type;
+ };
- // This is called after erasing a node or group of nodes to fix up
- // the bucket pointers.
- void fix_buckets(bucket_pointer this_bucket,
- previous_pointer prev, node_pointer next)
- {
- if (!next)
- {
- 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 != this_bucket)
- {
- next_bucket->next_ = prev;
- if (this_bucket->next_ == prev)
- this_bucket->next_ = node_pointer();
- }
- }
- }
+ template <>
+ struct pick_policy<unsigned long> {
+ typedef prime_policy<std::size_t> type;
+ };
- // 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,
- previous_pointer prev, node_pointer begin, node_pointer end)
- {
- 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 = static_cast<node_pointer>(n->next_);
- if (n == end) return;
-
- std::size_t new_bucket_index =
- policy::to_bucket(this->bucket_count_, n->hash_);
- if (bucket_index != new_bucket_index) {
- bucket_index = new_bucket_index;
- break;
- }
- }
- }
-
- // Iterate through the remaining nodes, clearing out the bucket
- // pointers.
- this->get_bucket(bucket_index)->next_ = previous_pointer();
- for(;;) {
- n = static_cast<node_pointer>(n->next_);
- if (n == end) break;
-
- std::size_t new_bucket_index =
- policy::to_bucket(this->bucket_count_, n->hash_);
- if (bucket_index != new_bucket_index) {
- bucket_index = new_bucket_index;
- this->get_bucket(bucket_index)->next_ = previous_pointer();
- }
- };
-
- // Finally fix the bucket containing the trailing node.
- if (n) {
- this->get_bucket(
- policy::to_bucket(this->bucket_count_, n->hash_))->next_
- = prev;
- }
- }
+ // TODO: Maybe not if std::size_t is smaller than long long.
+#if !defined(BOOST_NO_LONG_LONG)
+ template <>
+ struct pick_policy<long long> {
+ typedef prime_policy<std::size_t> type;
};
+ template <>
+ struct pick_policy<unsigned long long> {
+ typedef prime_policy<std::size_t> type;
+ };
+#endif
+
////////////////////////////////////////////////////////////////////////////
// Functions
@@ -941,12 +724,23 @@ namespace boost { namespace unordered { namespace detail {
// atomically assigns the new function objects in a strongly
// exception safe manner.
- template <class H, class P> class set_hash_functions;
+ template <class H, class P, bool NoThrowMoveAssign>
+ class set_hash_functions;
template <class H, class P>
class functions
{
- friend class boost::unordered::detail::set_hash_functions<H, P>;
+ public:
+ static const bool nothrow_move_assignable =
+ boost::is_nothrow_move_assignable<H>::value &&
+ boost::is_nothrow_move_assignable<P>::value;
+ static const bool nothrow_move_constructible =
+ boost::is_nothrow_move_constructible<H>::value &&
+ boost::is_nothrow_move_constructible<P>::value;
+
+ private:
+ friend class boost::unordered::detail::set_hash_functions<H, P,
+ nothrow_move_assignable>;
functions& operator=(functions const&);
typedef compressed<H, P> function_pair;
@@ -963,23 +757,40 @@ namespace boost { namespace unordered { namespace detail {
static_cast<void const*>(&funcs_[current_]));
}
+ function_pair& current() {
+ return *static_cast<function_pair*>(
+ static_cast<void*>(&funcs_[current_]));
+ }
+
void construct(bool which, H const& hf, P const& eq)
{
new((void*) &funcs_[which]) function_pair(hf, eq);
}
- void construct(bool which, function_pair const& f)
+ void construct(bool which, function_pair const& f,
+ boost::unordered::detail::false_type =
+ boost::unordered::detail::false_type())
{
new((void*) &funcs_[which]) function_pair(f);
}
+ void construct(bool which, function_pair& f,
+ boost::unordered::detail::true_type)
+ {
+ new((void*) &funcs_[which]) function_pair(f,
+ boost::unordered::detail::move_tag());
+ }
+
void destroy(bool which)
{
- boost::unordered::detail::destroy((function_pair*)(&funcs_[which]));
+ boost::unordered::detail::func::destroy((function_pair*)(&funcs_[which]));
}
public:
+ typedef boost::unordered::detail::set_hash_functions<H, P,
+ nothrow_move_assignable> set_hash_functions;
+
functions(H const& hf, P const& eq)
: current_(false)
{
@@ -992,6 +803,14 @@ namespace boost { namespace unordered { namespace detail {
construct(current_, bf.current());
}
+ functions(functions& bf, boost::unordered::detail::move_tag)
+ : current_(false)
+ {
+ construct(current_, bf.current(),
+ boost::unordered::detail::integral_constant<bool,
+ nothrow_move_constructible>());
+ }
+
~functions() {
this->destroy(current_);
}
@@ -1004,26 +823,28 @@ namespace boost { namespace unordered { namespace detail {
return current().second();
}
};
-
+
template <class H, class P>
- class set_hash_functions
+ class set_hash_functions<H, P, false>
{
set_hash_functions(set_hash_functions const&);
set_hash_functions& operator=(set_hash_functions const&);
+
+ typedef functions<H, P> functions_type;
- functions<H,P>& functions_;
+ functions_type& functions_;
bool tmp_functions_;
public:
- set_hash_functions(functions<H,P>& f, H const& h, P const& p)
+ set_hash_functions(functions_type& f, H const& h, P const& p)
: functions_(f),
tmp_functions_(!f.current_)
{
f.construct(tmp_functions_, h, p);
}
- set_hash_functions(functions<H,P>& f, functions<H,P> const& other)
+ set_hash_functions(functions_type& f, functions_type const& other)
: functions_(f),
tmp_functions_(!f.current_)
{
@@ -1041,10 +862,67 @@ namespace boost { namespace unordered { namespace detail {
tmp_functions_ = !tmp_functions_;
}
};
-}}}
-#if defined(BOOST_MSVC)
-#pragma warning(pop)
+ template <class H, class P>
+ class set_hash_functions<H, P, true>
+ {
+ set_hash_functions(set_hash_functions const&);
+ set_hash_functions& operator=(set_hash_functions const&);
+
+ typedef functions<H, P> functions_type;
+
+ functions_type& functions_;
+ H hash_;
+ P pred_;
+
+ public:
+
+ set_hash_functions(functions_type& f, H const& h, P const& p) :
+ functions_(f),
+ hash_(h),
+ pred_(p) {}
+
+ set_hash_functions(functions_type& f, functions_type const& other) :
+ functions_(f),
+ hash_(other.hash_function()),
+ pred_(other.key_eq()) {}
+
+ void commit()
+ {
+ functions_.current().first() = boost::move(hash_);
+ functions_.current().second() = boost::move(pred_);
+ }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////
+ // rvalue parameters when type can't be a BOOST_RV_REF(T) parameter
+ // e.g. for int
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+# define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T)
+#else
+ struct please_ignore_this_overload {
+ typedef please_ignore_this_overload type;
+ };
+
+ template <typename T>
+ struct rv_ref_impl {
+ typedef BOOST_RV_REF(T) type;
+ };
+
+ template <typename T>
+ struct rv_ref :
+ boost::detail::if_true<
+ boost::is_class<T>::value
+ >::BOOST_NESTED_TEMPLATE then <
+ boost::unordered::detail::rv_ref_impl<T>,
+ please_ignore_this_overload
+ >::type
+ {};
+
+# define BOOST_UNORDERED_RV_REF(T) \
+ typename boost::unordered::detail::rv_ref<T>::type
#endif
+}}}
#endif
diff --git a/boost/unordered/detail/equivalent.hpp b/boost/unordered/detail/equivalent.hpp
index 5cbf6a7cea..58478f99b6 100644
--- a/boost/unordered/detail/equivalent.hpp
+++ b/boost/unordered/detail/equivalent.hpp
@@ -7,8 +7,9 @@
#ifndef BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
+#include <boost/config.hpp>
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#pragma once
#endif
#include <boost/unordered/detail/table.hpp>
@@ -22,46 +23,25 @@ namespace boost { namespace unordered { namespace detail {
template <typename A, typename T>
struct grouped_node :
- boost::unordered::detail::node_base<
- typename ::boost::unordered::detail::rebind_wrap<
- A, grouped_node<A, T> >::type::pointer
- >,
boost::unordered::detail::value_base<T>
{
typedef typename ::boost::unordered::detail::rebind_wrap<
- A, grouped_node<A, T> >::type::pointer link_pointer;
- typedef boost::unordered::detail::node_base<link_pointer> node_base;
+ A, grouped_node<A, T> >::type allocator;
+ typedef typename ::boost::unordered::detail::
+ allocator_traits<allocator>::pointer node_pointer;
+ typedef node_pointer link_pointer;
- link_pointer group_prev_;
+ link_pointer next_;
+ node_pointer group_prev_;
std::size_t hash_;
-#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
- template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
- explicit grouped_node(BOOST_UNORDERED_EMPLACE_ARGS) :
- node_base(),
- group_prev_(),
- hash_(0)
- {
- boost::unordered::detail::construct_impl(
- this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
- }
-
- ~grouped_node() {
- boost::unordered::detail::destroy(this->value_ptr());
- }
-
- grouped_node(grouped_node const&) {
- assert(false);
- }
-#else
grouped_node() :
- node_base(),
+ next_(),
group_prev_(),
hash_(0)
{}
-#endif
- void init(link_pointer self)
+ void init(node_pointer self)
{
group_prev_ = self;
}
@@ -72,47 +52,32 @@ namespace boost { namespace unordered { namespace detail {
template <typename T>
struct grouped_ptr_node :
- boost::unordered::detail::value_base<T>,
boost::unordered::detail::ptr_bucket
{
+ typedef T value_type;
typedef boost::unordered::detail::ptr_bucket bucket_base;
- typedef bucket_base node_base;
+ typedef grouped_ptr_node<T>* node_pointer;
typedef ptr_bucket* link_pointer;
- link_pointer group_prev_;
+ node_pointer group_prev_;
std::size_t hash_;
+ boost::unordered::detail::value_base<T> value_base_;
-#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
- template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
- explicit grouped_ptr_node(BOOST_UNORDERED_EMPLACE_ARGS) :
- bucket_base(),
- group_prev_(0),
- hash_(0)
- {
- boost::unordered::detail::construct_impl(
- this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
- }
-
- ~grouped_ptr_node() {
- boost::unordered::detail::destroy(this->value_ptr());
- }
-
- grouped_ptr_node(grouped_ptr_node const&) {
- assert(false);
- }
-#else
grouped_ptr_node() :
bucket_base(),
group_prev_(0),
hash_(0)
{}
-#endif
- void init(link_pointer self)
+ void init(node_pointer self)
{
group_prev_ = self;
}
+ void* address() { return value_base_.address(); }
+ value_type& value() { return value_base_.value(); }
+ value_type* value_ptr() { return value_base_.value_ptr(); }
+
private:
grouped_ptr_node& operator=(grouped_ptr_node const&);
};
@@ -170,16 +135,15 @@ namespace boost { namespace unordered { namespace detail {
{
typedef boost::unordered::detail::multiset<A, T, H, P> types;
+ typedef A allocator;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
- typedef typename boost::unordered::detail::rebind_wrap<
- A, value_type>::type allocator;
-
typedef boost::unordered::detail::allocator_traits<allocator> traits;
- typedef boost::unordered::detail::pick_grouped_node<allocator, value_type> pick;
+ typedef boost::unordered::detail::pick_grouped_node<allocator,
+ value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
@@ -187,7 +151,7 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::grouped_table_impl<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
- typedef boost::unordered::detail::pick_policy::type policy;
+ typedef typename boost::unordered::detail::pick_policy<T>::type policy;
};
template <typename A, typename K, typename M, typename H, typename P>
@@ -195,16 +159,15 @@ namespace boost { namespace unordered { namespace detail {
{
typedef boost::unordered::detail::multimap<A, K, M, H, P> types;
+ typedef A allocator;
typedef std::pair<K const, M> value_type;
typedef H hasher;
typedef P key_equal;
typedef K key_type;
- typedef typename boost::unordered::detail::rebind_wrap<
- A, value_type>::type allocator;
-
typedef boost::unordered::detail::allocator_traits<allocator> traits;
- typedef boost::unordered::detail::pick_grouped_node<allocator, value_type> pick;
+ typedef boost::unordered::detail::pick_grouped_node<allocator,
+ value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
@@ -213,7 +176,7 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::map_extractor<key_type, value_type>
extractor;
- typedef boost::unordered::detail::pick_policy::type policy;
+ typedef typename boost::unordered::detail::pick_policy<K>::type policy;
};
template <typename Types>
@@ -222,14 +185,12 @@ namespace boost { namespace unordered { namespace detail {
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::policy policy;
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;
@@ -249,12 +210,17 @@ namespace boost { namespace unordered { namespace detail {
grouped_table_impl(grouped_table_impl const& x)
: table(x, node_allocator_traits::
- select_on_container_copy_construction(x.node_alloc())) {}
+ select_on_container_copy_construction(x.node_alloc()))
+ {
+ this->init(x);
+ }
grouped_table_impl(grouped_table_impl const& x,
node_allocator const& a)
: table(x, a)
- {}
+ {
+ this->init(x);
+ }
grouped_table_impl(grouped_table_impl& x,
boost::unordered::detail::move_tag m)
@@ -265,7 +231,9 @@ namespace boost { namespace unordered { namespace detail {
node_allocator const& a,
boost::unordered::detail::move_tag m)
: table(x, a, m)
- {}
+ {
+ this->move_init(x);
+ }
// Accessors
@@ -275,9 +243,8 @@ namespace boost { namespace unordered { namespace detail {
Key const& k,
Pred const& eq) const
{
- std::size_t bucket_index =
- policy::to_bucket(this->bucket_count_, key_hash);
- iterator n = this->get_start(bucket_index);
+ std::size_t bucket_index = this->hash_to_bucket(key_hash);
+ iterator n = this->begin(bucket_index);
for (;;)
{
@@ -291,13 +258,11 @@ namespace boost { namespace unordered { namespace detail {
}
else
{
- if (policy::to_bucket(this->bucket_count_, node_hash)
- != bucket_index)
+ if (this->hash_to_bucket(node_hash) != bucket_index)
return iterator();
}
- n = iterator(static_cast<node_pointer>(
- static_cast<node_pointer>(n.node_->group_prev_)->next_));
+ n = iterator(n.node_->group_prev_->next_);
}
}
@@ -309,7 +274,7 @@ namespace boost { namespace unordered { namespace detail {
std::size_t x = 0;
node_pointer it = n.node_;
do {
- it = static_cast<node_pointer>(it->group_prev_);
+ it = it->group_prev_;
++x;
} while(it != n.node_);
@@ -321,10 +286,7 @@ namespace boost { namespace unordered { namespace detail {
{
iterator n = this->find_node(k);
return std::make_pair(
- n, n.node_ ? iterator(
- static_cast<node_pointer>(
- static_cast<node_pointer>(n.node_->group_prev_)->next_
- )) : n);
+ n, n.node_ ? iterator(n.node_->group_prev_->next_) : n);
}
// Equality
@@ -332,16 +294,13 @@ namespace boost { namespace unordered { namespace detail {
bool equals(grouped_table_impl const& other) const
{
if(this->size_ != other.size_) return false;
- if(!this->size_) return true;
- for(iterator n1 = this->get_start(); n1.node_;)
+ for(iterator n1 = this->begin(); n1.node_;)
{
iterator n2 = other.find_matching_node(n1);
if (!n2.node_) return false;
- iterator end1(static_cast<node_pointer>(
- static_cast<node_pointer>(n1.node_->group_prev_)->next_));
- iterator end2(static_cast<node_pointer>(
- static_cast<node_pointer>(n2.node_->group_prev_)->next_));
+ iterator end1(n1.node_->group_prev_->next_);
+ iterator end2(n2.node_->group_prev_->next_);
if (!group_equals(n1, end1, n2, end2)) return false;
n1 = end1;
}
@@ -349,8 +308,6 @@ namespace boost { namespace unordered { namespace detail {
return true;
}
-#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
-
static bool group_equals(iterator n1, iterator end1,
iterator n2, iterator end2)
{
@@ -411,37 +368,16 @@ namespace boost { namespace unordered { namespace detail {
return count;
}
-#else
-
- static bool group_equals(iterator n1, iterator end1,
- iterator n2, iterator end2)
- {
- for(;;)
- {
- if(!extractor::compare_mapped(*n1, *n2))
- return false;
-
- ++n1;
- ++n2;
-
- if (n1 == end1) return n2 == end2;
- if (n2 == end2) return false;
- }
- }
-
-#endif
-
// Emplace/Insert
static inline void add_after_node(
node_pointer n,
node_pointer pos)
{
- n->next_ = static_cast<node_pointer>(pos->group_prev_)->next_;
+ n->next_ = 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);
+ pos->group_prev_->next_ = n;
+ pos->group_prev_ = n;
}
inline iterator add_node(
@@ -454,37 +390,35 @@ namespace boost { namespace unordered { namespace detail {
if (pos.node_) {
this->add_after_node(n, pos.node_);
if (n->next_) {
- std::size_t next_bucket = policy::to_bucket(
- this->bucket_count_,
+ std::size_t next_bucket = this->hash_to_bucket(
static_cast<node_pointer>(n->next_)->hash_);
- if (next_bucket !=
- policy::to_bucket(this->bucket_count_, key_hash)) {
+ if (next_bucket != this->hash_to_bucket(key_hash)) {
this->get_bucket(next_bucket)->next_ = n;
}
}
}
else {
bucket_pointer b = this->get_bucket(
- policy::to_bucket(this->bucket_count_, key_hash));
+ this->hash_to_bucket(key_hash));
if (!b->next_)
{
- previous_pointer start_node = this->get_previous_start();
+ link_pointer start_node = this->get_previous_start();
if (start_node->next_) {
- this->get_bucket(policy::to_bucket(this->bucket_count_,
+ this->get_bucket(this->hash_to_bucket(
static_cast<node_pointer>(start_node->next_)->hash_
))->next_ = n;
}
b->next_ = start_node;
n->next_ = start_node->next_;
- start_node->next_ = static_cast<link_pointer>(n);
+ start_node->next_ = n;
}
else
{
n->next_ = b->next_->next_;
- b->next_->next_ = static_cast<link_pointer>(n);
+ b->next_->next_ = n;
}
}
++this->size_;
@@ -510,8 +444,8 @@ namespace boost { namespace unordered { namespace detail {
this->add_node(a, key_hash, this->find_node(key_hash, k));
}
-#if defined(BOOST_NO_RVALUE_REFERENCES)
-# if defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+# if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
iterator emplace(boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
@@ -532,8 +466,7 @@ namespace boost { namespace unordered { namespace detail {
iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
node_constructor a(this->node_alloc());
- a.construct_node();
- a.construct_value(BOOST_UNORDERED_EMPLACE_FORWARD);
+ a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
return iterator(emplace_impl(a));
}
@@ -552,8 +485,7 @@ namespace boost { namespace unordered { namespace detail {
std::size_t distance = boost::unordered::detail::distance(i, j);
if(distance == 1) {
node_constructor a(this->node_alloc());
- a.construct_node();
- a.construct_value2(*i);
+ a.construct_with_value2(*i);
emplace_impl(a);
}
else {
@@ -562,8 +494,7 @@ namespace boost { namespace unordered { namespace detail {
node_constructor a(this->node_alloc());
for (; i != j; ++i) {
- a.construct_node();
- a.construct_value2(*i);
+ a.construct_with_value2(*i);
emplace_impl_no_rehash(a);
}
}
@@ -575,8 +506,7 @@ namespace boost { namespace unordered { namespace detail {
{
node_constructor a(this->node_alloc());
for (; i != j; ++i) {
- a.construct_node();
- a.construct_value2(*i);
+ a.construct_with_value2(*i);
emplace_impl(a);
}
}
@@ -591,11 +521,8 @@ namespace boost { namespace unordered { namespace detail {
if(!this->size_) return 0;
std::size_t key_hash = this->hash(k);
- std::size_t bucket_index =
- policy::to_bucket(this->bucket_count_, key_hash);
- bucket_pointer this_bucket = this->get_bucket(bucket_index);
-
- previous_pointer prev = this_bucket->next_;
+ std::size_t bucket_index = this->hash_to_bucket(key_hash);
+ link_pointer prev = this->get_previous_start(bucket_index);
if (!prev) return 0;
for (;;)
@@ -603,24 +530,21 @@ namespace boost { namespace unordered { namespace detail {
if (!prev->next_) return 0;
std::size_t node_hash =
static_cast<node_pointer>(prev->next_)->hash_;
- if (policy::to_bucket(this->bucket_count_, node_hash)
- != bucket_index)
+ if (this->hash_to_bucket(node_hash) != bucket_index)
return 0;
if (node_hash == key_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_);
+ prev = 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(this_bucket, prev, end);
- return this->delete_nodes(c_iterator(pos), c_iterator(end));
+ node_pointer first_node = static_cast<node_pointer>(prev->next_);
+ link_pointer end = first_node->group_prev_->next_;
+
+ std::size_t deleted_count = this->delete_nodes(prev, end);
+ this->fix_bucket(bucket_index, prev);
+ return deleted_count;
}
iterator erase(c_iterator r)
@@ -628,217 +552,94 @@ namespace boost { namespace unordered { namespace detail {
BOOST_ASSERT(r.node_);
iterator next(r.node_);
++next;
-
- bucket_pointer this_bucket = this->get_bucket(
- policy::to_bucket(this->bucket_count_, r.node_->hash_));
- previous_pointer prev = unlink_node(*this_bucket, r.node_);
-
- this->fix_buckets(this_bucket, prev, next.node_);
-
- this->delete_node(r);
-
+ erase_nodes(r.node_, next.node_);
return next;
}
iterator erase_range(c_iterator r1, c_iterator r2)
{
if (r1 == r2) return iterator(r2.node_);
-
- std::size_t bucket_index =
- policy::to_bucket(this->bucket_count_, r1.node_->hash_);
- previous_pointer prev = unlink_nodes(
- *this->get_bucket(bucket_index), r1.node_, r2.node_);
- this->fix_buckets_range(bucket_index, prev, r1.node_, r2.node_);
- this->delete_nodes(r1, r2);
-
+ erase_nodes(r1.node_, r2.node_);
return iterator(r2.node_);
}
- static previous_pointer unlink_node(bucket& b, node_pointer n)
+ link_pointer erase_nodes(node_pointer i, node_pointer j)
{
- 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_;
+ std::size_t bucket_index = this->hash_to_bucket(i->hash_);
+
+ // Split the groups containing 'i' and 'j'.
+ // And get the pointer to the node before i while
+ // we're at it.
+ link_pointer prev = split_groups(i, j);
+
+ // If we don't have a 'prev' it means that i is at the
+ // beginning of a block, so search through the blocks in the
+ // same bucket.
+ if (!prev) {
+ prev = this->get_previous_start(bucket_index);
+ while (prev->next_ != i)
+ prev = static_cast<node_pointer>(prev->next_)->group_prev_;
}
- prev->next_ = static_cast<link_pointer>(next);
+ // Delete the nodes.
+ do {
+ link_pointer group_end =
+ static_cast<node_pointer>(prev->next_)->group_prev_->next_;
+ this->delete_nodes(prev, group_end);
+ bucket_index = this->fix_bucket(bucket_index, prev);
+ } while(prev->next_ != j);
+
return prev;
}
- static previous_pointer unlink_nodes(bucket& b,
- node_pointer begin, node_pointer end)
+ static link_pointer split_groups(node_pointer i, node_pointer j)
{
- previous_pointer prev = static_cast<previous_pointer>(
- begin->group_prev_);
+ node_pointer prev = i->group_prev_;
+ if (prev->next_ != i) prev = node_pointer();
- 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 (j) {
+ node_pointer first = j;
+ while (first != i && first->group_prev_->next_ == first) {
+ first = first->group_prev_;
+ }
- if (end) split_group(end);
+ boost::swap(first->group_prev_, j->group_prev_);
+ if (first == i) return prev;
}
- 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;
- }
+ if (prev) {
+ node_pointer first = prev;
+ while (first->group_prev_->next_ == first) {
+ first = first->group_prev_;
}
+ boost::swap(first->group_prev_, i->group_prev_);
}
- 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.
+ // fill_buckets
- static void copy_buckets_to(buckets const& src, buckets& dst)
+ template <class NodeCreator>
+ static void fill_buckets(iterator n, table& dst,
+ NodeCreator& creator)
{
- BOOST_ASSERT(!dst.buckets_);
-
- dst.create_buckets();
-
- node_constructor a(dst.node_alloc());
-
- iterator n = src.get_start();
- previous_pointer prev = dst.get_previous_start();
+ link_pointer prev = dst.get_previous_start();
while (n.node_) {
std::size_t key_hash = n.node_->hash_;
- iterator group_end(
- static_cast<node_pointer>(
- static_cast<node_pointer>(n.node_->group_prev_)->next_
- ));
-
- a.construct_node();
- a.construct_value2(*n);
+ iterator group_end(n.node_->group_prev_->next_);
- node_pointer first_node = a.release();
+ node_pointer first_node = creator.create(*n);
node_pointer end = first_node;
first_node->hash_ = key_hash;
- prev->next_ = static_cast<link_pointer>(first_node);
+ prev->next_ = first_node;
++dst.size_;
for (++n; n != group_end; ++n)
{
- a.construct_node();
- a.construct_value2(*n);
- end = a.release();
- end->hash_ = key_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());
-
- iterator n = src.get_start();
- previous_pointer prev = dst.get_previous_start();
-
- while (n.node_) {
- std::size_t key_hash = n.node_->hash_;
- iterator group_end(
- static_cast<node_pointer>(
- static_cast<node_pointer>(n.node_->group_prev_)->next_
- ));
-
- a.construct_node();
- a.construct_value2(boost::move(*n));
-
- node_pointer first_node = a.release();
- node_pointer end = first_node;
- first_node->hash_ = key_hash;
- prev->next_ = static_cast<link_pointer>(first_node);
- ++dst.size_;
-
- for(++n; n != group_end; ++n)
- {
- a.construct_node();
- a.construct_value2(boost::move(*n));
- end = a.release();
+ end = creator.create(*n);
end->hash_ = key_hash;
add_after_node(end, first_node);
++dst.size_;
@@ -851,41 +652,25 @@ namespace boost { namespace unordered { namespace detail {
// 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();
+ BOOST_ASSERT(this->buckets_);
- dst_start->next_ = src_start->next_;
- src_start->next_ = link_pointer();
- dst.size_ = this->size_;
- this->size_ = 0;
-
- previous_pointer prev = dst_start;
+ this->create_buckets(num_buckets);
+ link_pointer prev = this->get_previous_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
+ prev = place_in_bucket(*this, prev,
+ static_cast<node_pointer>(prev->next_)->group_prev_);
}
// 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)
+ static link_pointer place_in_bucket(table& dst,
+ link_pointer prev, node_pointer end)
{
- bucket_pointer b = dst.get_bucket(policy::to_bucket(
- dst.bucket_count_, end->hash_));
+ bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(end->hash_));
if (!b->next_) {
- b->next_ = static_cast<node_pointer>(prev);
- return static_cast<previous_pointer>(end);
+ b->next_ = prev;
+ return end;
}
else {
link_pointer next = end->next_;
diff --git a/boost/unordered/detail/extract_key.hpp b/boost/unordered/detail/extract_key.hpp
index 56a85324ba..d68a4a77ef 100644
--- a/boost/unordered/detail/extract_key.hpp
+++ b/boost/unordered/detail/extract_key.hpp
@@ -6,6 +6,11 @@
#ifndef BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
+#include <boost/config.hpp>
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#pragma once
+#endif
+
#include <boost/unordered/detail/table.hpp>
namespace boost {
@@ -56,30 +61,25 @@ namespace detail {
return no_key();
}
-#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
- template <class... Args>
- static no_key extract(Args const&...)
- {
- return no_key();
- }
-#else
template <class Arg>
static no_key extract(Arg const&)
{
return no_key();
}
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template <class Arg1, class Arg2, class... Args>
+ static no_key extract(Arg1 const&, Arg2 const&, Args const&...)
+ {
+ return no_key();
+ }
+#else
template <class Arg1, class Arg2>
static no_key extract(Arg1 const&, Arg2 const&)
{
return no_key();
}
#endif
-
- static bool compare_mapped(value_type const&, value_type const&)
- {
- return true;
- }
};
template <class Key, class ValueType>
@@ -93,11 +93,6 @@ namespace detail {
return v.first;
}
- static key_type const& extract(key_type const& v)
- {
- return v;
- }
-
template <class Second>
static key_type const& extract(std::pair<key_type, Second> const& v)
{
@@ -111,21 +106,6 @@ namespace detail {
return v.first;
}
-#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
- template <class Arg1, class... Args>
- static key_type const& extract(key_type const& k,
- Arg1 const&, Args const&...)
- {
- return k;
- }
-
- template <class... Args>
- static no_key extract(Args const&...)
- {
- return no_key();
- }
-#else
-
template <class Arg1>
static key_type const& extract(key_type const& k, Arg1 const&)
{
@@ -143,19 +123,27 @@ namespace detail {
return no_key();
}
- template <class Arg, class Arg1>
- static no_key extract(Arg const&, Arg1 const&)
+ template <class Arg1, class Arg2>
+ static no_key extract(Arg1 const&, Arg2 const&)
+ {
+ return no_key();
+ }
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template <class Arg1, class Arg2, class Arg3, class... Args>
+ static no_key extract(Arg1 const&, Arg2 const&, Arg3 const&,
+ Args const&...)
{
return no_key();
}
#endif
-#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
template <typename T2> \
static no_key extract(boost::unordered::piecewise_construct_t, \
- namespace_::tuple<> const&, BOOST_FWD_REF(T2)) \
+ namespace_ tuple<> const&, T2 const&) \
{ \
return no_key(); \
} \
@@ -163,17 +151,17 @@ namespace detail {
template <typename T, typename T2> \
static typename is_key<key_type, T>::type \
extract(boost::unordered::piecewise_construct_t, \
- namespace_::tuple<T> const& k, BOOST_FWD_REF(T2)) \
+ namespace_ tuple<T> const& k, T2 const&) \
{ \
return typename is_key<key_type, T>::type( \
- namespace_::get<0>(k)); \
+ namespace_ get<0>(k)); \
}
#else
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
static no_key extract(boost::unordered::piecewise_construct_t, \
- namespace_::tuple<> const&) \
+ namespace_ tuple<> const&) \
{ \
return no_key(); \
} \
@@ -181,25 +169,19 @@ namespace detail {
template <typename T> \
static typename is_key<key_type, T>::type \
extract(boost::unordered::piecewise_construct_t, \
- namespace_::tuple<T> const& k) \
+ namespace_ tuple<T> const& k) \
{ \
return typename is_key<key_type, T>::type( \
- namespace_::get<0>(k)); \
+ namespace_ get<0>(k)); \
}
#endif
-BOOST_UNORDERED_KEY_FROM_TUPLE(boost)
+BOOST_UNORDERED_KEY_FROM_TUPLE(boost::)
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
-BOOST_UNORDERED_KEY_FROM_TUPLE(std)
+BOOST_UNORDERED_KEY_FROM_TUPLE(std::)
#endif
-
-
- static bool compare_mapped(value_type const& x, value_type const& y)
- {
- return x.second == y.second;
- }
};
}}}
diff --git a/boost/unordered/detail/fwd.hpp b/boost/unordered/detail/fwd.hpp
index ee8966b755..87c2c23b04 100644
--- a/boost/unordered/detail/fwd.hpp
+++ b/boost/unordered/detail/fwd.hpp
@@ -6,11 +6,11 @@
#ifndef BOOST_UNORDERED_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_FWD_HPP_INCLUDED
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
+#include <boost/config.hpp>
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#pragma once
#endif
-
namespace boost
{
namespace unordered
diff --git a/boost/unordered/detail/table.hpp b/boost/unordered/detail/table.hpp
index cbf6219554..2bb5d45003 100644
--- a/boost/unordered/detail/table.hpp
+++ b/boost/unordered/detail/table.hpp
@@ -7,12 +7,34 @@
#ifndef BOOST_UNORDERED_DETAIL_ALL_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_ALL_HPP_INCLUDED
+#include <boost/config.hpp>
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#pragma once
+#endif
+
#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 <cmath>
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+#pragma warning(disable:4127) // conditional expression is constant
+#endif
+
+#if defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
+
+#if defined(__EDG__)
+#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
+#pragma message("Warning: BOOST_UNORDERED_DEPRECATED_EQUALITY is no longer supported.")
+#elif defined(__GNUC__) || defined(__HP_aCC) || \
+ defined(__SUNPRO_CC) || defined(__IBMCPP__)
+#warning "BOOST_UNORDERED_DEPRECATED_EQUALITY is no longer supported."
+#endif
+
+#endif
+
namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////////
@@ -37,6 +59,10 @@ namespace boost { namespace unordered { namespace detail {
sizeof(value_type),
boost::alignment_of<value_type>::value>::type data_;
+ value_base() :
+ data_()
+ {}
+
void* address() {
return this;
}
@@ -54,13 +80,72 @@ namespace boost { namespace unordered { namespace detail {
value_base& operator=(value_base const&);
};
+ template <typename NodeAlloc>
+ struct copy_nodes
+ {
+ typedef boost::unordered::detail::allocator_traits<NodeAlloc>
+ node_allocator_traits;
+
+ node_constructor<NodeAlloc> constructor;
+
+ explicit copy_nodes(NodeAlloc& a) : constructor(a) {}
+
+ typename node_allocator_traits::pointer create(
+ typename node_allocator_traits::value_type::value_type const& v)
+ {
+ constructor.construct_with_value2(v);
+ return constructor.release();
+ }
+ };
+
+ template <typename NodeAlloc>
+ struct move_nodes
+ {
+ typedef boost::unordered::detail::allocator_traits<NodeAlloc>
+ node_allocator_traits;
+
+ node_constructor<NodeAlloc> constructor;
+
+ explicit move_nodes(NodeAlloc& a) : constructor(a) {}
+
+ typename node_allocator_traits::pointer create(
+ typename node_allocator_traits::value_type::value_type& v)
+ {
+ constructor.construct_with_value2(boost::move(v));
+ return constructor.release();
+ }
+ };
+
+ template <typename Buckets>
+ struct assign_nodes
+ {
+ node_holder<typename Buckets::node_allocator> holder;
+
+ explicit assign_nodes(Buckets& b) : holder(b) {}
+
+ typename Buckets::node_pointer create(
+ typename Buckets::value_type const& v)
+ {
+ return holder.copy_of(v);
+ }
+ };
+
+ template <typename Buckets>
+ struct move_assign_nodes
+ {
+ node_holder<typename Buckets::node_allocator> holder;
+
+ explicit move_assign_nodes(Buckets& b) : holder(b) {}
+
+ typename Buckets::node_pointer create(
+ typename Buckets::value_type& v)
+ {
+ return holder.move_copy_of(v);
+ }
+ };
+
template <typename Types>
struct table :
- boost::unordered::detail::buckets<
- typename Types::allocator,
- typename Types::bucket,
- typename Types::node,
- typename Types::policy>,
boost::unordered::detail::functions<
typename Types::hasher,
typename Types::key_equal>
@@ -69,6 +154,8 @@ namespace boost { namespace unordered { namespace detail {
table(table const&);
table& operator=(table const&);
public:
+ typedef typename Types::node node;
+ typedef typename Types::bucket bucket;
typedef typename Types::hasher hasher;
typedef typename Types::key_equal key_equal;
typedef typename Types::key_type key_type;
@@ -81,24 +168,130 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::functions<
typename Types::hasher,
typename Types::key_equal> functions;
+ typedef typename functions::set_hash_functions set_hash_functions;
+
+ typedef typename Types::allocator allocator;
+ typedef typename boost::unordered::detail::
+ rebind_wrap<allocator, node>::type node_allocator;
+ typedef typename boost::unordered::detail::
+ rebind_wrap<allocator, 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 boost::unordered::detail::node_constructor<node_allocator>
+ node_constructor;
+
+ typedef boost::unordered::iterator_detail::
+ iterator<node> iterator;
+ typedef boost::unordered::iterator_detail::
+ c_iterator<node, const_node_pointer> c_iterator;
+ typedef boost::unordered::iterator_detail::
+ l_iterator<node, policy> l_iterator;
+ typedef boost::unordered::iterator_detail::
+ cl_iterator<node, const_node_pointer, policy> cl_iterator;
- typedef boost::unordered::detail::buckets<
- typename Types::allocator,
- typename Types::bucket,
- typename Types::node,
- typename Types::policy> buckets;
+ ////////////////////////////////////////////////////////////////////////
+ // Members
- 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;
+ boost::unordered::detail::compressed<bucket_allocator, node_allocator>
+ allocators_;
+ std::size_t bucket_count_;
+ std::size_t size_;
+ float mlf_;
+ std::size_t max_load_;
+ bucket_pointer buckets_;
- typedef typename table::iterator iterator;
+ ////////////////////////////////////////////////////////////////////////
+ // Data access
- // Members
+ bucket_allocator const& bucket_alloc() const
+ {
+ return allocators_.first();
+ }
- float mlf_;
- std::size_t max_load_; // Only use if this->buckets_.
+ node_allocator const& node_alloc() const
+ {
+ return allocators_.second();
+ }
+
+ bucket_allocator& bucket_alloc()
+ {
+ return allocators_.first();
+ }
+
+ node_allocator& node_alloc()
+ {
+ return allocators_.second();
+ }
+
+ std::size_t max_bucket_count() const
+ {
+ // -1 to account for the start bucket.
+ return policy::prev_bucket_count(
+ bucket_allocator_traits::max_size(bucket_alloc()) - 1);
+ }
+
+ bucket_pointer get_bucket(std::size_t bucket_index) const
+ {
+ BOOST_ASSERT(buckets_);
+ return buckets_ + static_cast<std::ptrdiff_t>(bucket_index);
+ }
+
+ link_pointer get_previous_start() const
+ {
+ return get_bucket(bucket_count_)->first_from_start();
+ }
+
+ link_pointer get_previous_start(std::size_t bucket_index) const
+ {
+ return get_bucket(bucket_index)->next_;
+ }
+
+ iterator begin() const
+ {
+ return size_ ? iterator(get_previous_start()->next_) : iterator();
+ }
+
+ iterator begin(std::size_t bucket_index) const
+ {
+ if (!size_) return iterator();
+ link_pointer prev = get_previous_start(bucket_index);
+ return prev ? iterator(prev->next_) : iterator();
+ }
+
+ std::size_t hash_to_bucket(std::size_t hash_value) const
+ {
+ return policy::to_bucket(bucket_count_, hash_value);
+ }
+
+ float load_factor() const
+ {
+ BOOST_ASSERT(bucket_count_ != 0);
+ return static_cast<float>(size_)
+ / static_cast<float>(bucket_count_);
+ }
+
+ std::size_t bucket_size(std::size_t index) const
+ {
+ iterator it = begin(index);
+ if (!it.node_) return 0;
+
+ std::size_t count = 0;
+ while(it.node_ && hash_to_bucket(it.node_->hash_) == index)
+ {
+ ++count;
+ ++it;
+ }
+
+ return count;
+ }
////////////////////////////////////////////////////////////////////////
// Load methods
@@ -109,34 +302,34 @@ namespace boost { namespace unordered { namespace detail {
// size < mlf_ * count
return boost::unordered::detail::double_to_size(ceil(
- static_cast<double>(this->mlf_) *
- static_cast<double>(this->max_bucket_count())
+ static_cast<double>(mlf_) *
+ static_cast<double>(max_bucket_count())
)) - 1;
}
- std::size_t calculate_max_load()
+ void recalculate_max_load()
{
using namespace std;
// From 6.3.1/13:
// Only resize when size >= mlf_ * count
- return boost::unordered::detail::double_to_size(ceil(
- static_cast<double>(this->mlf_) *
- static_cast<double>(this->bucket_count_)
- ));
+ max_load_ = buckets_ ? boost::unordered::detail::double_to_size(ceil(
+ static_cast<double>(mlf_) *
+ static_cast<double>(bucket_count_)
+ )) : 0;
}
+
void max_load_factor(float z)
{
BOOST_ASSERT(z > 0);
mlf_ = (std::max)(z, minimum_max_load_factor);
- if (this->buckets_)
- this->max_load_ = this->calculate_max_load();
+ recalculate_max_load();
}
std::size_t min_buckets_for_size(std::size_t size) const
{
- BOOST_ASSERT(this->mlf_ >= minimum_max_load_factor);
+ BOOST_ASSERT(mlf_ >= minimum_max_load_factor);
using namespace std;
@@ -160,177 +353,407 @@ namespace boost { namespace unordered { namespace detail {
hasher const& hf,
key_equal const& eq,
node_allocator const& a) :
- buckets(a, policy::new_bucket_count(num_buckets)),
functions(hf, eq),
+ allocators_(a,a),
+ bucket_count_(policy::new_bucket_count(num_buckets)),
+ size_(0),
mlf_(1.0f),
- max_load_(0)
+ max_load_(0),
+ buckets_()
{}
table(table const& x, node_allocator const& a) :
- buckets(a, x.min_buckets_for_size(x.size_)),
functions(x),
+ allocators_(a,a),
+ bucket_count_(x.min_buckets_for_size(x.size_)),
+ size_(0),
mlf_(x.mlf_),
- max_load_(0)
- {
- if(x.size_) {
- table_impl::copy_buckets_to(x, *this);
- this->max_load_ = calculate_max_load();
- }
- }
+ max_load_(0),
+ buckets_()
+ {}
- // TODO: Why calculate_max_load?
table(table& x, boost::unordered::detail::move_tag m) :
- buckets(x, m),
- functions(x),
+ functions(x, m),
+ allocators_(x.allocators_, m),
+ bucket_count_(x.bucket_count_),
+ size_(x.size_),
mlf_(x.mlf_),
- max_load_(calculate_max_load())
- {}
+ max_load_(x.max_load_),
+ buckets_(x.buckets_)
+ {
+ x.buckets_ = bucket_pointer();
+ x.size_ = 0;
+ x.max_load_ = 0;
+ }
- // TODO: Why not calculate_max_load?
- // TODO: Why do I use x's bucket count?
table(table& x, node_allocator const& a,
boost::unordered::detail::move_tag m) :
- buckets(a, x.bucket_count_),
- functions(x),
+ functions(x, m),
+ allocators_(a, a),
+ bucket_count_(x.bucket_count_),
+ size_(0),
mlf_(x.mlf_),
- max_load_(x.max_load_)
+ max_load_(x.max_load_),
+ buckets_()
+ {}
+
+ ////////////////////////////////////////////////////////////////////////
+ // Initialisation.
+
+ void init(table const& x)
{
- if(a == x.node_alloc()) {
- this->buckets::swap(x, false_type());
+ if (x.size_) {
+ create_buckets(bucket_count_);
+ copy_nodes<node_allocator> node_creator(node_alloc());
+ table_impl::fill_buckets(x.begin(), *this, node_creator);
+ }
+ }
+
+ void move_init(table& x)
+ {
+ if(node_alloc() == x.node_alloc()) {
+ move_buckets_from(x);
}
else if(x.size_) {
- // Use a temporary table because move_buckets_to leaves the
- // source container in a complete mess.
+ // TODO: Could pick new bucket size?
+ create_buckets(bucket_count_);
- buckets tmp(x, m);
- table_impl::move_buckets_to(tmp, *this);
- this->max_load_ = calculate_max_load();
+ move_nodes<node_allocator> node_creator(node_alloc());
+ node_holder<node_allocator> nodes(x);
+ table_impl::fill_buckets(nodes.begin(), *this, node_creator);
}
}
- // Iterators
+ ////////////////////////////////////////////////////////////////////////
+ // Create buckets
+
+ void create_buckets(std::size_t new_count)
+ {
+ boost::unordered::detail::array_constructor<bucket_allocator>
+ constructor(bucket_alloc());
+
+ // Creates an extra bucket to act as the start node.
+ constructor.construct(bucket(), new_count + 1);
+
+ if (buckets_)
+ {
+ // Copy the nodes to the new buckets, including the dummy
+ // node if there is one.
+ (constructor.get() +
+ static_cast<std::ptrdiff_t>(new_count))->next_ =
+ (buckets_ + static_cast<std::ptrdiff_t>(
+ bucket_count_))->next_;
+ destroy_buckets();
+ }
+ else if (bucket::extra_node)
+ {
+ node_constructor a(node_alloc());
+ a.construct();
+
+ (constructor.get() +
+ static_cast<std::ptrdiff_t>(new_count))->next_ =
+ a.release();
+ }
- iterator begin() const {
- return !this->buckets_ ?
- iterator() : this->get_start();
+ bucket_count_ = new_count;
+ buckets_ = constructor.release();
+ recalculate_max_load();
}
- // Assignment
+ ////////////////////////////////////////////////////////////////////////
+ // Swap and Move
- void assign(table const& x)
+ void swap_allocators(table& other, false_type)
+ {
+ boost::unordered::detail::func::ignore_unused_variable_warning(other);
+
+ // According to 23.2.1.8, if propagate_on_container_swap is
+ // false the behaviour is undefined unless the allocators
+ // are equal.
+ BOOST_ASSERT(node_alloc() == other.node_alloc());
+ }
+
+ void swap_allocators(table& other, true_type)
+ {
+ allocators_.swap(other.allocators_);
+ }
+
+ // Only swaps the allocators if propagate_on_container_swap
+ void swap(table& x)
{
- assign(x,
+ set_hash_functions op1(*this, x);
+ set_hash_functions op2(x, *this);
+
+ // I think swap can throw if Propagate::value,
+ // since the allocators' swap can throw. Not sure though.
+ swap_allocators(x,
boost::unordered::detail::integral_constant<bool,
allocator_traits<node_allocator>::
- propagate_on_container_copy_assignment::value>());
+ propagate_on_container_swap::value>());
+
+ boost::swap(buckets_, x.buckets_);
+ boost::swap(bucket_count_, x.bucket_count_);
+ boost::swap(size_, x.size_);
+ std::swap(mlf_, x.mlf_);
+ std::swap(max_load_, x.max_load_);
+ op1.commit();
+ op2.commit();
+ }
+
+ void move_buckets_from(table& other)
+ {
+ BOOST_ASSERT(node_alloc() == other.node_alloc());
+ BOOST_ASSERT(!buckets_);
+ buckets_ = other.buckets_;
+ bucket_count_ = other.bucket_count_;
+ size_ = other.size_;
+ other.buckets_ = bucket_pointer();
+ other.size_ = 0;
+ other.max_load_ = 0;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Delete/destruct
+
+ ~table()
+ {
+ delete_buckets();
+ }
+
+ void delete_node(link_pointer prev)
+ {
+ node_pointer n = static_cast<node_pointer>(prev->next_);
+ prev->next_ = n->next_;
+
+ boost::unordered::detail::func::destroy_value_impl(node_alloc(),
+ n->value_ptr());
+ boost::unordered::detail::func::destroy(boost::addressof(*n));
+ node_allocator_traits::deallocate(node_alloc(), n, 1);
+ --size_;
+ }
+
+ std::size_t delete_nodes(link_pointer prev, link_pointer end)
+ {
+ BOOST_ASSERT(prev->next_ != end);
+
+ std::size_t count = 0;
+
+ do {
+ delete_node(prev);
+ ++count;
+ } while (prev->next_ != end);
+
+ return count;
+ }
+
+ void delete_buckets()
+ {
+ if(buckets_) {
+ if (size_) delete_nodes(get_previous_start(), link_pointer());
+
+ if (bucket::extra_node) {
+ node_pointer n = static_cast<node_pointer>(
+ get_bucket(bucket_count_)->next_);
+ boost::unordered::detail::func::destroy(
+ boost::addressof(*n));
+ node_allocator_traits::deallocate(node_alloc(), n, 1);
+ }
+
+ destroy_buckets();
+ buckets_ = bucket_pointer();
+ max_load_ = 0;
+ }
+
+ BOOST_ASSERT(!size_);
+ }
+
+ void clear()
+ {
+ if (!size_) return;
+
+ delete_nodes(get_previous_start(), link_pointer());
+ clear_buckets();
+
+ BOOST_ASSERT(!size_);
+ }
+
+ void clear_buckets()
+ {
+ bucket_pointer end = get_bucket(bucket_count_);
+ for(bucket_pointer it = buckets_; it != end; ++it)
+ {
+ it->next_ = node_pointer();
+ }
+ }
+
+ void destroy_buckets()
+ {
+ bucket_pointer end = get_bucket(bucket_count_ + 1);
+ for(bucket_pointer it = buckets_; it != end; ++it)
+ {
+ boost::unordered::detail::func::destroy(
+ boost::addressof(*it));
+ }
+
+ bucket_allocator_traits::deallocate(bucket_alloc(),
+ buckets_, bucket_count_ + 1);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Fix buckets after delete
+ //
+
+ std::size_t fix_bucket(std::size_t bucket_index, link_pointer prev)
+ {
+ link_pointer end = prev->next_;
+ std::size_t bucket_index2 = bucket_index;
+
+ if (end)
+ {
+ bucket_index2 = hash_to_bucket(
+ static_cast<node_pointer>(end)->hash_);
+
+ // If begin and end are in the same bucket, then
+ // there's nothing to do.
+ if (bucket_index == bucket_index2) return bucket_index2;
+
+ // Update the bucket containing end.
+ get_bucket(bucket_index2)->next_ = prev;
+ }
+
+ // Check if this bucket is now empty.
+ bucket_pointer this_bucket = get_bucket(bucket_index);
+ if (this_bucket->next_ == prev)
+ this_bucket->next_ = link_pointer();
+
+ return bucket_index2;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Assignment
+
+ void assign(table const& x)
+ {
+ if (this != boost::addressof(x))
+ {
+ 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)
{
- table tmp(x, this->node_alloc());
- this->swap(tmp, false_type());
+ // Strong exception safety.
+ set_hash_functions new_func_this(*this, x);
+ new_func_this.commit();
+ mlf_ = x.mlf_;
+ recalculate_max_load();
+
+ if (!size_ && !x.size_) return;
+
+ if (x.size_ >= max_load_) {
+ create_buckets(min_buckets_for_size(x.size_));
+ }
+ else {
+ clear_buckets();
+ }
+
+ // assign_nodes takes ownership of the container's elements,
+ // assigning to them if possible, and deleting any that are
+ // left over.
+ assign_nodes<table> node_creator(*this);
+ table_impl::fill_buckets(x.begin(), *this, node_creator);
}
void assign(table const& x, true_type)
{
- table tmp(x, x.node_alloc());
- // Need to delete before setting the allocator so that buckets
- // aren't deleted with the wrong allocator.
- if(this->buckets_) this->delete_buckets();
- // TODO: Can allocator assignment throw?
- this->allocators_.assign(x.allocators_);
- this->swap(tmp, false_type());
+ if (node_alloc() == x.node_alloc()) {
+ allocators_.assign(x.allocators_);
+ assign(x, false_type());
+ }
+ else {
+ set_hash_functions new_func_this(*this, x);
+
+ // Delete everything with current allocators before assigning
+ // the new ones.
+ delete_buckets();
+ allocators_.assign(x.allocators_);
+
+ // Copy over other data, all no throw.
+ new_func_this.commit();
+ mlf_ = x.mlf_;
+ bucket_count_ = min_buckets_for_size(x.size_);
+ max_load_ = 0;
+
+ // Finally copy the elements.
+ if (x.size_) {
+ create_buckets(bucket_count_);
+ copy_nodes<node_allocator> node_creator(node_alloc());
+ table_impl::fill_buckets(x.begin(), *this, node_creator);
+ }
+ }
}
void move_assign(table& x)
{
- move_assign(x,
- boost::unordered::detail::integral_constant<bool,
- allocator_traits<node_allocator>::
- propagate_on_container_move_assignment::value>());
+ if (this != boost::addressof(x))
+ {
+ 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();
- this->allocators_.move_assign(x.allocators_);
+ delete_buckets();
+ allocators_.move_assign(x.allocators_);
move_assign_no_alloc(x);
}
void move_assign(table& x, false_type)
{
- if(this->node_alloc() == x.node_alloc()) {
- if(this->buckets_) this->delete_buckets();
+ if (node_alloc() == x.node_alloc()) {
+ delete_buckets();
move_assign_no_alloc(x);
}
else {
- boost::unordered::detail::set_hash_functions<hasher, key_equal>
- new_func_this(*this, x);
+ set_hash_functions new_func_this(*this, x);
+ new_func_this.commit();
+ mlf_ = x.mlf_;
+ recalculate_max_load();
- if (x.size_) {
- buckets b(this->node_alloc(),
- x.min_buckets_for_size(x.size_));
- buckets tmp(x, move_tag());
- table_impl::move_buckets_to(tmp, b);
- b.swap(*this);
+ if (!size_ && !x.size_) return;
+
+ if (x.size_ >= max_load_) {
+ create_buckets(min_buckets_for_size(x.size_));
}
else {
- this->clear();
+ clear_buckets();
}
-
- this->mlf_ = x.mlf_;
- if (this->buckets_) this->max_load_ = calculate_max_load();
- new_func_this.commit();
+
+ // move_assign_nodes takes ownership of the container's
+ // elements, assigning to them if possible, and deleting
+ // any that are left over.
+ move_assign_nodes<table> node_creator(*this);
+ node_holder<node_allocator> nodes(x);
+ table_impl::fill_buckets(nodes.begin(), *this, node_creator);
}
}
void move_assign_no_alloc(table& x)
{
- boost::unordered::detail::set_hash_functions<hasher, key_equal>
- new_func_this(*this, x);
+ set_hash_functions new_func_this(*this, x);
// No throw from here.
- this->move_buckets_from(x);
- this->mlf_ = x.mlf_;
- this->max_load_ = x.max_load_;
+ mlf_ = x.mlf_;
+ max_load_ = x.max_load_;
+ move_buckets_from(x);
new_func_this.commit();
}
- ////////////////////////////////////////////////////////////////////////
- // Swap & Move
-
- void swap(table& x)
- {
- swap(x,
- boost::unordered::detail::integral_constant<bool,
- allocator_traits<node_allocator>::
- propagate_on_container_swap::value>());
- }
-
- // Only swaps the allocators if Propagate::value
- template <typename Propagate>
- void swap(table& x, Propagate p)
- {
- 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);
- std::swap(this->mlf_, x.mlf_);
- std::swap(this->max_load_, x.max_load_);
- op1.commit();
- op2.commit();
- }
-
- // Swap everything but the allocators, and the functions objects.
- void swap_contents(table& x)
- {
- this->buckets::swap(x, false_type());
- std::swap(this->mlf_, x.mlf_);
- std::swap(this->max_load_, x.max_load_);
- }
-
// Accessors
key_type const& get_key(value_type const& x) const
@@ -351,7 +774,6 @@ namespace boost { namespace unordered { namespace detail {
Hash const& hf,
Pred const& eq) const
{
- if (!this->size_) return iterator();
return static_cast<table_impl const*>(this)->
find_node_impl(policy::apply_hash(hf, k), k, eq);
}
@@ -360,16 +782,14 @@ namespace boost { namespace unordered { namespace detail {
std::size_t key_hash,
key_type const& k) const
{
- if (!this->size_) return iterator();
return static_cast<table_impl const*>(this)->
find_node_impl(key_hash, k, this->key_eq());
}
iterator find_node(key_type const& k) const
{
- if (!this->size_) return iterator();
return static_cast<table_impl const*>(this)->
- find_node_impl(this->hash(k), k, this->key_eq());
+ find_node_impl(hash(k), k, this->key_eq());
}
iterator find_matching_node(iterator n) const
@@ -397,22 +817,19 @@ namespace boost { namespace unordered { namespace detail {
template <typename Types>
inline void table<Types>::reserve_for_insert(std::size_t size)
{
- if (!this->buckets_) {
- this->bucket_count_ = (std::max)(this->bucket_count_,
- this->min_buckets_for_size(size));
- this->create_buckets();
- this->max_load_ = this->calculate_max_load();
+ if (!buckets_) {
+ create_buckets((std::max)(bucket_count_,
+ min_buckets_for_size(size)));
}
// 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)));
- if (num_buckets != this->bucket_count_) {
+ = min_buckets_for_size((std::max)(size,
+ size_ + (size_ >> 1)));
+
+ if (num_buckets != bucket_count_)
static_cast<table_impl*>(this)->rehash_impl(num_buckets);
- this->max_load_ = this->calculate_max_load();
- }
}
}
@@ -424,20 +841,18 @@ namespace boost { namespace unordered { namespace detail {
{
using namespace std;
- if(!this->size_) {
- if(this->buckets_) this->delete_buckets();
- this->bucket_count_ = policy::new_bucket_count(min_buckets);
+ if(!size_) {
+ delete_buckets();
+ bucket_count_ = policy::new_bucket_count(min_buckets);
}
else {
min_buckets = policy::new_bucket_count((std::max)(min_buckets,
boost::unordered::detail::double_to_size(floor(
- static_cast<double>(this->size_) /
+ static_cast<double>(size_) /
static_cast<double>(mlf_))) + 1));
- if(min_buckets != this->bucket_count_) {
+ if(min_buckets != bucket_count_)
static_cast<table_impl*>(this)->rehash_impl(min_buckets);
- this->max_load_ = this->calculate_max_load();
- }
}
}
@@ -445,8 +860,12 @@ namespace boost { namespace unordered { namespace detail {
inline void table<Types>::reserve(std::size_t num_elements)
{
rehash(static_cast<std::size_t>(
- std::ceil(static_cast<double>(num_elements) / this->mlf_)));
+ std::ceil(static_cast<double>(num_elements) / mlf_)));
}
}}}
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#endif
+
#endif
diff --git a/boost/unordered/detail/unique.hpp b/boost/unordered/detail/unique.hpp
index 10db58fa75..f76ca5a6a5 100644
--- a/boost/unordered/detail/unique.hpp
+++ b/boost/unordered/detail/unique.hpp
@@ -7,8 +7,9 @@
#ifndef BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
+#include <boost/config.hpp>
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#pragma once
#endif
#include <boost/unordered/detail/table.hpp>
@@ -24,43 +25,23 @@ namespace boost { namespace unordered { namespace detail {
template <typename A, typename T>
struct unique_node :
- boost::unordered::detail::node_base<
- typename ::boost::unordered::detail::rebind_wrap<
- A, unique_node<A, T> >::type::pointer
- >,
boost::unordered::detail::value_base<T>
{
typedef typename ::boost::unordered::detail::rebind_wrap<
- A, unique_node<A, T> >::type::pointer link_pointer;
- typedef boost::unordered::detail::node_base<link_pointer> node_base;
+ A, unique_node<A, T> >::type allocator;
+ typedef typename ::boost::unordered::detail::
+ allocator_traits<allocator>::pointer node_pointer;
+ typedef node_pointer link_pointer;
+ link_pointer next_;
std::size_t hash_;
-#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
- template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
- explicit unique_node(BOOST_UNORDERED_EMPLACE_ARGS) :
- node_base(),
- hash_(0)
- {
- boost::unordered::detail::construct_impl(
- this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
- }
-
- ~unique_node() {
- boost::unordered::detail::destroy(this->value_ptr());
- }
-
- unique_node(unique_node const&) {
- BOOST_ASSERT(false);
- }
-#else
unique_node() :
- node_base(),
+ next_(),
hash_(0)
{}
-#endif
- void init(link_pointer)
+ void init(node_pointer)
{
}
@@ -70,43 +51,29 @@ namespace boost { namespace unordered { namespace detail {
template <typename T>
struct ptr_node :
- boost::unordered::detail::value_base<T>,
boost::unordered::detail::ptr_bucket
{
+ typedef T value_type;
typedef boost::unordered::detail::ptr_bucket bucket_base;
- typedef bucket_base node_base;
+ typedef ptr_node<T>* node_pointer;
typedef ptr_bucket* link_pointer;
std::size_t hash_;
+ boost::unordered::detail::value_base<T> value_base_;
-#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
- template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
- explicit ptr_node(BOOST_UNORDERED_EMPLACE_ARGS) :
- bucket_base(),
- hash_(0)
- {
- boost::unordered::detail::construct_impl(
- this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
- }
-
- ~ptr_node() {
- boost::unordered::detail::destroy(this->value_ptr());
- }
-
- ptr_node(ptr_node const&) {
- BOOST_ASSERT(false);
- }
-#else
ptr_node() :
bucket_base(),
hash_(0)
{}
-#endif
- void init(link_pointer)
+ void init(node_pointer)
{
}
+ void* address() { return value_base_.address(); }
+ value_type& value() { return value_base_.value(); }
+ value_type* value_ptr() { return value_base_.value_ptr(); }
+
private:
ptr_node& operator=(ptr_node const&);
};
@@ -164,14 +131,12 @@ namespace boost { namespace unordered { namespace detail {
{
typedef boost::unordered::detail::set<A, T, H, P> types;
+ typedef A allocator;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
- typedef typename boost::unordered::detail::rebind_wrap<
- A, value_type>::type allocator;
-
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
typedef typename pick::node node;
@@ -181,7 +146,7 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::table_impl<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
- typedef boost::unordered::detail::pick_policy::type policy;
+ typedef typename boost::unordered::detail::pick_policy<T>::type policy;
};
template <typename A, typename K, typename M, typename H, typename P>
@@ -189,15 +154,14 @@ namespace boost { namespace unordered { namespace detail {
{
typedef boost::unordered::detail::map<A, K, M, H, P> types;
+ typedef A allocator;
typedef std::pair<K const, M> value_type;
typedef H hasher;
typedef P key_equal;
typedef K key_type;
- typedef typename boost::unordered::detail::rebind_wrap<
- A, value_type>::type allocator;
-
- typedef boost::unordered::detail::allocator_traits<allocator> traits;
+ typedef boost::unordered::detail::allocator_traits<allocator>
+ traits;
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
@@ -207,7 +171,7 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::map_extractor<key_type, value_type>
extractor;
- typedef boost::unordered::detail::pick_policy::type policy;
+ typedef typename boost::unordered::detail::pick_policy<K>::type policy;
};
template <typename Types>
@@ -216,14 +180,12 @@ namespace boost { namespace unordered { namespace detail {
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::policy policy;
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;
@@ -245,12 +207,17 @@ namespace boost { namespace unordered { namespace detail {
table_impl(table_impl const& x)
: table(x, node_allocator_traits::
- select_on_container_copy_construction(x.node_alloc())) {}
+ select_on_container_copy_construction(x.node_alloc()))
+ {
+ this->init(x);
+ }
table_impl(table_impl const& x,
node_allocator const& a)
: table(x, a)
- {}
+ {
+ this->init(x);
+ }
table_impl(table_impl& x,
boost::unordered::detail::move_tag m)
@@ -261,7 +228,9 @@ namespace boost { namespace unordered { namespace detail {
node_allocator const& a,
boost::unordered::detail::move_tag m)
: table(x, a, m)
- {}
+ {
+ this->move_init(x);
+ }
// Accessors
@@ -271,9 +240,8 @@ namespace boost { namespace unordered { namespace detail {
Key const& k,
Pred const& eq) const
{
- std::size_t bucket_index =
- policy::to_bucket(this->bucket_count_, key_hash);
- iterator n = this->get_start(bucket_index);
+ std::size_t bucket_index = this->hash_to_bucket(key_hash);
+ iterator n = this->begin(bucket_index);
for (;;)
{
@@ -287,8 +255,7 @@ namespace boost { namespace unordered { namespace detail {
}
else
{
- if (policy::to_bucket(this->bucket_count_, node_hash)
- != bucket_index)
+ if (this->hash_to_bucket(node_hash) != bucket_index)
return iterator();
}
@@ -326,19 +293,13 @@ namespace boost { namespace unordered { namespace detail {
bool equals(table_impl const& other) const
{
if(this->size_ != other.size_) return false;
- if(!this->size_) return true;
- for(iterator n1 = this->get_start(); n1.node_; ++n1)
+ for(iterator n1 = this->begin(); n1.node_; ++n1)
{
iterator n2 = other.find_matching_node(n1);
-#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
if (!n2.node_ || *n1 != *n2)
return false;
-#else
- if (!n2.node_ || !extractor::compare_mapped(*n1, *n2))
- return false;
-#endif
}
return true;
@@ -353,27 +314,26 @@ namespace boost { namespace unordered { namespace detail {
node_pointer n = a.release();
n->hash_ = key_hash;
- bucket_pointer b = this->get_bucket(
- policy::to_bucket(this->bucket_count_, key_hash));
+ bucket_pointer b = this->get_bucket(this->hash_to_bucket(key_hash));
if (!b->next_)
{
- previous_pointer start_node = this->get_previous_start();
+ link_pointer start_node = this->get_previous_start();
if (start_node->next_) {
- this->get_bucket(policy::to_bucket(this->bucket_count_,
+ this->get_bucket(this->hash_to_bucket(
static_cast<node_pointer>(start_node->next_)->hash_)
)->next_ = n;
}
b->next_ = start_node;
n->next_ = start_node->next_;
- start_node->next_ = static_cast<link_pointer>(n);
+ start_node->next_ = n;
}
else
{
n->next_ = b->next_->next_;
- b->next_->next_ = static_cast<link_pointer>(n);
+ b->next_->next_ = n;
}
++this->size_;
@@ -382,8 +342,6 @@ namespace boost { namespace unordered { namespace detail {
value_type& operator[](key_type const& k)
{
- typedef typename value_type::second_type mapped_type;
-
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
@@ -392,9 +350,7 @@ namespace boost { namespace unordered { namespace detail {
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(this->node_alloc());
- a.construct_node();
-
- a.construct_value(BOOST_UNORDERED_EMPLACE_ARGS3(
+ a.construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS3(
boost::unordered::piecewise_construct,
boost::make_tuple(k),
boost::make_tuple()));
@@ -403,8 +359,8 @@ namespace boost { namespace unordered { namespace detail {
return *add_node(a, key_hash);
}
-#if defined(BOOST_NO_RVALUE_REFERENCES)
-# if defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+# if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
emplace_return emplace(boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
@@ -424,7 +380,7 @@ namespace boost { namespace unordered { namespace detail {
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
emplace_return emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
-#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
return emplace_impl(
extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
BOOST_UNORDERED_EMPLACE_FORWARD);
@@ -435,7 +391,7 @@ namespace boost { namespace unordered { namespace detail {
#endif
}
-#if defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename A0>
emplace_return emplace(
boost::unordered::detail::emplace_args1<A0> const& args)
@@ -456,8 +412,7 @@ namespace boost { namespace unordered { namespace detail {
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(this->node_alloc());
- a.construct_node();
- a.construct_value(BOOST_UNORDERED_EMPLACE_FORWARD);
+ a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
@@ -485,8 +440,7 @@ namespace boost { namespace unordered { namespace detail {
// 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);
+ a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
return emplace_impl_with_node(a);
}
@@ -508,14 +462,9 @@ namespace boost { namespace unordered { namespace detail {
{
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, k, i, j);
- if (++i == j) return;
- }
+ insert_range_impl2(a, k, i, j);
- do {
+ while(++i != j) {
// 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.
@@ -525,19 +474,7 @@ namespace boost { namespace unordered { namespace detail {
// be less efficient if copying the full value_type is
// expensive.
insert_range_impl2(a, extractor::extract(*i), i, j);
- } while(++i != j);
- }
-
- template <class InputIt>
- void insert_range_empty(node_constructor& a, key_type const& k,
- InputIt i, InputIt j)
- {
- 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, key_hash);
+ }
}
template <class InputIt>
@@ -549,9 +486,7 @@ namespace boost { namespace unordered { namespace detail {
iterator pos = this->find_node(key_hash, k);
if (!pos.node_) {
- a.construct_node();
- a.construct_value2(*i);
-
+ a.construct_with_value2(*i);
if(this->size_ + 1 > this->max_load_)
this->reserve_for_insert(this->size_ +
boost::unordered::detail::insert_size(i, j));
@@ -567,8 +502,7 @@ namespace boost { namespace unordered { namespace detail {
node_constructor a(this->node_alloc());
do {
- a.construct_node();
- a.construct_value2(*i);
+ a.construct_with_value2(*i);
emplace_impl_with_node(a);
} while(++i != j);
}
@@ -583,11 +517,8 @@ namespace boost { namespace unordered { namespace detail {
if(!this->size_) return 0;
std::size_t key_hash = this->hash(k);
- std::size_t bucket_index =
- policy::to_bucket(this->bucket_count_, key_hash);
- bucket_pointer this_bucket = this->get_bucket(bucket_index);
-
- previous_pointer prev = this_bucket->next_;
+ std::size_t bucket_index = this->hash_to_bucket(key_hash);
+ link_pointer prev = this->get_previous_start(bucket_index);
if (!prev) return 0;
for (;;)
@@ -595,21 +526,20 @@ namespace boost { namespace unordered { namespace detail {
if (!prev->next_) return 0;
std::size_t node_hash =
static_cast<node_pointer>(prev->next_)->hash_;
- if (policy::to_bucket(this->bucket_count_, node_hash)
- != bucket_index)
+ if (this->hash_to_bucket(node_hash) != bucket_index)
return 0;
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(
static_cast<node_pointer>(prev->next_)->value())))
break;
- prev = static_cast<previous_pointer>(prev->next_);
+ prev = 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(this_bucket, prev, end);
- return this->delete_nodes(c_iterator(pos), c_iterator(end));
+ link_pointer end = static_cast<node_pointer>(prev->next_)->next_;
+
+ std::size_t deleted_count = this->delete_nodes(prev, end);
+ this->fix_bucket(bucket_index, prev);
+ return deleted_count;
}
iterator erase(c_iterator r)
@@ -617,103 +547,45 @@ namespace boost { namespace unordered { namespace detail {
BOOST_ASSERT(r.node_);
iterator next(r.node_);
++next;
-
- bucket_pointer this_bucket = this->get_bucket(
- policy::to_bucket(this->bucket_count_, r.node_->hash_));
- previous_pointer prev = unlink_node(*this_bucket, r.node_);
-
- this->fix_buckets(this_bucket, prev, next.node_);
-
- this->delete_node(r);
-
+ erase_nodes(r.node_, next.node_);
return next;
}
iterator erase_range(c_iterator r1, c_iterator r2)
{
if (r1 == r2) return iterator(r2.node_);
-
- std::size_t bucket_index =
- policy::to_bucket(this->bucket_count_, r1.node_->hash_);
- previous_pointer prev = unlink_nodes(
- *this->get_bucket(bucket_index), r1.node_, r2.node_);
- this->fix_buckets_range(bucket_index, prev, r1.node_, r2.node_);
- this->delete_nodes(r1, r2);
-
+ erase_nodes(r1.node_, r2.node_);
return iterator(r2.node_);
}
- static previous_pointer unlink_node(bucket& b, node_pointer n)
+ void erase_nodes(node_pointer i, node_pointer j)
{
- return unlink_nodes(b, n, static_cast<node_pointer>(n->next_));
- }
+ std::size_t bucket_index = this->hash_to_bucket(i->hash_);
- 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;
- }
+ // Find the node before i.
+ link_pointer prev = this->get_previous_start(bucket_index);
+ while(prev->next_ != i) prev = prev->next_;
- ////////////////////////////////////////////////////////////////////////
- // 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());
-
- iterator n = src.get_start();
- previous_pointer prev = dst.get_previous_start();
-
- while(n.node_) {
- a.construct_node();
- a.construct_value2(*n);
-
- node_pointer node = a.release();
- node->hash_ = n.node_->hash_;
- prev->next_ = static_cast<link_pointer>(node);
- ++dst.size_;
- ++n;
-
- prev = place_in_bucket(dst, prev);
- }
+ // Delete the nodes.
+ do {
+ this->delete_node(prev);
+ bucket_index = this->fix_bucket(bucket_index, prev);
+ } while (prev->next_ != j);
}
////////////////////////////////////////////////////////////////////////
- // move_buckets_to
- //
- // Basic exception safety. The source nodes are left in an unusable
- // state if an exception throws.
+ // fill_buckets
- static void move_buckets_to(buckets& src, buckets& dst)
+ template <class NodeCreator>
+ static void fill_buckets(iterator n, table& dst,
+ NodeCreator& creator)
{
- BOOST_ASSERT(!dst.buckets_);
-
- dst.create_buckets();
-
- node_constructor a(dst.node_alloc());
-
- iterator n = src.get_start();
- previous_pointer prev = dst.get_previous_start();
+ link_pointer prev = dst.get_previous_start();
while (n.node_) {
- a.construct_node();
- a.construct_value2(boost::move(*n));
-
- node_pointer node = a.release();
+ node_pointer node = creator.create(*n);
node->hash_ = n.node_->hash_;
- prev->next_ = static_cast<link_pointer>(node);
+ prev->next_ = node;
++dst.size_;
++n;
@@ -724,45 +596,29 @@ namespace boost { namespace unordered { namespace detail {
// strong otherwise exception safety
void rehash_impl(std::size_t num_buckets)
{
- BOOST_ASSERT(this->size_);
+ BOOST_ASSERT(this->buckets_);
- 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();
+ this->create_buckets(num_buckets);
+ link_pointer prev = this->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
+ prev = place_in_bucket(*this, prev);
}
// 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)
+ static link_pointer place_in_bucket(table& dst, link_pointer prev)
{
node_pointer n = static_cast<node_pointer>(prev->next_);
- bucket_pointer b = dst.get_bucket(
- buckets::to_bucket(dst.bucket_count_, n->hash_));
+ bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(n->hash_));
if (!b->next_) {
b->next_ = prev;
- return static_cast<previous_pointer>(n);
+ return n;
}
else {
prev->next_ = n->next_;
n->next_ = b->next_->next_;
- b->next_->next_ = static_cast<link_pointer>(n);
+ b->next_->next_ = n;
return prev;
}
}
diff --git a/boost/unordered/detail/util.hpp b/boost/unordered/detail/util.hpp
index a901477d19..3428ed7ae2 100644
--- a/boost/unordered/detail/util.hpp
+++ b/boost/unordered/detail/util.hpp
@@ -7,8 +7,9 @@
#ifndef BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
+#include <boost/config.hpp>
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#pragma once
#endif
#include <boost/type_traits/is_convertible.hpp>
@@ -28,6 +29,11 @@ namespace boost { namespace unordered { namespace detail {
struct move_tag {};
struct empty_emplace {};
+ namespace func {
+ template <class T>
+ inline void ignore_unused_variable_warning(T const&) {}
+ }
+
////////////////////////////////////////////////////////////////////////////
// iterator SFINAE
diff --git a/boost/unordered/unordered_map.hpp b/boost/unordered/unordered_map.hpp
index ce52e5becf..9b180796d1 100644
--- a/boost/unordered/unordered_map.hpp
+++ b/boost/unordered/unordered_map.hpp
@@ -9,8 +9,9 @@
#ifndef BOOST_UNORDERED_UNORDERED_MAP_HPP_INCLUDED
#define BOOST_UNORDERED_UNORDERED_MAP_HPP_INCLUDED
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
+#include <boost/config.hpp>
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#pragma once
#endif
#include <boost/unordered/unordered_map_fwd.hpp>
@@ -56,7 +57,6 @@ namespace unordered
private:
typedef boost::unordered::detail::map<A, K, T, H, P> types;
- typedef typename types::allocator value_allocator;
typedef typename types::traits allocator_traits;
typedef typename types::table table;
@@ -118,17 +118,19 @@ namespace unordered
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_map(BOOST_RV_REF(unordered_map) other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
-#elif !defined(BOOST_NO_RVALUE_REFERENCES)
+#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_map(unordered_map&& other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#endif
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_map(unordered_map&&, allocator_type const&);
#endif
@@ -143,7 +145,7 @@ namespace unordered
// Destructor
- ~unordered_map();
+ ~unordered_map() BOOST_NOEXCEPT;
// Assign
@@ -166,7 +168,7 @@ namespace unordered
return *this;
}
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_map& operator=(unordered_map&& x)
{
table_.move_assign(x.table_);
@@ -179,60 +181,60 @@ namespace unordered
unordered_map& operator=(std::initializer_list<value_type>);
#endif
- allocator_type get_allocator() const
+ allocator_type get_allocator() const BOOST_NOEXCEPT
{
return table_.node_alloc();
}
// size and capacity
- bool empty() const
+ bool empty() const BOOST_NOEXCEPT
{
return table_.size_ == 0;
}
- size_type size() const
+ size_type size() const BOOST_NOEXCEPT
{
return table_.size_;
}
- size_type max_size() const;
+ size_type max_size() const BOOST_NOEXCEPT;
// iterators
- iterator begin()
+ iterator begin() BOOST_NOEXCEPT
{
return table_.begin();
}
- const_iterator begin() const
+ const_iterator begin() const BOOST_NOEXCEPT
{
return table_.begin();
}
- iterator end()
+ iterator end() BOOST_NOEXCEPT
{
return iterator();
}
- const_iterator end() const
+ const_iterator end() const BOOST_NOEXCEPT
{
return const_iterator();
}
- const_iterator cbegin() const
+ const_iterator cbegin() const BOOST_NOEXCEPT
{
return table_.begin();
}
- const_iterator cend() const
+ const_iterator cend() const BOOST_NOEXCEPT
{
return const_iterator();
}
// emplace
-#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
{
@@ -450,12 +452,12 @@ namespace unordered
// bucket interface
- size_type bucket_count() const
+ size_type bucket_count() const BOOST_NOEXCEPT
{
return table_.bucket_count_;
}
- size_type max_bucket_count() const
+ size_type max_bucket_count() const BOOST_NOEXCEPT
{
return table_.max_bucket_count();
}
@@ -464,22 +466,19 @@ namespace unordered
size_type bucket(const key_type& k) const
{
- return table::to_bucket(table_.bucket_count_,
- table_.hash(k));
+ return table_.hash_to_bucket(table_.hash(k));
}
local_iterator begin(size_type n)
{
- return table_.size_ ? local_iterator(
- table_.get_start(n), n, table_.bucket_count_) :
- local_iterator();
+ return local_iterator(
+ table_.begin(n), n, table_.bucket_count_);
}
const_local_iterator begin(size_type n) const
{
- return table_.size_ ? const_local_iterator(
- table_.get_start(n), n, table_.bucket_count_) :
- const_local_iterator();
+ return const_local_iterator(
+ table_.begin(n), n, table_.bucket_count_);
}
local_iterator end(size_type)
@@ -494,9 +493,8 @@ namespace unordered
const_local_iterator cbegin(size_type n) const
{
- return table_.size_ ? const_local_iterator(
- table_.get_start(n), n, table_.bucket_count_) :
- const_local_iterator();
+ return const_local_iterator(
+ table_.begin(n), n, table_.bucket_count_);
}
const_local_iterator cend(size_type) const
@@ -506,13 +504,13 @@ namespace unordered
// hash policy
- float max_load_factor() const
+ float max_load_factor() const BOOST_NOEXCEPT
{
return table_.mlf_;
}
- float load_factor() const;
- void max_load_factor(float);
+ float load_factor() const BOOST_NOEXCEPT;
+ void max_load_factor(float) BOOST_NOEXCEPT;
void rehash(size_type);
void reserve(size_type);
@@ -542,7 +540,6 @@ namespace unordered
private:
typedef boost::unordered::detail::multimap<A, K, T, H, P> types;
- typedef typename types::allocator value_allocator;
typedef typename types::traits allocator_traits;
typedef typename types::table table;
@@ -604,17 +601,19 @@ namespace unordered
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multimap(BOOST_RV_REF(unordered_multimap) other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
-#elif !defined(BOOST_NO_RVALUE_REFERENCES)
+#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multimap(unordered_multimap&& other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#endif
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multimap(unordered_multimap&&, allocator_type const&);
#endif
@@ -629,7 +628,7 @@ namespace unordered
// Destructor
- ~unordered_multimap();
+ ~unordered_multimap() BOOST_NOEXCEPT;
// Assign
@@ -653,7 +652,7 @@ namespace unordered
return *this;
}
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multimap& operator=(unordered_multimap&& x)
{
table_.move_assign(x.table_);
@@ -666,60 +665,60 @@ namespace unordered
unordered_multimap& operator=(std::initializer_list<value_type>);
#endif
- allocator_type get_allocator() const
+ allocator_type get_allocator() const BOOST_NOEXCEPT
{
return table_.node_alloc();
}
// size and capacity
- bool empty() const
+ bool empty() const BOOST_NOEXCEPT
{
return table_.size_ == 0;
}
- size_type size() const
+ size_type size() const BOOST_NOEXCEPT
{
return table_.size_;
}
- size_type max_size() const;
+ size_type max_size() const BOOST_NOEXCEPT;
// iterators
- iterator begin()
+ iterator begin() BOOST_NOEXCEPT
{
return table_.begin();
}
- const_iterator begin() const
+ const_iterator begin() const BOOST_NOEXCEPT
{
return table_.begin();
}
- iterator end()
+ iterator end() BOOST_NOEXCEPT
{
return iterator();
}
- const_iterator end() const
+ const_iterator end() const BOOST_NOEXCEPT
{
return const_iterator();
}
- const_iterator cbegin() const
+ const_iterator cbegin() const BOOST_NOEXCEPT
{
return table_.begin();
}
- const_iterator cend() const
+ const_iterator cend() const BOOST_NOEXCEPT
{
return const_iterator();
}
// emplace
-#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
iterator emplace(BOOST_FWD_REF(Args)... args)
{
@@ -933,12 +932,12 @@ namespace unordered
// bucket interface
- size_type bucket_count() const
+ size_type bucket_count() const BOOST_NOEXCEPT
{
return table_.bucket_count_;
}
- size_type max_bucket_count() const
+ size_type max_bucket_count() const BOOST_NOEXCEPT
{
return table_.max_bucket_count();
}
@@ -947,22 +946,19 @@ namespace unordered
size_type bucket(const key_type& k) const
{
- return table::to_bucket(table_.bucket_count_,
- table_.hash(k));
+ return table_.hash_to_bucket(table_.hash(k));
}
local_iterator begin(size_type n)
{
- return table_.size_ ? local_iterator(
- table_.get_start(n), n, table_.bucket_count_) :
- local_iterator();
+ return local_iterator(
+ table_.begin(n), n, table_.bucket_count_);
}
const_local_iterator begin(size_type n) const
{
- return table_.size_ ? const_local_iterator(
- table_.get_start(n), n, table_.bucket_count_) :
- const_local_iterator();
+ return const_local_iterator(
+ table_.begin(n), n, table_.bucket_count_);
}
local_iterator end(size_type)
@@ -977,9 +973,8 @@ namespace unordered
const_local_iterator cbegin(size_type n) const
{
- return table_.size_ ? const_local_iterator(
- table_.get_start(n), n, table_.bucket_count_) :
- const_local_iterator();
+ return const_local_iterator(
+ table_.begin(n), n, table_.bucket_count_);
}
const_local_iterator cend(size_type) const
@@ -989,13 +984,13 @@ namespace unordered
// hash policy
- float max_load_factor() const
+ float max_load_factor() const BOOST_NOEXCEPT
{
return table_.mlf_;
}
- float load_factor() const;
- void max_load_factor(float);
+ float load_factor() const BOOST_NOEXCEPT;
+ void max_load_factor(float) BOOST_NOEXCEPT;
void rehash(size_type);
void reserve(size_type);
@@ -1067,7 +1062,7 @@ namespace unordered
}
template <class K, class T, class H, class P, class A>
- unordered_map<K,T,H,P,A>::~unordered_map() {}
+ unordered_map<K,T,H,P,A>::~unordered_map() BOOST_NOEXCEPT {}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
@@ -1076,7 +1071,7 @@ namespace unordered
{
}
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
@@ -1115,7 +1110,7 @@ namespace unordered
// size and capacity
template <class K, class T, class H, class P, class A>
- std::size_t unordered_map<K,T,H,P,A>::max_size() const
+ std::size_t unordered_map<K,T,H,P,A>::max_size() const BOOST_NOEXCEPT
{
return table_.max_size();
}
@@ -1284,13 +1279,13 @@ namespace unordered
// hash policy
template <class K, class T, class H, class P, class A>
- float unordered_map<K,T,H,P,A>::load_factor() const
+ float unordered_map<K,T,H,P,A>::load_factor() const BOOST_NOEXCEPT
{
return table_.load_factor();
}
template <class K, class T, class H, class P, class A>
- void unordered_map<K,T,H,P,A>::max_load_factor(float m)
+ void unordered_map<K,T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
{
table_.max_load_factor(m);
}
@@ -1400,7 +1395,7 @@ namespace unordered
}
template <class K, class T, class H, class P, class A>
- unordered_multimap<K,T,H,P,A>::~unordered_multimap() {}
+ unordered_multimap<K,T,H,P,A>::~unordered_multimap() BOOST_NOEXCEPT {}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
@@ -1409,7 +1404,7 @@ namespace unordered
{
}
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
@@ -1448,7 +1443,7 @@ namespace unordered
// size and capacity
template <class K, class T, class H, class P, class A>
- std::size_t unordered_multimap<K,T,H,P,A>::max_size() const
+ std::size_t unordered_multimap<K,T,H,P,A>::max_size() const BOOST_NOEXCEPT
{
return table_.max_size();
}
@@ -1596,13 +1591,13 @@ namespace unordered
// hash policy
template <class K, class T, class H, class P, class A>
- float unordered_multimap<K,T,H,P,A>::load_factor() const
+ float unordered_multimap<K,T,H,P,A>::load_factor() const BOOST_NOEXCEPT
{
return table_.load_factor();
}
template <class K, class T, class H, class P, class A>
- void unordered_multimap<K,T,H,P,A>::max_load_factor(float m)
+ void unordered_multimap<K,T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
{
table_.max_load_factor(m);
}
diff --git a/boost/unordered/unordered_map_fwd.hpp b/boost/unordered/unordered_map_fwd.hpp
index 980bb3ee77..1eb26ce951 100644
--- a/boost/unordered/unordered_map_fwd.hpp
+++ b/boost/unordered/unordered_map_fwd.hpp
@@ -6,11 +6,11 @@
#ifndef BOOST_UNORDERED_MAP_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_MAP_FWD_HPP_INCLUDED
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
+#include <boost/config.hpp>
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#pragma once
#endif
-#include <boost/config.hpp>
#include <memory>
#include <functional>
#include <boost/functional/hash_fwd.hpp>
diff --git a/boost/unordered/unordered_set.hpp b/boost/unordered/unordered_set.hpp
index 5d9a0b8e8d..853b5d7317 100644
--- a/boost/unordered/unordered_set.hpp
+++ b/boost/unordered/unordered_set.hpp
@@ -9,8 +9,9 @@
#ifndef BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
#define BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
+#include <boost/config.hpp>
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#pragma once
#endif
#include <boost/unordered/unordered_set_fwd.hpp>
@@ -54,7 +55,6 @@ namespace unordered
private:
typedef boost::unordered::detail::set<A, T, H, P> types;
- typedef typename types::allocator value_allocator;
typedef typename types::traits allocator_traits;
typedef typename types::table table;
@@ -116,17 +116,19 @@ namespace unordered
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_set(BOOST_RV_REF(unordered_set) other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
-#elif !defined(BOOST_NO_RVALUE_REFERENCES)
+#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_set(unordered_set&& other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#endif
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_set(unordered_set&&, allocator_type const&);
#endif
@@ -141,7 +143,7 @@ namespace unordered
// Destructor
- ~unordered_set();
+ ~unordered_set() BOOST_NOEXCEPT;
// Assign
@@ -164,7 +166,7 @@ namespace unordered
return *this;
}
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_set& operator=(unordered_set&& x)
{
table_.move_assign(x.table_);
@@ -177,60 +179,60 @@ namespace unordered
unordered_set& operator=(std::initializer_list<value_type>);
#endif
- allocator_type get_allocator() const
+ allocator_type get_allocator() const BOOST_NOEXCEPT
{
return table_.node_alloc();
}
// size and capacity
- bool empty() const
+ bool empty() const BOOST_NOEXCEPT
{
return table_.size_ == 0;
}
- size_type size() const
+ size_type size() const BOOST_NOEXCEPT
{
return table_.size_;
}
- size_type max_size() const;
+ size_type max_size() const BOOST_NOEXCEPT;
// iterators
- iterator begin()
+ iterator begin() BOOST_NOEXCEPT
{
return table_.begin();
}
- const_iterator begin() const
+ const_iterator begin() const BOOST_NOEXCEPT
{
return table_.begin();
}
- iterator end()
+ iterator end() BOOST_NOEXCEPT
{
return iterator();
}
- const_iterator end() const
+ const_iterator end() const BOOST_NOEXCEPT
{
return const_iterator();
}
- const_iterator cbegin() const
+ const_iterator cbegin() const BOOST_NOEXCEPT
{
return table_.begin();
}
- const_iterator cend() const
+ const_iterator cend() const BOOST_NOEXCEPT
{
return const_iterator();
}
// emplace
-#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
{
@@ -435,12 +437,12 @@ namespace unordered
// bucket interface
- size_type bucket_count() const
+ size_type bucket_count() const BOOST_NOEXCEPT
{
return table_.bucket_count_;
}
- size_type max_bucket_count() const
+ size_type max_bucket_count() const BOOST_NOEXCEPT
{
return table_.max_bucket_count();
}
@@ -449,22 +451,19 @@ namespace unordered
size_type bucket(const key_type& k) const
{
- return table::to_bucket(table_.bucket_count_,
- table_.hash(k));
+ return table_.hash_to_bucket(table_.hash(k));
}
local_iterator begin(size_type n)
{
- return table_.size_ ? local_iterator(
- table_.get_start(n), n, table_.bucket_count_) :
- local_iterator();
+ return local_iterator(
+ table_.begin(n), n, table_.bucket_count_);
}
const_local_iterator begin(size_type n) const
{
- return table_.size_ ? const_local_iterator(
- table_.get_start(n), n, table_.bucket_count_) :
- const_local_iterator();
+ return const_local_iterator(
+ table_.begin(n), n, table_.bucket_count_);
}
local_iterator end(size_type)
@@ -479,9 +478,8 @@ namespace unordered
const_local_iterator cbegin(size_type n) const
{
- return table_.size_ ? const_local_iterator(
- table_.get_start(n), n, table_.bucket_count_) :
- const_local_iterator();
+ return const_local_iterator(
+ table_.begin(n), n, table_.bucket_count_);
}
const_local_iterator cend(size_type) const
@@ -491,13 +489,13 @@ namespace unordered
// hash policy
- float max_load_factor() const
+ float max_load_factor() const BOOST_NOEXCEPT
{
return table_.mlf_;
}
- float load_factor() const;
- void max_load_factor(float);
+ float load_factor() const BOOST_NOEXCEPT;
+ void max_load_factor(float) BOOST_NOEXCEPT;
void rehash(size_type);
void reserve(size_type);
@@ -526,7 +524,6 @@ namespace unordered
private:
typedef boost::unordered::detail::multiset<A, T, H, P> types;
- typedef typename types::allocator value_allocator;
typedef typename types::traits allocator_traits;
typedef typename types::table table;
@@ -588,17 +585,19 @@ namespace unordered
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multiset(BOOST_RV_REF(unordered_multiset) other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
-#elif !defined(BOOST_NO_RVALUE_REFERENCES)
+#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multiset(unordered_multiset&& other)
+ BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#endif
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multiset(unordered_multiset&&, allocator_type const&);
#endif
@@ -613,7 +612,7 @@ namespace unordered
// Destructor
- ~unordered_multiset();
+ ~unordered_multiset() BOOST_NOEXCEPT;
// Assign
@@ -637,7 +636,7 @@ namespace unordered
return *this;
}
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multiset& operator=(unordered_multiset&& x)
{
table_.move_assign(x.table_);
@@ -650,60 +649,60 @@ namespace unordered
unordered_multiset& operator=(std::initializer_list<value_type>);
#endif
- allocator_type get_allocator() const
+ allocator_type get_allocator() const BOOST_NOEXCEPT
{
return table_.node_alloc();
}
// size and capacity
- bool empty() const
+ bool empty() const BOOST_NOEXCEPT
{
return table_.size_ == 0;
}
- size_type size() const
+ size_type size() const BOOST_NOEXCEPT
{
return table_.size_;
}
- size_type max_size() const;
+ size_type max_size() const BOOST_NOEXCEPT;
// iterators
- iterator begin()
+ iterator begin() BOOST_NOEXCEPT
{
return iterator(table_.begin());
}
- const_iterator begin() const
+ const_iterator begin() const BOOST_NOEXCEPT
{
return const_iterator(table_.begin());
}
- iterator end()
+ iterator end() BOOST_NOEXCEPT
{
return iterator();
}
- const_iterator end() const
+ const_iterator end() const BOOST_NOEXCEPT
{
return const_iterator();
}
- const_iterator cbegin() const
+ const_iterator cbegin() const BOOST_NOEXCEPT
{
return const_iterator(table_.begin());
}
- const_iterator cend() const
+ const_iterator cend() const BOOST_NOEXCEPT
{
return const_iterator();
}
// emplace
-#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
iterator emplace(BOOST_FWD_REF(Args)... args)
{
@@ -908,12 +907,12 @@ namespace unordered
// bucket interface
- size_type bucket_count() const
+ size_type bucket_count() const BOOST_NOEXCEPT
{
return table_.bucket_count_;
}
- size_type max_bucket_count() const
+ size_type max_bucket_count() const BOOST_NOEXCEPT
{
return table_.max_bucket_count();
}
@@ -922,22 +921,19 @@ namespace unordered
size_type bucket(const key_type& k) const
{
- return table::to_bucket(table_.bucket_count_,
- table_.hash(k));
+ return table_.hash_to_bucket(table_.hash(k));
}
local_iterator begin(size_type n)
{
- return table_.size_ ? local_iterator(
- table_.get_start(n), n, table_.bucket_count_) :
- local_iterator();
+ return local_iterator(
+ table_.begin(n), n, table_.bucket_count_);
}
const_local_iterator begin(size_type n) const
{
- return table_.size_ ? const_local_iterator(
- table_.get_start(n), n, table_.bucket_count_) :
- const_local_iterator();
+ return const_local_iterator(
+ table_.begin(n), n, table_.bucket_count_);
}
local_iterator end(size_type)
@@ -952,9 +948,8 @@ namespace unordered
const_local_iterator cbegin(size_type n) const
{
- return table_.size_ ? const_local_iterator(
- table_.get_start(n), n, table_.bucket_count_) :
- const_local_iterator();
+ return const_local_iterator(
+ table_.begin(n), n, table_.bucket_count_);
}
const_local_iterator cend(size_type) const
@@ -964,13 +959,13 @@ namespace unordered
// hash policy
- float max_load_factor() const
+ float max_load_factor() const BOOST_NOEXCEPT
{
return table_.mlf_;
}
- float load_factor() const;
- void max_load_factor(float);
+ float load_factor() const BOOST_NOEXCEPT;
+ void max_load_factor(float) BOOST_NOEXCEPT;
void rehash(size_type);
void reserve(size_type);
@@ -1042,7 +1037,7 @@ namespace unordered
}
template <class T, class H, class P, class A>
- unordered_set<T,H,P,A>::~unordered_set() {}
+ unordered_set<T,H,P,A>::~unordered_set() BOOST_NOEXCEPT {}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
@@ -1051,7 +1046,7 @@ namespace unordered
{
}
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
@@ -1090,7 +1085,7 @@ namespace unordered
// size and capacity
template <class T, class H, class P, class A>
- std::size_t unordered_set<T,H,P,A>::max_size() const
+ std::size_t unordered_set<T,H,P,A>::max_size() const BOOST_NOEXCEPT
{
return table_.max_size();
}
@@ -1210,13 +1205,13 @@ namespace unordered
// hash policy
template <class T, class H, class P, class A>
- float unordered_set<T,H,P,A>::load_factor() const
+ float unordered_set<T,H,P,A>::load_factor() const BOOST_NOEXCEPT
{
return table_.load_factor();
}
template <class T, class H, class P, class A>
- void unordered_set<T,H,P,A>::max_load_factor(float m)
+ void unordered_set<T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
{
table_.max_load_factor(m);
}
@@ -1326,7 +1321,7 @@ namespace unordered
}
template <class T, class H, class P, class A>
- unordered_multiset<T,H,P,A>::~unordered_multiset() {}
+ unordered_multiset<T,H,P,A>::~unordered_multiset() BOOST_NOEXCEPT {}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
@@ -1335,7 +1330,7 @@ namespace unordered
{
}
-#if !defined(BOOST_NO_RVALUE_REFERENCES)
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
@@ -1374,7 +1369,7 @@ namespace unordered
// size and capacity
template <class T, class H, class P, class A>
- std::size_t unordered_multiset<T,H,P,A>::max_size() const
+ std::size_t unordered_multiset<T,H,P,A>::max_size() const BOOST_NOEXCEPT
{
return table_.max_size();
}
@@ -1494,13 +1489,13 @@ namespace unordered
// hash policy
template <class T, class H, class P, class A>
- float unordered_multiset<T,H,P,A>::load_factor() const
+ float unordered_multiset<T,H,P,A>::load_factor() const BOOST_NOEXCEPT
{
return table_.load_factor();
}
template <class T, class H, class P, class A>
- void unordered_multiset<T,H,P,A>::max_load_factor(float m)
+ void unordered_multiset<T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
{
table_.max_load_factor(m);
}
diff --git a/boost/unordered/unordered_set_fwd.hpp b/boost/unordered/unordered_set_fwd.hpp
index 0c8b6d8d63..52b9e822f2 100644
--- a/boost/unordered/unordered_set_fwd.hpp
+++ b/boost/unordered/unordered_set_fwd.hpp
@@ -6,11 +6,11 @@
#ifndef BOOST_UNORDERED_SET_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_SET_FWD_HPP_INCLUDED
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
+#include <boost/config.hpp>
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#pragma once
#endif
-#include <boost/config.hpp>
#include <memory>
#include <functional>
#include <boost/functional/hash_fwd.hpp>