Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r78349 - trunk/boost/unordered/detail
From: dnljms_at_[hidden]
Date: 2012-05-06 08:29:26


Author: danieljames
Date: 2012-05-06 08:29:24 EDT (Sun, 06 May 2012)
New Revision: 78349
URL: http://svn.boost.org/trac/boost/changeset/78349

Log:
Unordered: Use std::allocator_trait's variadic construct.
Text files modified:
   trunk/boost/unordered/detail/allocator_helpers.hpp | 225 +++++++++++++++++++++++++++++----------
   trunk/boost/unordered/detail/buckets.hpp | 94 +++++++++-------
   trunk/boost/unordered/detail/emplace_args.hpp | 36 ++++++
   trunk/boost/unordered/detail/equivalent.hpp | 42 ++++++
   trunk/boost/unordered/detail/unique.hpp | 40 ++++++
   5 files changed, 332 insertions(+), 105 deletions(-)

Modified: trunk/boost/unordered/detail/allocator_helpers.hpp
==============================================================================
--- trunk/boost/unordered/detail/allocator_helpers.hpp (original)
+++ trunk/boost/unordered/detail/allocator_helpers.hpp 2012-05-06 08:29:24 EDT (Sun, 06 May 2012)
@@ -15,14 +15,7 @@
 # pragma once
 #endif
 
-#include <boost/config.hpp>
-#include <boost/detail/select_type.hpp>
-#include <boost/utility/enable_if.hpp>
-#include <boost/preprocessor/cat.hpp>
-#include <boost/preprocessor/enum.hpp>
-#include <boost/limits.hpp>
-#include <boost/type_traits/add_lvalue_reference.hpp>
-#include <boost/pointer_to_other.hpp>
+#include <boost/unordered/detail/emplace_args.hpp>
 #include <boost/assert.hpp>
 #include <boost/utility/addressof.hpp>
 
@@ -31,23 +24,29 @@
 # if defined(__GXX_EXPERIMENTAL_CXX0X__) && \
             (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
 # define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
-# elif BOOST_MSVC >= 1700 && defined(_CPPLIB_VER)
-# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
-# endif
-
-// Use container's allocator_traits for older versions of Visual C++ as I don't
-// test with them.
-# if defined(BOOST_MSVC) && BOOST_MSVC < 1400
-# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 2
+# elif defined(BOOST_MSVC)
+# if BOOST_MSVC < 1400
+ // Use container's allocator_traits for older versions of Visual
+ // C++ as I don't test with them.
+# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 2
+# elif BOOST_MSVC >= 1700
+# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
+# endif
 # endif
-
 #endif
 
 #if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
 # define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
 #endif
 
-#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
+#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0
+# include <boost/limits.hpp>
+# include <boost/utility/enable_if.hpp>
+# include <boost/pointer_to_other.hpp>
+# if defined(BOOST_NO_SFINAE_EXPR)
+# include <boost/type_traits/is_same.hpp>
+# endif
+#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
 # include <memory>
 #elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
 # include <boost/container/allocator_traits.hpp>
@@ -57,6 +56,7 @@
 # include <type_traits>
 #endif
 
+
 namespace boost { namespace unordered { namespace detail {
 
     ////////////////////////////////////////////////////////////////////////////
@@ -98,43 +98,10 @@
 #endif
 
     ////////////////////////////////////////////////////////////////////////////
- // Bits and pieces for implementing traits
- //
- // Some of these are also used elsewhere
-
- template <typename T> typename boost::add_lvalue_reference<T>::type make();
- struct choice9 { typedef char (&type)[9]; };
- struct choice8 : choice9 { typedef char (&type)[8]; };
- struct choice7 : choice8 { typedef char (&type)[7]; };
- struct choice6 : choice7 { typedef char (&type)[6]; };
- struct choice5 : choice6 { typedef char (&type)[5]; };
- struct choice4 : choice5 { typedef char (&type)[4]; };
- struct choice3 : choice4 { typedef char (&type)[3]; };
- struct choice2 : choice3 { typedef char (&type)[2]; };
- struct choice1 : choice2 { typedef char (&type)[1]; };
- choice1 choose();
-
- typedef choice1::type yes_type;
- typedef choice2::type no_type;
-
- struct private_type
- {
- private_type const &operator,(int) const;
- };
-
- template <typename T>
- no_type is_private_type(T const&);
- yes_type is_private_type(private_type const&);
-
- struct convert_from_anything {
- template <typename T>
- convert_from_anything(T const&);
- };
+ // Expression test mechanism
 
 #if !defined(BOOST_NO_SFINAE_EXPR)
 
-# define BOOST_UNORDERED_HAVE_CALL_DETECTION 1
-
     template <typename T, unsigned int> struct expr_test;
     template <typename T> struct expr_test<T, sizeof(char)> : T {};
     template <typename U> static char for_expr_test(U const&);
@@ -165,8 +132,6 @@
 
 #else
 
-# define BOOST_UNORDERED_HAVE_CALL_DETECTION 0
-
     template <typename T> struct identity { typedef T type; };
 
 #define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
@@ -209,12 +174,11 @@
 
     ////////////////////////////////////////////////////////////////////////////
     // Allocator traits
- //
- // Uses the standard versions if available.
- // (although untested as I don't have access to a standard version yet)
 
 #if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
 
+#define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
+
     template <typename Alloc>
     struct allocator_traits : std::allocator_traits<Alloc> {};
 
@@ -227,6 +191,8 @@
 
 #elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
 
+#define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
+
     template <typename Alloc>
     struct allocator_traits :
         boost::container::allocator_traits<Alloc> {};
@@ -239,6 +205,13 @@
 
 #else
 
+#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
+# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
+#else
+# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
+#endif
+
+
     // TODO: Does this match std::allocator_traits<Alloc>::rebind_alloc<T>?
     template <typename Alloc, typename T>
     struct rebind_wrap
@@ -309,7 +282,7 @@
     BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
     BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
 
-#if BOOST_UNORDERED_HAVE_CALL_DETECTION
+#if !defined(BOOST_NO_SFINAE_EXPR)
     template <typename T>
     BOOST_UNORDERED_HAS_FUNCTION(
         select_on_container_copy_construction, U const, (), 0
@@ -320,12 +293,21 @@
         max_size, U const, (), 0
     );
 
+# if defined(BOOST_UNORDERED_VARIADIC_MOVE)
+ template <typename T, typename ValueType, typename... Args>
+ BOOST_UNORDERED_HAS_FUNCTION(
+ construct, U, (
+ boost::unordered::detail::make<ValueType*>(),
+ boost::unordered::detail::make<Args const>()...), 2
+ );
+# else
     template <typename T, typename ValueType>
     BOOST_UNORDERED_HAS_FUNCTION(
         construct, U, (
             boost::unordered::detail::make<ValueType*>(),
             boost::unordered::detail::make<ValueType const>()), 2
     );
+# endif
 
     template <typename T, typename ValueType>
     BOOST_UNORDERED_HAS_FUNCTION(
@@ -425,7 +407,27 @@
 
     public:
 
- // Only supporting the basic copy constructor for now.
+#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
+
+ template <typename T, typename... Args>
+ static typename boost::enable_if_c<
+ boost::unordered::detail::has_construct<Alloc, T, Args...>
+ ::value>::type
+ construct(Alloc& a, T* p, Args&&... x)
+ {
+ a.construct(p, boost::forward<Args>(x)...);
+ }
+
+ template <typename T, typename... Args>
+ static typename boost::disable_if_c<
+ boost::unordered::detail::has_construct<Alloc, T, Args...>
+ ::value>::type
+ construct(Alloc&, T* p, Args&&... x)
+ {
+ new ((void*) p) T(boost::forward<Args>(x)...);
+ }
+
+#elif !defined(BOOST_NO_SFINAE_EXPR)
 
         template <typename T>
         static typename boost::enable_if_c<
@@ -443,6 +445,52 @@
             new ((void*) p) T(x);
         }
 
+#else
+
+ // If we don't have SFINAE expressions, only construct the type
+ // that matches the allocator.
+
+ template <typename T>
+ static typename boost::enable_if_c<
+ boost::unordered::detail::has_construct<Alloc, T>::value &&
+ boost::is_same<T, value_type>::value
+ >::type
+ construct(Alloc& a, T* p, T const& x)
+ {
+ a.construct(p, x);
+ }
+
+ template <typename T>
+ static typename boost::disable_if_c<
+ boost::unordered::detail::has_construct<Alloc, T>::value &&
+ boost::is_same<T, value_type>::value
+ >::type
+ construct(Alloc&, T* p, T const& x)
+ {
+ new ((void*) p) T(x);
+ }
+
+#endif
+
+#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
+ template <typename T>
+ static typename boost::enable_if_c<
+ boost::unordered::detail::has_destroy<Alloc, T>::value>::type
+ destroy(Alloc& a, T* p)
+ {
+ a.destroy(p);
+ }
+
+ template <typename T>
+ static typename boost::disable_if_c<
+ boost::unordered::detail::has_destroy<Alloc, T>::value>::type
+ destroy(Alloc&, T* p)
+ {
+ boost::unordered::detail::destroy(p);
+ }
+
+#elif !defined(BOOST_NO_SFINAE_EXPR)
+
         template <typename T>
         static typename boost::enable_if_c<
                 boost::unordered::detail::has_destroy<Alloc, T>::value>::type
@@ -459,6 +507,30 @@
             boost::unordered::detail::destroy(p);
         }
 
+#else
+
+ template <typename T>
+ static typename boost::enable_if_c<
+ boost::unordered::detail::has_destroy<Alloc, T>::value &&
+ boost::is_same<T, value_type>::value
+ >::type
+ destroy(Alloc& a, T* p)
+ {
+ a.destroy(p);
+ }
+
+ template <typename T>
+ static typename boost::disable_if_c<
+ boost::unordered::detail::has_destroy<Alloc, T>::value &&
+ boost::is_same<T, value_type>::value
+ >::type
+ destroy(Alloc&, T* p)
+ {
+ boost::unordered::detail::destroy(p);
+ }
+
+#endif
+
         static size_type max_size(const Alloc& a)
         {
             return boost::unordered::detail::call_max_size<size_type>(a);
@@ -490,6 +562,41 @@
 
 #endif
 
+#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+ template <typename Alloc, typename T, BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ inline void construct_node(Alloc& a, T* p, BOOST_UNORDERED_EMPLACE_ARGS)
+ {
+ boost::unordered::detail::allocator_traits<Alloc>::construct(
+ a, p, BOOST_UNORDERED_EMPLACE_FORWARD);
+ }
+
+ template <typename Alloc, typename T>
+ inline void destroy_node(Alloc& a, T* p)
+ {
+ boost::unordered::detail::allocator_traits<Alloc>::destroy(a, p);
+ }
+#else
+ template <typename Alloc, typename T, BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ inline void construct_node(Alloc& a, T* p, BOOST_UNORDERED_EMPLACE_ARGS)
+ {
+ boost::unordered::detail::allocator_traits<Alloc>::construct(a, p, T());
+ try {
+ boost::unordered::detail::construct_impl(
+ p->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
+ } catch(...) {
+ boost::unordered::detail::allocator_traits<Alloc>::destroy(a, p);
+ throw;
+ }
+ }
+
+ template <typename Alloc, typename T>
+ inline void destroy_node(Alloc& a, T* p)
+ {
+ boost::unordered::detail::destroy(p->value_ptr());
+ boost::unordered::detail::allocator_traits<Alloc>::destroy(a, p);
+ }
+#endif
+
     // array_constructor
     //
     // Allocate and construct an array in an exception safe manner, and

Modified: trunk/boost/unordered/detail/buckets.hpp
==============================================================================
--- trunk/boost/unordered/detail/buckets.hpp (original)
+++ trunk/boost/unordered/detail/buckets.hpp 2012-05-06 08:29:24 EDT (Sun, 06 May 2012)
@@ -13,7 +13,6 @@
 
 #include <boost/unordered/detail/util.hpp>
 #include <boost/unordered/detail/allocator_helpers.hpp>
-#include <boost/unordered/detail/emplace_args.hpp>
 #include <boost/type_traits/aligned_storage.hpp>
 #include <boost/type_traits/alignment_of.hpp>
 #include <boost/swap.hpp>
@@ -54,16 +53,14 @@
 
         node_allocator& alloc_;
         node_pointer node_;
- bool node_constructed_;
- bool value_constructed_;
+ bool constructed_;
 
     public:
 
         node_constructor(node_allocator& n) :
             alloc_(n),
             node_(),
- node_constructed_(false),
- value_constructed_(false)
+ constructed_(false)
         {
         }
 
@@ -74,26 +71,40 @@
         template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
         void construct_value(BOOST_UNORDERED_EMPLACE_ARGS)
         {
- BOOST_ASSERT(node_ && node_constructed_ && !value_constructed_);
- boost::unordered::detail::construct_impl(
- node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
- value_constructed_ = true;
+ 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_ && node_constructed_ && !value_constructed_);
- boost::unordered::detail::construct_impl2(
- node_->value_ptr(), boost::forward<A0>(a0));
- value_constructed_ = true;
+ BOOST_ASSERT(node_ && !constructed_);
+# if defined(BOOST_UNORDERED_VARIADIC_MOVE)
+ boost::unordered::detail::construct_node(alloc_,
+ boost::addressof(*node_), boost::forward<A0>(a0));
+# else
+ boost::unordered::detail::construct_node(alloc_,
+ boost::addressof(*node_),
+ boost::unordered::detail::create_emplace_args(
+ boost::forward<A0>(a0)));
+# endif
+ constructed_ = true;
+ node_->init(static_cast<typename node::link_pointer>(node_));
         }
 
         value_type const& value() const {
- BOOST_ASSERT(node_ && node_constructed_ && value_constructed_);
+ BOOST_ASSERT(node_ && constructed_);
             return node_->value();
         }
 
+ node_pointer get()
+ {
+ return node_;
+ }
+
         // no throw
         node_pointer release()
         {
@@ -111,12 +122,8 @@
     node_constructor<Alloc>::~node_constructor()
     {
         if (node_) {
- if (value_constructed_) {
- boost::unordered::detail::destroy(node_->value_ptr());
- }
-
- if (node_constructed_) {
- node_allocator_traits::destroy(alloc_,
+ if (constructed_) {
+ boost::unordered::detail::destroy_node(alloc_,
                     boost::addressof(*node_));
             }
 
@@ -128,24 +135,13 @@
     void node_constructor<Alloc>::construct_node()
     {
         if(!node_) {
- node_constructed_ = false;
- value_constructed_ = false;
-
+ constructed_ = false;
             node_ = node_allocator_traits::allocate(alloc_, 1);
-
- node_allocator_traits::construct(alloc_,
- boost::addressof(*node_), node());
- node_->init(static_cast<typename node::link_pointer>(node_));
- node_constructed_ = true;
         }
- else {
- BOOST_ASSERT(node_constructed_);
-
- if (value_constructed_)
- {
- boost::unordered::detail::destroy(node_->value_ptr());
- value_constructed_ = false;
- }
+ else if (constructed_) {
+ boost::unordered::detail::destroy_node(alloc_,
+ boost::addressof(*node_));
+ constructed_ = false;
         }
     }
 
@@ -183,6 +179,16 @@
 
         enum { extra_node = false };
     };
+
+ template <typename LinkPointer>
+ struct node_base
+ {
+ typedef LinkPointer link_pointer;
+ link_pointer next_;
+
+ node_base() : next_() {}
+ };
+
 }}}
 
 namespace boost { namespace unordered { namespace iterator_detail {
@@ -718,6 +724,14 @@
                 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();
@@ -762,9 +776,8 @@
 
         inline void delete_node(c_iterator n)
         {
- boost::unordered::detail::destroy(n.node_->value_ptr());
- node_allocator_traits::destroy(node_alloc(),
- boost::addressof(*n.node_));
+ boost::unordered::detail::destroy_node(
+ node_alloc(), boost::addressof(*n.node_));
             node_allocator_traits::deallocate(node_alloc(), n.node_, 1);
             --size_;
         }
@@ -786,7 +799,8 @@
         inline void delete_extra_node(bucket_pointer) {}
 
         inline void delete_extra_node(node_pointer n) {
- node_allocator_traits::destroy(node_alloc(), boost::addressof(*n));
+ node_allocator_traits::destroy(node_alloc(),
+ static_cast<typename node::node_base*>(boost::addressof(*n)));
             node_allocator_traits::deallocate(node_alloc(), n, 1);
         }
 

Modified: trunk/boost/unordered/detail/emplace_args.hpp
==============================================================================
--- trunk/boost/unordered/detail/emplace_args.hpp (original)
+++ trunk/boost/unordered/detail/emplace_args.hpp 2012-05-06 08:29:24 EDT (Sun, 06 May 2012)
@@ -12,6 +12,7 @@
 # pragma once
 #endif
 
+#include <boost/unordered/detail/fwd.hpp>
 #include <boost/move/move.hpp>
 #include <boost/preprocessor/cat.hpp>
 #include <boost/preprocessor/inc.hpp>
@@ -21,7 +22,10 @@
 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
 #include <boost/type_traits/is_class.hpp>
+#include <boost/type_traits/add_lvalue_reference.hpp>
 #include <boost/tuple/tuple.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/detail/select_type.hpp>
 #include <utility>
 
 #if !defined(BOOST_NO_0X_HDR_TUPLE)
@@ -46,6 +50,38 @@
 namespace boost { namespace unordered { namespace detail {
 
     ////////////////////////////////////////////////////////////////////////////
+ // Bits and pieces for implementing traits
+
+ template <typename T> typename boost::add_lvalue_reference<T>::type make();
+ struct choice9 { typedef char (&type)[9]; };
+ struct choice8 : choice9 { typedef char (&type)[8]; };
+ struct choice7 : choice8 { typedef char (&type)[7]; };
+ struct choice6 : choice7 { typedef char (&type)[6]; };
+ struct choice5 : choice6 { typedef char (&type)[5]; };
+ struct choice4 : choice5 { typedef char (&type)[4]; };
+ struct choice3 : choice4 { typedef char (&type)[3]; };
+ struct choice2 : choice3 { typedef char (&type)[2]; };
+ struct choice1 : choice2 { typedef char (&type)[1]; };
+ choice1 choose();
+
+ typedef choice1::type yes_type;
+ typedef choice2::type no_type;
+
+ struct private_type
+ {
+ private_type const &operator,(int) const;
+ };
+
+ template <typename T>
+ no_type is_private_type(T const&);
+ yes_type is_private_type(private_type const&);
+
+ struct convert_from_anything {
+ template <typename T>
+ convert_from_anything(T const&);
+ };
+
+ ////////////////////////////////////////////////////////////////////////////
     // emplace_args
     //
     // Either forwarding variadic arguments, or storing the arguments in

Modified: trunk/boost/unordered/detail/equivalent.hpp
==============================================================================
--- trunk/boost/unordered/detail/equivalent.hpp (original)
+++ trunk/boost/unordered/detail/equivalent.hpp 2012-05-06 08:29:24 EDT (Sun, 06 May 2012)
@@ -12,7 +12,6 @@
 #endif
 
 #include <boost/unordered/detail/table.hpp>
-#include <boost/unordered/detail/emplace_args.hpp>
 #include <boost/unordered/detail/extract_key.hpp>
 
 namespace boost { namespace unordered { namespace detail {
@@ -23,20 +22,40 @@
 
     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;
 
- link_pointer next_;
         link_pointer group_prev_;
         std::size_t hash_;
 
+#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+ template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ grouped_node(BOOST_UNORDERED_EMPLACE_ARGS) :
+ node_base(),
+ group_prev_(),
+ hash_(0)
+ {
+ boost::unordered::detail::construct_impl(
+ this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
+ }
+
+ ~grouped_node() {
+ boost::unordered::detail::destroy(this->value_ptr());
+ }
+#else
         grouped_node() :
- next_(),
+ node_base(),
             group_prev_(),
             hash_(0)
         {}
+#endif
 
         void init(link_pointer self)
         {
@@ -50,16 +69,33 @@
         boost::unordered::detail::ptr_bucket
     {
         typedef boost::unordered::detail::ptr_bucket bucket_base;
+ typedef bucket_base node_base;
         typedef ptr_bucket* link_pointer;
 
         link_pointer group_prev_;
         std::size_t hash_;
 
+#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+ template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ grouped_ptr_node(BOOST_UNORDERED_EMPLACE_ARGS) :
+ bucket_base(),
+ group_prev_(0),
+ hash_(0)
+ {
+ boost::unordered::detail::construct_impl(
+ this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
+ }
+
+ ~grouped_ptr_node() {
+ boost::unordered::detail::destroy(this->value_ptr());
+ }
+#else
         grouped_ptr_node() :
             bucket_base(),
             group_prev_(0),
             hash_(0)
         {}
+#endif
 
         void init(link_pointer self)
         {

Modified: trunk/boost/unordered/detail/unique.hpp
==============================================================================
--- trunk/boost/unordered/detail/unique.hpp (original)
+++ trunk/boost/unordered/detail/unique.hpp 2012-05-06 08:29:24 EDT (Sun, 06 May 2012)
@@ -12,7 +12,6 @@
 #endif
 
 #include <boost/unordered/detail/table.hpp>
-#include <boost/unordered/detail/emplace_args.hpp>
 #include <boost/unordered/detail/extract_key.hpp>
 #include <boost/throw_exception.hpp>
 #include <stdexcept>
@@ -25,18 +24,37 @@
 
     template <typename A, typename T>
     struct node :
+ boost::unordered::detail::node_base<
+ typename ::boost::unordered::detail::rebind_wrap<
+ A, node<A, T> >::type::pointer
+ >,
         boost::unordered::detail::value_base<T>
     {
         typedef typename ::boost::unordered::detail::rebind_wrap<
             A, node<A, T> >::type::pointer link_pointer;
+ typedef boost::unordered::detail::node_base<link_pointer> node_base;
 
- link_pointer next_;
         std::size_t hash_;
 
+#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+ template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ node(BOOST_UNORDERED_EMPLACE_ARGS) :
+ node_base(),
+ hash_(0)
+ {
+ boost::unordered::detail::construct_impl(
+ this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
+ }
+
+ ~node() {
+ boost::unordered::detail::destroy(this->value_ptr());
+ }
+#else
         node() :
- next_(),
+ node_base(),
             hash_(0)
         {}
+#endif
 
         void init(link_pointer)
         {
@@ -49,14 +67,30 @@
         boost::unordered::detail::ptr_bucket
     {
         typedef boost::unordered::detail::ptr_bucket bucket_base;
+ typedef bucket_base node_base;
         typedef ptr_bucket* link_pointer;
 
         std::size_t hash_;
 
+#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
+ template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
+ ptr_node(BOOST_UNORDERED_EMPLACE_ARGS) :
+ bucket_base(),
+ hash_(0)
+ {
+ boost::unordered::detail::construct_impl(
+ this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
+ }
+
+ ~ptr_node() {
+ boost::unordered::detail::destroy(this->value_ptr());
+ }
+#else
         ptr_node() :
             bucket_base(),
             hash_(0)
         {}
+#endif
 
         void init(link_pointer)
         {


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk