diff --git a/doc/ref.php b/doc/ref.php
index 30d79a92..1070c6cf 100644
--- a/doc/ref.php
+++ b/doc/ref.php
@@ -418,7 +418,7 @@ EOL;
In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
- BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
+ BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
@@ -459,12 +459,11 @@ EOL;
for rvalue references or move semantics.
Since existing std::pair
implementations don't support
std::piecewise_construct
this emulates it,
- but using boost::unordered::piecewise_construct
.
+ but using boost::unordered::piecewise_construct
.
In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
- BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
-
+ BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
@@ -811,10 +810,6 @@ EOL;
An exception object of type std::out_of_range
if no such element is present.
-
- This is not specified in the draft standard, but that is probably an oversight. The issue has been raised in
- comp.std.c++.
-
diff --git a/doc/ref.xml b/doc/ref.xml
index a31236dd..5afa1f4f 100644
--- a/doc/ref.xml
+++ b/doc/ref.xml
@@ -356,7 +356,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
- BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
+ BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
@@ -390,12 +390,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
for rvalue references or move semantics.
Since existing std::pair
implementations don't support
std::piecewise_construct
this emulates it,
- but using boost::unordered::piecewise_construct
.
+ but using boost::unordered::piecewise_construct
.
In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
- BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
-
+ BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
@@ -1296,7 +1295,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
- BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
+ BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
@@ -1330,12 +1329,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
for rvalue references or move semantics.
Since existing std::pair
implementations don't support
std::piecewise_construct
this emulates it,
- but using boost::unordered::piecewise_construct
.
+ but using boost::unordered::piecewise_construct
.
In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
- BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
-
+ BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
@@ -2248,7 +2246,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
- BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
+ BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
@@ -2282,12 +2280,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
for rvalue references or move semantics.
Since existing std::pair
implementations don't support
std::piecewise_construct
this emulates it,
- but using boost::unordered::piecewise_construct
.
+ but using boost::unordered::piecewise_construct
.
In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
- BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
-
+ BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
@@ -2618,10 +2615,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
An exception object of type std::out_of_range
if no such element is present.
-
- This is not specified in the draft standard, but that is probably an oversight. The issue has been raised in
- comp.std.c++.
-
@@ -3237,7 +3230,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
- BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
+ BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
@@ -3271,12 +3264,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
for rvalue references or move semantics.
Since existing std::pair
implementations don't support
std::piecewise_construct
this emulates it,
- but using boost::unordered::piecewise_construct
.
+ but using boost::unordered::piecewise_construct
.
In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
- BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
-
+ BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
.
diff --git a/include/boost/unordered/detail/allocator_helpers.hpp b/include/boost/unordered/detail/allocator_helpers.hpp
index 3392ac03..7a44a479 100644
--- a/include/boost/unordered/detail/allocator_helpers.hpp
+++ b/include/boost/unordered/detail/allocator_helpers.hpp
@@ -19,34 +19,45 @@
#include
#include
#include
+#include
#include
#include
+#include
+#include
+#include
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
# include
#endif
#if !defined(BOOST_NO_0X_HDR_TYPE_TRAITS)
-#include
+# include
+#endif
+
namespace boost { namespace unordered { namespace detail {
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Integral_constrant, true_type, false_type
+ //
+ // Uses the standard versions if available.
+
+#if !defined(BOOST_NO_0X_HDR_TYPE_TRAITS)
+
using std::integral_constant;
using std::true_type;
using std::false_type;
-}}}
+
#else
-namespace boost { namespace unordered { namespace detail {
+
template
struct integral_constant { enum { value = Value }; };
- typedef integral_constant true_type;
- typedef integral_constant false_type;
-}}}
+
+ typedef boost::unordered::detail::integral_constant true_type;
+ typedef boost::unordered::detail::integral_constant false_type;
+
#endif
-// TODO: Use std::addressof if available?
-#include
-
-namespace boost { namespace unordered { namespace detail {
-
+ ////////////////////////////////////////////////////////////////////////////
// Explicitly call a destructor
#if defined(BOOST_MSVC)
@@ -63,27 +74,10 @@ namespace boost { namespace unordered { namespace detail {
#pragma warning(pop)
#endif
-#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
- template
- struct allocator_traits : std::allocator_traits {};
-
- template
- struct rebind_wrap
- {
- typedef typename allocator_traits::rebind_alloc type;
- };
-#else
- // rebind_wrap
+ ////////////////////////////////////////////////////////////////////////////
+ // Bits and pieces for implementing traits
//
- // Rebind allocators. For some problematic libraries, use rebind_to
- // from .
-
- template
- struct rebind_wrap
- {
- typedef typename Alloc::BOOST_NESTED_TEMPLATE rebind::other
- type;
- };
+ // Some of these are also used elsewhere
template typename boost::add_lvalue_reference::type make();
struct choice9 { typedef char (&type)[9]; };
@@ -97,6 +91,125 @@ namespace boost { namespace unordered { namespace detail {
struct choice1 : choice2 { typedef char (&type)[1]; };
choice1 choose();
+ typedef choice1::type yes_type;
+ typedef choice2::type no_type;
+
+ struct private_type
+ {
+ private_type const &operator,(int) const;
+ };
+
+ template
+ no_type is_private_type(T const&);
+ yes_type is_private_type(private_type const&);
+
+ struct convert_from_anything {
+ convert_from_anything(...);
+ };
+
+#if !defined(BOOST_NO_SFINAE_EXPR) || BOOST_WORKAROUND(BOOST_MSVC, >= 1500)
+
+# define BOOST_UNORDERED_HAVE_CALL_DETECTION 1
+
+ template struct expr_test;
+ template struct expr_test : T {};
+ template static char for_expr_test(U const&);
+
+#define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
+ template \
+ static typename boost::unordered::detail::expr_test< \
+ BOOST_PP_CAT(choice, result), \
+ sizeof(boost::unordered::detail::for_expr_test(( \
+ (expression), \
+ 0)))>::type test( \
+ BOOST_PP_CAT(choice, count))
+
+#define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \
+ template \
+ static BOOST_PP_CAT(choice, result)::type test( \
+ BOOST_PP_CAT(choice, count))
+
+#define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
+ struct BOOST_PP_CAT(has_, name) \
+ { \
+ BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \
+ boost::unordered::detail::make< thing >().name args); \
+ BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
+ \
+ enum { value = sizeof(test(choose())) == sizeof(choice1::type) };\
+ }
+
+#else
+
+# define BOOST_UNORDERED_HAVE_CALL_DETECTION 0
+
+ template struct identity { typedef T type; };
+
+#define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
+ \
+ typedef typename boost::unordered::detail::identity::type \
+ BOOST_PP_CAT(check, count); \
+ \
+ template \
+ struct BOOST_PP_CAT(test, count) { \
+ typedef BOOST_PP_CAT(choice, result) type; \
+ }; \
+ \
+ template static typename \
+ BOOST_PP_CAT(test, count)<&U::name>::type \
+ test(BOOST_PP_CAT(choice, count))
+
+#define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \
+ template static BOOST_PP_CAT(choice, result)::type \
+ test(BOOST_PP_CAT(choice, count))
+
+#define BOOST_UNORDERED_HAS_MEMBER(name) \
+ struct BOOST_PP_CAT(has_, name) \
+ { \
+ struct impl { \
+ struct base_mixin { int name; }; \
+ struct base : public T, public base_mixin {}; \
+ \
+ BOOST_UNORDERED_CHECK_MEMBER(1, 1, name, int base_mixin::*); \
+ BOOST_UNORDERED_DEFAULT_MEMBER(2, 2); \
+ \
+ enum { value = sizeof(choice2::type) == \
+ sizeof(test(choose())) \
+ }; \
+ }; \
+ \
+ enum { value = impl::value }; \
+ }
+
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Allocator traits
+ //
+ // Uses the standard versions if available.
+ // (although untested as I don't have access to a standard version yet)
+
+#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
+
+ template
+ struct allocator_traits : std::allocator_traits {};
+
+ template
+ struct rebind_wrap
+ {
+ typedef typename std::allocator_traits::rebind_alloc type;
+ };
+
+#else
+
+ // TODO: Does this match std::allocator_traits::rebind_alloc?
+ template
+ struct rebind_wrap
+ {
+ typedef typename Alloc::BOOST_NESTED_TEMPLATE rebind::other
+ type;
+ };
+
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
#define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
@@ -128,7 +241,8 @@ namespace boost { namespace unordered { namespace detail {
struct default_type_ ## tname { \
\
template \
- static typename sfinae::type \
+ static typename boost::unordered::detail::sfinae< \
+ typename X::tname, choice1>::type \
test(choice1); \
\
template \
@@ -158,130 +272,72 @@ namespace boost { namespace unordered { namespace detail {
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
-#if !defined(BOOST_NO_SFINAE_EXPR) || BOOST_WORKAROUND(BOOST_MSVC, >= 1500)
-
- template struct expr_test;
- template struct expr_test : T {};
- template static char for_expr_test(U const&);
-
-#define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
- template \
- static typename expr_test< \
- BOOST_PP_CAT(choice, result), \
- sizeof(for_expr_test(((expression), 0)))>::type test( \
- BOOST_PP_CAT(choice, count))
-
-#define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \
- template \
- static BOOST_PP_CAT(choice, result)::type test( \
- BOOST_PP_CAT(choice, count))
-
-#define BOOST_UNORDERED_HAS_EXPRESSION(name, expression) \
- struct BOOST_PP_CAT(has_, name) \
- { \
- BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, expression); \
- BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
- \
- enum { value = sizeof(test(choose())) == sizeof(choice1::type) };\
- }
-
+#if BOOST_UNORDERED_HAVE_CALL_DETECTION
template
- BOOST_UNORDERED_HAS_EXPRESSION(
- select_on_container_copy_construction,
- make().select_on_container_copy_construction()
- );
-
- // Only supporting the basic copy constructor for now.
-
- template
- BOOST_UNORDERED_HAS_EXPRESSION(
- construct,
- make().construct(make(), make())
- );
-
- template
- BOOST_UNORDERED_HAS_EXPRESSION(
- destroy,
- make().destroy(make())
+ BOOST_UNORDERED_HAS_FUNCTION(
+ select_on_container_copy_construction, U const, (), 0
);
template
- BOOST_UNORDERED_HAS_EXPRESSION(
- max_size,
- make().max_size()
+ BOOST_UNORDERED_HAS_FUNCTION(
+ max_size, U const, (), 0
);
+ template
+ BOOST_UNORDERED_HAS_FUNCTION(
+ construct, U, (
+ boost::unordered::detail::make(),
+ boost::unordered::detail::make()), 2
+ );
+
+ template
+ BOOST_UNORDERED_HAS_FUNCTION(
+ destroy, U, (boost::unordered::detail::make()), 1
+ );
#else
-
- template struct identity { typedef T type; };
-
-#define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
- \
- typedef typename identity::type BOOST_PP_CAT(check, count); \
- \
- template \
- struct BOOST_PP_CAT(test, count) { \
- typedef BOOST_PP_CAT(choice, result) type; \
- }; \
- \
- template static typename \
- BOOST_PP_CAT(test, count)<&U::name>::type \
- test(BOOST_PP_CAT(choice, count))
-
-#define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \
- template static BOOST_PP_CAT(choice, result)::type \
- test(BOOST_PP_CAT(choice, count))
-
+ template
+ BOOST_UNORDERED_HAS_MEMBER(select_on_container_copy_construction);
template
- struct has_select_on_container_copy_construction
- {
- BOOST_UNORDERED_CHECK_MEMBER(1, 1,
- select_on_container_copy_construction,
- T (T::*)() const);
- BOOST_UNORDERED_DEFAULT_MEMBER(2, 2);
-
- enum { value = sizeof(test(choose())) == sizeof(choice1::type) };
- };
+ BOOST_UNORDERED_HAS_MEMBER(max_size);
- // Detection isn't reliable enough, so just assume that we have these
- // functions.
-
- template
- struct has_construct : true_type {};
- template
- struct has_destroy : true_type {};
- template
- struct has_max_size : true_type {};
+ template
+ BOOST_UNORDERED_HAS_MEMBER(construct);
+ template
+ BOOST_UNORDERED_HAS_MEMBER(destroy);
#endif
template
- inline typename boost::enable_if<
- has_select_on_container_copy_construction, Alloc
+ inline typename boost::enable_if_c<
+ boost::unordered::detail::
+ has_select_on_container_copy_construction::value, Alloc
>::type call_select_on_container_copy_construction(const Alloc& rhs)
{
return rhs.select_on_container_copy_construction();
}
template
- inline typename boost::disable_if<
- has_select_on_container_copy_construction, Alloc
+ inline typename boost::disable_if_c<
+ boost::unordered::detail::
+ has_select_on_container_copy_construction::value, Alloc
>::type call_select_on_container_copy_construction(const Alloc& rhs)
{
return rhs;
}
template
- SizeType call_max_size(const Alloc& a,
- typename boost::enable_if, void*>::type = 0)
+ inline typename boost::enable_if_c<
+ boost::unordered::detail::has_max_size::value, SizeType
+ >::type call_max_size(const Alloc& a)
{
return a.max_size();
}
template
- SizeType call_max_size(const Alloc&,
- typename boost::disable_if, void*>::type = 0)
+ inline typename boost::disable_if_c<
+ boost::unordered::detail::has_max_size::value, SizeType
+ >::type call_max_size(const Alloc&)
{
return std::numeric_limits::max();
}
@@ -295,26 +351,19 @@ namespace boost { namespace unordered { namespace detail {
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, pointer, value_type*)
pointer;
- // For now always use the allocator's const_pointer.
-
- //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
- // typename pointer_traits::
- // BOOST_NESTED_TEMPLATE rebind::other)
- // const_pointer;
+ template
+ struct pointer_to_other : boost::pointer_to_other {};
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
- value_type const*) const_pointer;
-
- // I'm not using void pointers for now.
+ typename pointer_to_other::type)
+ const_pointer;
//typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, void_pointer,
- // BOOST_NESTED_TEMPLATE pointer_traits::
- // BOOST_NESTED_TEMPLATE rebind::other)
+ // typename pointer_to_other::type)
// void_pointer;
-
+ //
//typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_void_pointer,
- // typename pointer_traits::
- // BOOST_NESTED_TEMPLATE rebind::other)
+ // typename pointer_to_other::type)
// const_void_pointer;
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, difference_type,
@@ -342,31 +391,35 @@ namespace boost { namespace unordered { namespace detail {
// Only supporting the basic copy constructor for now.
template
- static void construct(Alloc& a, T* p, T const& x, typename
- boost::enable_if, void*>::type = 0)
+ static typename boost::enable_if_c<
+ boost::unordered::detail::has_construct::value>::type
+ construct(Alloc& a, T* p, T const& x)
{
a.construct(p, x);
}
template
- static void construct(Alloc&, T* p, T const& x, typename
- boost::disable_if, void*>::type = 0)
+ static typename boost::disable_if_c<
+ boost::unordered::detail::has_construct::value>::type
+ construct(Alloc&, T* p, T const& x)
{
new ((void*) p) T(x);
}
template
- static void destroy(Alloc& a, T* p, typename
- boost::enable_if, void*>::type = 0)
+ static typename boost::enable_if_c<
+ boost::unordered::detail::has_destroy::value>::type
+ destroy(Alloc& a, T* p)
{
a.destroy(p);
}
template
- static void destroy(Alloc&, T* p, typename
- boost::disable_if, void*>::type = 0)
+ static typename boost::disable_if_c<
+ boost::unordered::detail::has_destroy::value>::type
+ destroy(Alloc&, T* p)
{
- ::boost::unordered::detail::destroy(p);
+ boost::unordered::detail::destroy(p);
}
static size_type max_size(const Alloc& a)
@@ -394,39 +447,42 @@ namespace boost { namespace unordered { namespace detail {
Alloc,propagate_on_container_swap,false_type)
propagate_on_container_swap;
};
+
+#undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
+#undef BOOST_UNORDERED_DEFAULT_TYPE
+
#endif
- // allocator_array_constructor
+ // array_constructor
//
// Allocate and construct an array in an exception safe manner, and
// clean up if an exception is thrown before the container takes charge
// of it.
template
- struct allocator_array_constructor
+ struct array_constructor
{
- typedef typename allocator_traits::pointer
- pointer;
+ typedef boost::unordered::detail::allocator_traits traits;
+ typedef typename traits::pointer pointer;
Allocator& alloc_;
pointer ptr_;
pointer constructed_;
std::size_t length_;
- allocator_array_constructor(Allocator& a)
+ array_constructor(Allocator& a)
: alloc_(a), ptr_(), constructed_(), length_(0)
{
constructed_ = pointer();
ptr_ = pointer();
}
- ~allocator_array_constructor() {
+ ~array_constructor() {
if (ptr_) {
for(pointer p = ptr_; p != constructed_; ++p)
- allocator_traits::destroy(alloc_,
- boost::addressof(*p));
+ traits::destroy(alloc_, boost::addressof(*p));
- allocator_traits::deallocate(alloc_, ptr_, length_);
+ traits::deallocate(alloc_, ptr_, length_);
}
}
@@ -435,11 +491,10 @@ namespace boost { namespace unordered { namespace detail {
{
BOOST_ASSERT(!ptr_);
length_ = l;
- ptr_ = allocator_traits::allocate(alloc_, length_);
+ ptr_ = traits::allocate(alloc_, length_);
pointer end = ptr_ + static_cast(length_);
for(constructed_ = ptr_; constructed_ != end; ++constructed_)
- allocator_traits::construct(alloc_,
- boost::addressof(*constructed_), v);
+ traits::construct(alloc_, boost::addressof(*constructed_), v);
}
pointer get() const
@@ -454,9 +509,8 @@ namespace boost { namespace unordered { namespace detail {
return p;
}
private:
- allocator_array_constructor(allocator_array_constructor const&);
- allocator_array_constructor& operator=(
- allocator_array_constructor const&);
+ array_constructor(array_constructor const&);
+ array_constructor& operator=(array_constructor const&);
};
}}}
diff --git a/include/boost/unordered/detail/buckets.hpp b/include/boost/unordered/detail/buckets.hpp
index fdb30b70..7492220b 100644
--- a/include/boost/unordered/detail/buckets.hpp
+++ b/include/boost/unordered/detail/buckets.hpp
@@ -7,65 +7,221 @@
#ifndef BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
-#include
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+#pragma warning(disable:4127) // conditional expression is constant
+#endif
namespace boost { namespace unordered { namespace detail {
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Now the main data structure:
- //
- // buckets functions
- // | |
- // +---------------+--------------+
- // |
- // table
- //
- // T is a class which contains typedefs for all the types we need.
-
- // buckets
- //
- // This is responsible for allocating and deallocating buckets and nodes.
- //
- // Notes:
- // 1. For the sake exception safety the consturctors don't allocate
- // anything.
- // 2. It's the callers responsibility to allocate the buckets before calling
- // any of the methods (other than getters and setters).
- template
- class buckets
+ template struct table;
+ template struct bucket;
+ struct ptr_bucket;
+ template struct buckets;
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // Node construction
+
+ template
+ struct node_constructor
{
+ private:
+
+ typedef NodeAlloc node_allocator;
+ typedef boost::unordered::detail::allocator_traits
+ node_allocator_traits;
+ typedef typename node_allocator_traits::value_type node;
+ typedef typename node_allocator_traits::pointer node_pointer;
+ typedef typename node::value_type value_type;
+
+ node_allocator& alloc_;
+ node_pointer node_;
+ bool node_constructed_;
+ bool value_constructed_;
+
+ public:
+
+ node_constructor(node_allocator& n) :
+ alloc_(n),
+ node_(),
+ node_constructed_(false),
+ value_constructed_(false)
+ {
+ }
+
+ ~node_constructor();
+
+ void construct_node();
+
+ template
+ void construct_value(BOOST_UNORDERED_EMPLACE_ARGS)
+ {
+ BOOST_ASSERT(node_ && node_constructed_ && !value_constructed_);
+ boost::unordered::detail::construct_impl(
+ node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
+ value_constructed_ = true;
+ }
+
+ template
+ void construct_value2(BOOST_FWD_REF(A0) a0)
+ {
+ BOOST_ASSERT(node_ && node_constructed_ && !value_constructed_);
+ boost::unordered::detail::construct_impl2(
+ node_->value_ptr(), boost::forward(a0));
+ value_constructed_ = true;
+ }
+
+ value_type const& value() const {
+ BOOST_ASSERT(node_ && node_constructed_ && value_constructed_);
+ return node_->value();
+ }
+
+ // no throw
+ node_pointer release()
+ {
+ node_pointer p = node_;
+ node_ = node_pointer();
+ return p;
+ }
+
+ private:
+ node_constructor(node_constructor const&);
+ node_constructor& operator=(node_constructor const&);
+ };
+
+ template
+ node_constructor::~node_constructor()
+ {
+ if (node_) {
+ if (value_constructed_) {
+ boost::unordered::detail::destroy(node_->value_ptr());
+ }
+
+ if (node_constructed_) {
+ node_allocator_traits::destroy(alloc_,
+ boost::addressof(*node_));
+ }
+
+ node_allocator_traits::deallocate(alloc_, node_, 1);
+ }
+ }
+
+ template
+ void node_constructor::construct_node()
+ {
+ if(!node_) {
+ node_constructed_ = false;
+ value_constructed_ = false;
+
+ node_ = node_allocator_traits::allocate(alloc_, 1);
+
+ node_allocator_traits::construct(alloc_,
+ boost::addressof(*node_), node());
+ node_->init(static_cast(node_));
+ node_constructed_ = true;
+ }
+ else {
+ BOOST_ASSERT(node_constructed_);
+
+ if (value_constructed_)
+ {
+ boost::unordered::detail::destroy(node_->value_ptr());
+ value_constructed_ = false;
+ }
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // Bucket
+
+ template
+ 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 };
+ };
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // Buckets
+
+ template
+ struct buckets
+ {
+ private:
buckets(buckets const&);
buckets& operator=(buckets const&);
public:
- // Types
+ typedef boost::unordered::detail::allocator_traits traits;
+ typedef typename traits::value_type value_type;
- typedef typename ::boost::detail::if_true::
- BOOST_NESTED_TEMPLATE then<
- ::boost::unordered::detail::ungrouped_node,
- ::boost::unordered::detail::grouped_node
- >::type node;
-
- typedef A value_allocator;
- typedef ::boost::unordered::detail::bucket bucket;
- typedef typename allocator_traits::value_type value_type;
-
- typedef typename bucket::bucket_allocator bucket_allocator;
- typedef typename allocator_traits::pointer bucket_ptr;
- typedef typename bucket::node_ptr node_ptr;
-
- typedef typename rebind_wrap::type
+ typedef Node node;
+ typedef Bucket bucket;
+ typedef typename boost::unordered::detail::rebind_wrap::type
node_allocator;
- typedef typename allocator_traits::pointer real_node_ptr;
+ typedef typename boost::unordered::detail::rebind_wrap::type
+ bucket_allocator;
+ typedef boost::unordered::detail::allocator_traits
+ node_allocator_traits;
+ typedef boost::unordered::detail::allocator_traits
+ 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_constructor;
// Members
- bucket_ptr buckets_;
+ bucket_pointer buckets_;
std::size_t bucket_count_;
std::size_t size_;
- compressed_pair allocators_;
-
+ boost::unordered::detail::compressed
+ allocators_;
+
// Data access
bucket_allocator const& bucket_alloc() const
@@ -91,120 +247,37 @@ namespace boost { namespace unordered { namespace detail {
std::size_t max_bucket_count() const
{
// -1 to account for the start bucket.
- return prev_prime(allocator_traits::max_size(bucket_alloc()) - 1);
+ return boost::unordered::detail::prev_prime(
+ bucket_allocator_traits::max_size(bucket_alloc()) - 1);
}
- ////////////////////////////////////////////////////////////////////////
- // Constructors and Destructors
-
- buckets(node_allocator const& a, std::size_t bucket_count)
- : buckets_(),
- bucket_count_(bucket_count),
- size_(),
- allocators_(a,a)
- {
- }
-
- buckets(buckets& b, move_tag m)
- : buckets_(),
- bucket_count_(b.bucket_count_),
- size_(),
- allocators_(b.allocators_, m)
- {
- swap(b);
- }
-
- template
- buckets(table& x, move_tag m)
- : buckets_(),
- bucket_count_(x.bucket_count_),
- allocators_(x.allocators_, m)
- {
- swap(x);
- x.size_ = 0;
- }
-
- inline ~buckets()
- {
- if(this->buckets_) { this->delete_buckets(); }
- }
-
- void create_buckets()
- {
- // The array constructor will clean up in the event of an
- // exception.
- allocator_array_constructor
- constructor(bucket_alloc());
-
- // Creates an extra bucket to act as the start node.
- constructor.construct(bucket(), this->bucket_count_ + 1);
-
- // Only release the buckets once everything is successfully
- // done.
- this->buckets_ = constructor.release();
- }
-
- void swap(buckets& other, false_type = false_type())
- {
- BOOST_ASSERT(node_alloc() == other.node_alloc());
- std::swap(buckets_, other.buckets_);
- std::swap(bucket_count_, other.bucket_count_);
- std::swap(size_, other.size_);
- }
-
- void swap(buckets& other, true_type)
- {
- allocators_.swap(other.allocators_);
- std::swap(buckets_, other.buckets_);
- std::swap(bucket_count_, other.bucket_count_);
- std::swap(size_, other.size_);
- }
-
- 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_ptr();
- other.bucket_count_ = 0;
- other.size_ = 0;
- }
-
- std::size_t bucket_size(std::size_t index) const
- {
- if (!this->size_) return 0;
- node_ptr ptr = this->buckets_[index].next_;
- if (!ptr) return 0;
- ptr = ptr->next_;
-
- std::size_t count = 0;
- while(BOOST_UNORDERED_BORLAND_BOOL(ptr) &&
- node::get_hash(ptr) % this->bucket_count_ == index)
- {
- ++count;
- ptr = ptr->next_;
- }
-
- return count;
- }
-
- node_ptr bucket_begin(std::size_t bucket_index) const
- {
- if (!this->size_) return node_ptr();
- bucket& b = this->buckets_[bucket_index];
- if (!b.next_) return node_ptr();
- return b.next_->next_;
- }
-
- // For the remaining functions, buckets_ must not be null.
-
- bucket_ptr get_bucket(std::size_t bucket_index) const
+ bucket_pointer get_bucket(std::size_t bucket_index) const
{
return buckets_ + static_cast(bucket_index);
}
+ previous_pointer get_previous_start() const
+ {
+ return this->get_bucket(this->bucket_count_)->first_from_start();
+ }
+
+ previous_pointer get_previous_start(std::size_t bucket_index) const
+ {
+ return this->get_bucket(bucket_index)->next_;
+ }
+
+ node_pointer get_start() const
+ {
+ return static_cast(this->get_previous_start()->next_);
+ }
+
+ node_pointer get_start(std::size_t bucket_index) const
+ {
+ previous_pointer prev = this->get_previous_start(bucket_index);
+ return prev ? static_cast(prev->next_) :
+ node_pointer();
+ }
+
float load_factor() const
{
BOOST_ASSERT(this->bucket_count_ != 0);
@@ -212,144 +285,235 @@ namespace boost { namespace unordered { namespace detail {
/ static_cast(this->bucket_count_);
}
- ////////////////////////////////////////////////////////////////////////
- // Delete
-
- void delete_node(node_ptr n)
+ std::size_t bucket_size(std::size_t index) const
{
- node* raw_ptr = static_cast(boost::addressof(*n));
- real_node_ptr real_ptr(node_alloc().address(*raw_ptr));
+ if (!this->size_) return 0;
+ node_pointer ptr = this->get_start(index);
+ if (!ptr) return 0;
- ::boost::unordered::detail::destroy(raw_ptr->value_ptr());
- allocator_traits::destroy(node_alloc(), raw_ptr);
- allocator_traits::deallocate(node_alloc(), real_ptr, 1);
+ std::size_t count = 0;
+ while(ptr && ptr->hash_ % this->bucket_count_ == index)
+ {
+ ++count;
+ ptr = static_cast(ptr->next_);
+ }
- --this->size_;
+ return count;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Constructors
+
+ buckets(node_allocator const& a, std::size_t bucket_count) :
+ buckets_(),
+ bucket_count_(bucket_count),
+ size_(),
+ allocators_(a,a)
+ {
+ }
+
+ buckets(buckets& b, boost::unordered::detail::move_tag m) :
+ buckets_(),
+ bucket_count_(b.bucket_count_),
+ size_(),
+ allocators_(b.allocators_, m)
+ {
+ swap(b);
+ }
+
+ template
+ buckets(boost::unordered::detail::table& x,
+ boost::unordered::detail::move_tag m) :
+ buckets_(),
+ bucket_count_(x.bucket_count_),
+ size_(),
+ allocators_(x.allocators_, m)
+ {
+ swap(x);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Create buckets
+ // (never called in constructor to avoid exception issues)
+
+ void create_buckets()
+ {
+ boost::unordered::detail::array_constructor
+ 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();
+
+ (constructor.get() +
+ static_cast(this->bucket_count_))->next_ =
+ a.release();
+ }
+
+ this->buckets_ = constructor.release();
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Swap and Move
+
+ void swap(buckets& other, false_type = false_type())
+ {
+ BOOST_ASSERT(node_alloc() == other.node_alloc());
+ boost::swap(buckets_, other.buckets_);
+ boost::swap(bucket_count_, other.bucket_count_);
+ boost::swap(size_, other.size_);
+ }
+
+ void swap(buckets& other, true_type)
+ {
+ allocators_.swap(other.allocators_);
+ boost::swap(buckets_, other.buckets_);
+ boost::swap(bucket_count_, other.bucket_count_);
+ boost::swap(size_, other.size_);
+ }
+
+ 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;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Delete/destruct
+
+ inline void delete_node(node_pointer n)
+ {
+ boost::unordered::detail::destroy(n->value_ptr());
+ node_allocator_traits::destroy(node_alloc(), boost::addressof(*n));
+ node_allocator_traits::deallocate(node_alloc(), n, 1);
+ --size_;
+ }
+
+ std::size_t delete_nodes(node_pointer begin, node_pointer end)
+ {
+ std::size_t count = 0;
+
+ while(begin != end) {
+ node_pointer n = begin;
+ begin = static_cast(begin->next_);
+ delete_node(n);
+ ++count;
+ }
+
+ return count;
+ }
+
+ inline void delete_extra_node(bucket_pointer) {}
+
+ inline void delete_extra_node(node_pointer n) {
+ node_allocator_traits::destroy(node_alloc(), boost::addressof(*n));
+ node_allocator_traits::deallocate(node_alloc(), n, 1);
+ }
+
+ inline ~buckets()
+ {
+ this->delete_buckets();
}
void delete_buckets()
{
- bucket_ptr end = this->get_bucket(this->bucket_count_);
- node_ptr n = (end)->next_;
- while(BOOST_UNORDERED_BORLAND_BOOL(n))
- {
- node_ptr node_to_delete = n;
- n = n->next_;
- delete_node(node_to_delete);
- }
-
- ++end;
- for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
- allocator_traits::destroy(bucket_alloc(),
- boost::addressof(*begin));
- }
-
- allocator_traits::deallocate(bucket_alloc(), this->buckets_, this->bucket_count_ + 1);
-
- this->buckets_ = bucket_ptr();
- BOOST_ASSERT(this->size_ == 0);
- }
+ if(this->buckets_) {
+ previous_pointer prev = this->get_previous_start();
- std::size_t delete_nodes(node_ptr begin, node_ptr end)
- {
- std::size_t count = 0;
- while(begin != end) {
- node_ptr n = begin;
- begin = begin->next_;
- delete_node(n);
- ++count;
+ while(prev->next_) {
+ node_pointer n = static_cast(prev->next_);
+ prev->next_ = n->next_;
+ delete_node(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();
}
- return count;
+
+ BOOST_ASSERT(!this->size_);
}
void clear()
{
if(!this->size_) return;
-
- bucket_ptr end = this->get_bucket(this->bucket_count_);
-
- node_ptr n = (end)->next_;
- while(BOOST_UNORDERED_BORLAND_BOOL(n))
+
+ previous_pointer prev = this->get_previous_start();
+
+ while(prev->next_) {
+ node_pointer n = static_cast(prev->next_);
+ prev->next_ = n->next_;
+ delete_node(n);
+ }
+
+ bucket_pointer end = this->get_bucket(this->bucket_count_);
+ for(bucket_pointer it = this->buckets_; it != end; ++it)
{
- node_ptr node_to_delete = n;
- n = n->next_;
- this->delete_node(node_to_delete);
+ it->next_ = node_pointer();
}
-
- ++end;
- for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
- begin->next_ = bucket_ptr();
- }
-
- this->size_ = 0;
- }
- node_ptr erase(node_ptr r)
- {
- BOOST_ASSERT(r);
- node_ptr next = r->next_;
-
- bucket_ptr bucket = this->get_bucket(
- node::get_hash(r) % this->bucket_count_);
- node_ptr prev = node::unlink_node(*bucket, r);
-
- this->fix_buckets(bucket, prev, next);
-
- this->delete_node(r);
-
- return next;
- }
-
- node_ptr erase_range(node_ptr r1, node_ptr r2)
- {
- if (r1 == r2) return r2;
-
- std::size_t bucket_index = node::get_hash(r1) % this->bucket_count_;
- node_ptr prev = node::unlink_nodes(
- this->buckets_[bucket_index], r1, r2);
- this->fix_buckets_range(bucket_index, prev, r1, r2);
- this->delete_nodes(r1, r2);
-
- return r2;
+ BOOST_ASSERT(!this->size_);
}
// This is called after erasing a node or group of nodes to fix up
// the bucket pointers.
- void fix_buckets(bucket_ptr bucket, node_ptr prev, node_ptr next)
+ void fix_buckets(bucket_pointer bucket,
+ previous_pointer prev, node_pointer next)
{
if (!next)
{
- if (bucket->next_ == prev) bucket->next_ = node_ptr();
+ if (bucket->next_ == prev) bucket->next_ = node_pointer();
}
else
{
- bucket_ptr next_bucket = this->get_bucket(
- node::get_hash(next) % this->bucket_count_);
+ bucket_pointer next_bucket = this->get_bucket(
+ next->hash_ % this->bucket_count_);
+
if (next_bucket != bucket)
{
next_bucket->next_ = prev;
- if (bucket->next_ == prev) bucket->next_ = node_ptr();
+ if (bucket->next_ == prev) bucket->next_ = node_pointer();
}
}
}
// This is called after erasing a range of nodes to fix any bucket
// pointers into that range.
- void fix_buckets_range(
- std::size_t bucket_index, node_ptr prev, node_ptr begin, node_ptr end)
+ void fix_buckets_range(std::size_t bucket_index,
+ previous_pointer prev, node_pointer begin, node_pointer end)
{
- node_ptr n = begin;
+ node_pointer n = begin;
// If we're not at the start of the current bucket, then
// go to the start of the next bucket.
if (this->get_bucket(bucket_index)->next_ != prev)
{
for(;;) {
- n = n->next_;
+ n = static_cast(n->next_);
if (n == end) return;
std::size_t new_bucket_index =
- node::get_hash(n) % this->bucket_count_;
+ n->hash_ % this->bucket_count_;
if (bucket_index != new_bucket_index) {
bucket_index = new_bucket_index;
break;
@@ -359,49 +523,30 @@ namespace boost { namespace unordered { namespace detail {
// Iterate through the remaining nodes, clearing out the bucket
// pointers.
- this->buckets_[bucket_index].next_ = bucket_ptr();
+ this->get_bucket(bucket_index)->next_ = previous_pointer();
for(;;) {
- n = n->next_;
+ n = static_cast(n->next_);
if (n == end) break;
std::size_t new_bucket_index =
- node::get_hash(n) % this->bucket_count_;
+ n->hash_ % this->bucket_count_;
if (bucket_index != new_bucket_index) {
bucket_index = new_bucket_index;
- this->buckets_[bucket_index].next_ = bucket_ptr();
+ this->get_bucket(bucket_index)->next_ = previous_pointer();
}
};
// Finally fix the bucket containing the trailing node.
- if (BOOST_UNORDERED_BORLAND_BOOL(n)) {
- this->buckets_[node::get_hash(n) % this->bucket_count_].next_
+ if (n) {
+ this->get_bucket(n->hash_ % this->bucket_count_)->next_
= prev;
}
}
-
- // Iterate through the nodes placing them in the correct buckets.
- // pre: prev->next_ is not null.
- node_ptr place_in_bucket(node_ptr prev, node_ptr end) {
- bucket_ptr b = this->get_bucket(node::get_hash(prev->next_) % this->bucket_count_);
-
- if (!b->next_) {
- b->next_ = prev;
- return end;
- }
- else {
- node_ptr next = end->next_;
- end->next_ = b->next_->next_;
- b->next_->next_ = prev->next_;
- prev->next_ = next;
- return prev;
- }
- }
-
- void copy_buckets_to(buckets&) const;
- void move_buckets_to(buckets&) const;
- void rehash_impl(std::size_t);
};
+ ////////////////////////////////////////////////////////////////////////////
+ // Functions
+
// Assigning and swapping the equality and hash function objects
// needs strong exception safety. To implement that normally we'd
// require one of them to be known to not throw and the other to
@@ -418,13 +563,14 @@ namespace boost { namespace unordered { namespace detail {
template
class functions
{
- friend class set_hash_functions;
+ friend class boost::unordered::detail::set_hash_functions;
functions& operator=(functions const&);
- typedef compressed_pair function_pair;
- typedef typename ::boost::aligned_storage<
+ typedef compressed function_pair;
+
+ typedef typename boost::aligned_storage<
sizeof(function_pair),
- ::boost::alignment_of::value>::type aligned_function;
+ boost::alignment_of::value>::type aligned_function;
bool current_; // The currently active functions.
aligned_function funcs_[2];
@@ -446,7 +592,7 @@ namespace boost { namespace unordered { namespace detail {
void destroy(bool which)
{
- ::boost::unordered::detail::destroy((function_pair*)(&funcs_[which]));
+ boost::unordered::detail::destroy((function_pair*)(&funcs_[which]));
}
public:
@@ -464,7 +610,7 @@ namespace boost { namespace unordered { namespace detail {
}
~functions() {
- destroy(current_);
+ this->destroy(current_);
}
H const& hash_function() const {
@@ -512,517 +658,10 @@ namespace boost { namespace unordered { namespace detail {
tmp_functions_ = !tmp_functions_;
}
};
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Value Construction
-
-#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
- template \
- 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\
- void construct_from_tuple(T* ptr, \
- namespace_::tuple 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(x)
-
-BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost)
-
-#if !defined(BOOST_NO_0X_HDR_TUPLE)
-BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std)
-#elif defined(BOOST_HAS_TR1_TUPLE)
-BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::tr1)
-#endif
-
-#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
- template
- struct emulation1 {
- static choice1::type check(choice1, std::pair const&);
- static choice2::type check(choice2, A const&);
-
- enum { value = sizeof(check(choose(), make())) == sizeof(choice2::type) };
- };
-#endif
-
-#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
- template
- struct check3_base {
- static choice1::type check(choice1, boost::unordered::piecewise_construct_t);
- static choice2::type check(choice2, A const&);
- static choice3::type check(choice3, ...);
- };
-#else
- template
- struct check3_base {
- static choice1::type check(choice1, boost::unordered::piecewise_construct_t);
- static choice3::type check(choice3, ...);
- };
-#endif
-
- template
- struct piecewise3 {
- enum { value =
- sizeof(check3_base::check(choose(), make())) ==
- sizeof(choice1::type) };
- };
-
- template
- struct emulation3 {
- enum { value =
- sizeof(check3_base::check(choose(), make())) ==
- sizeof(choice2::type) };
- };
-
- template
- struct normal3 {
- enum { value =
- sizeof(check3_base::check(choose(), make())) ==
- sizeof(choice3::type) };
- };
-
- template
- struct pair_construct1 {};
- template
- struct normal_construct1 { typedef void type; };
-
-#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
- template
- struct pair_construct1, Arg1>
- : enable_if, void> {};
-
- template
- struct normal_construct1, Arg1>
- : disable_if, void> {};
-#endif
-
- template
- struct piecewise_construct3 {};
- template
- struct piecewise_construct3, Arg1>
- : enable_if, void> {};
-
- template
- struct pair_construct3 {};
- template
- struct pair_construct3, Arg1>
- : enable_if, void> {};
-
- template
- struct normal_construct3 { typedef void type; };
- template
- struct normal_construct3, Arg1>
- : enable_if, void> {};
-
- template
- struct pair_construct_n {};
- template
- struct normal_construct_n { typedef void type; };
-
-#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
- template
- struct pair_construct_n > { typedef void type; };
- template
- struct normal_construct_n > {};
-#endif
-
- template
- inline void construct_impl(void* address)
- {
- new(address) T();
- }
-
- template
- inline typename normal_construct1::type
- construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1)
- {
- new(address) T(
- boost::forward(arg1)
- );
- }
-
- template
- inline typename pair_construct1::type
- construct_impl(void* address, BOOST_FWD_REF(Arg1) arg1)
- {
- new((void*)(&static_cast