$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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)
         {