summaryrefslogtreecommitdiff
path: root/boost/container/node_handle.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/container/node_handle.hpp')
-rw-r--r--boost/container/node_handle.hpp188
1 files changed, 116 insertions, 72 deletions
diff --git a/boost/container/node_handle.hpp b/boost/container/node_handle.hpp
index c46313cc4f..594a09c99e 100644
--- a/boost/container/node_handle.hpp
+++ b/boost/container/node_handle.hpp
@@ -23,7 +23,7 @@
#include <boost/container/detail/workaround.hpp>
#include <boost/static_assert.hpp>
#include <boost/container/detail/placement_new.hpp>
-#include <boost/container/detail/to_raw_pointer.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/mpl.hpp>
@@ -40,20 +40,34 @@ namespace container {
///@cond
-template<class Value, class KeyMapped, bool keymapped_is_void = container_detail::is_same<KeyMapped, void>::value>
+template<class Value, class KeyMapped>
struct node_handle_keymapped_traits
{
+ typedef typename KeyMapped::key_type key_type;
+ typedef typename KeyMapped::mapped_type mapped_type;
+};
+
+template<class Value>
+struct node_handle_keymapped_traits<Value, void>
+{
typedef Value key_type;
typedef Value mapped_type;
};
-template<class Value, class KeyMapped>
-struct node_handle_keymapped_traits<Value, KeyMapped, false>
+class node_handle_friend
{
- typedef typename KeyMapped::key_type key_type;
- typedef typename KeyMapped::mapped_type mapped_type;
+ public:
+
+ template<class NH>
+ BOOST_CONTAINER_FORCEINLINE static void destroy_alloc(NH &nh) BOOST_NOEXCEPT
+ { nh.destroy_alloc(); }
+
+ template<class NH>
+ BOOST_CONTAINER_FORCEINLINE static typename NH::node_pointer &get_node_pointer(NH &nh) BOOST_NOEXCEPT
+ { return nh.get_node_pointer(); }
};
+
///@endcond
//! A node_handle is an object that accepts ownership of a single element from an associative container.
@@ -73,76 +87,63 @@ struct node_handle_keymapped_traits<Value, KeyMapped, false>
//!
//! If a node handle is not empty, then it contains an allocator that is equal to the allocator of the container
//! when the element was extracted. If a node handle is empty, it contains no allocator.
-template <class NodeType, class Value, class Allocator, class KeyMapped = void>
+template <class NodeAllocator, class KeyMapped = void>
class node_handle
{
- typedef node_handle_keymapped_traits<Value, KeyMapped> keymapped_t;
+ typedef NodeAllocator nallocator_type;
+ typedef allocator_traits<NodeAllocator> nator_traits;
+ typedef typename nator_traits::value_type priv_node_t;
+ typedef typename priv_node_t::value_type priv_value_t;
+ typedef node_handle_keymapped_traits<priv_value_t, KeyMapped> keymapped_t;
public:
- typedef Value value_type;
+ typedef priv_value_t value_type;
typedef typename keymapped_t::key_type key_type;
typedef typename keymapped_t::mapped_type mapped_type;
- typedef Allocator allocator_type;
- typedef NodeType container_node_type;
+ typedef typename nator_traits::template portable_rebind_alloc
+ <value_type>::type allocator_type;
+
+ typedef priv_node_t container_node_type;
+ friend class node_handle_friend;
///@cond
private:
BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle)
- typedef allocator_traits<allocator_type> ator_traits;
- typedef typename ator_traits::template portable_rebind_alloc
- <container_node_type>::type nallocator_type;
- typedef allocator_traits<nallocator_type> node_ator_traits;
- typedef typename node_ator_traits::pointer node_pointer;
+ typedef typename nator_traits::pointer node_pointer;
typedef ::boost::aligned_storage
- <sizeof(allocator_type), boost::alignment_of<nallocator_type>::value> nalloc_storage_t;
+ < sizeof(nallocator_type)
+ , boost::alignment_of<nallocator_type>::value> nalloc_storage_t;
node_pointer m_ptr;
nalloc_storage_t m_nalloc_storage;
void move_construct_alloc(nallocator_type &al)
- { ::new(m_nalloc_storage.address(), boost_container_new_t()) allocator_type(::boost::move(al)); }
+ { ::new(m_nalloc_storage.address(), boost_container_new_t()) nallocator_type(::boost::move(al)); }
- void destroy_node()
+ void destroy_deallocate_node()
{
- node_ator_traits::destroy(this->node_alloc(), container_detail::to_raw_pointer(m_ptr));
- node_ator_traits::deallocate(this->node_alloc(), m_ptr, 1u);
+ nator_traits::destroy(this->node_alloc(), boost::movelib::to_raw_pointer(m_ptr));
+ nator_traits::deallocate(this->node_alloc(), m_ptr, 1u);
}
template<class OtherNodeHandle>
void move_construct_end(OtherNodeHandle &nh)
{
if(m_ptr){
- ::new (m_nalloc_storage.address(), boost_container_new_t()) allocator_type(::boost::move(nh.node_alloc()));
- nh.destroy_alloc();
- nh.get_node_pointer() = node_pointer();
+ ::new (m_nalloc_storage.address(), boost_container_new_t()) nallocator_type(::boost::move(nh.node_alloc()));
+ node_handle_friend::destroy_alloc(nh);
+ node_handle_friend::get_node_pointer(nh) = node_pointer();
}
BOOST_ASSERT(nh.empty());
}
- public:
-
- void destroy_alloc()
- { static_cast<allocator_type*>(m_nalloc_storage.address())->~allocator_type(); }
+ void destroy_alloc() BOOST_NOEXCEPT
+ { static_cast<nallocator_type*>(m_nalloc_storage.address())->~nallocator_type(); }
- node_pointer &get_node_pointer()
+ node_pointer &get_node_pointer() BOOST_NOEXCEPT
{ return m_ptr; }
- nallocator_type &node_alloc()
- { return *static_cast<nallocator_type*>(m_nalloc_storage.address()); }
-
- const nallocator_type &node_alloc() const
- { return *static_cast<const nallocator_type*>(m_nalloc_storage.address()); }
-
- node_pointer release()
- {
- node_pointer p(m_ptr);
- m_ptr = node_pointer();
- if(p)
- this->destroy_alloc();
- return p;
- }
-
///@endcond
public:
@@ -150,13 +151,13 @@ class node_handle
//!
//! <b>Postcondition</b>: this->empty()
BOOST_CXX14_CONSTEXPR node_handle() BOOST_NOEXCEPT
- : m_ptr(), m_nalloc_storage()
- { BOOST_ASSERT(this->empty()); }
+ : m_ptr()
+ { }
//! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with p.
- //! If p != nullptr copy constructs internal allocator al.
+ //! If p != nullptr copy constructs internal allocator from al.
node_handle(node_pointer p, const nallocator_type &al) BOOST_NOEXCEPT
- : m_ptr(p), m_nalloc_storage()
+ : m_ptr(p)
{
if(m_ptr){
::new (m_nalloc_storage.address(), boost_container_new_t()) nallocator_type(al);
@@ -172,12 +173,12 @@ class node_handle
//! <b>Note</b>: Two node_handle's are related if only one of KeyMapped template parameter
//! of a node handle is void.
template<class KeyMapped2>
- node_handle( BOOST_RV_REF_BEG node_handle<NodeType, Value, Allocator, KeyMapped2> BOOST_RV_REF_END nh
+ node_handle( BOOST_RV_REF_BEG node_handle<NodeAllocator, KeyMapped2> BOOST_RV_REF_END nh
, typename container_detail::enable_if_c
< ((unsigned)container_detail::is_same<KeyMapped, void>::value +
(unsigned)container_detail::is_same<KeyMapped2, void>::value) == 1u
- >::type* = 0)
- : m_ptr(nh.get_node_pointer()), m_nalloc_storage()
+ >::type* = 0) BOOST_NOEXCEPT
+ : m_ptr(nh.get())
{ this->move_construct_end(nh); }
//! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with nh's internal pointer
@@ -186,43 +187,44 @@ class node_handle
//!
//! <b>Postcondition</b>: nh.empty()
node_handle (BOOST_RV_REF(node_handle) nh) BOOST_NOEXCEPT
- : m_ptr(nh.m_ptr), m_nalloc_storage()
+ : m_ptr(nh.m_ptr)
{ this->move_construct_end(nh); }
//! <b>Effects</b>: If !this->empty(), destroys the value_type subobject in the container_node_type object
//! pointed to by c by calling allocator_traits<impl_defined>::destroy, then deallocates m_ptr by calling
- //! ator_traits::rebind_traits<container_node_type>::deallocate.
- ~node_handle () BOOST_NOEXCEPT
+ //! nator_traits::rebind_traits<container_node_type>::deallocate.
+ ~node_handle() BOOST_NOEXCEPT
{
if(!this->empty()){
- this->destroy_node();
+ this->destroy_deallocate_node();
this->destroy_alloc();
}
}
- //! <b>Requires</b>: Either this->empty(), or ator_traits::propagate_on_container_move_assignment is true, or
+ //! <b>Requires</b>: Either this->empty(), or nator_traits::propagate_on_container_move_assignment is true, or
//! node_alloc() == nh.node_alloc().
//!
//! <b>Effects</b>: If m_ptr != nullptr, destroys the value_type subobject in the container_node_type object
- //! pointed to by m_ptr by calling ator_traits::destroy, then deallocates m_ptr by calling ator_-
- //! traits::rebind_traits<container_node_type>::deallocate. Assigns nh.m_ptr to m_ptr. If this->empty()
- //! or ator_traits::propagate_on_container_move_assignment is true, move assigns nh.node_alloc() to
+ //! pointed to by m_ptr by calling nator_traits::destroy, then deallocates m_ptr by calling
+ //! nator_traits::deallocate. Assigns nh.m_ptr to m_ptr. If this->empty()
+ //! or nator_traits::propagate_on_container_move_assignment is true, move assigns nh.node_alloc() to
//! node_alloc(). Assigns nullptr to nh.m_ptr and assigns nullopt to nh.node_alloc().
+ //!
//! <b>Returns</b>: *this.
//!
//! <b>Throws</b>: Nothing.
- node_handle & operator=(BOOST_RV_REF(node_handle) nh)
+ node_handle & operator=(BOOST_RV_REF(node_handle) nh) BOOST_NOEXCEPT
{
- BOOST_ASSERT(this->empty() || nh.empty() || ator_traits::propagate_on_container_move_assignment::value
- || ator_traits::equal(node_alloc(), nh.node_alloc()));
+ BOOST_ASSERT(this->empty() || nator_traits::propagate_on_container_move_assignment::value
+ || nator_traits::equal(node_alloc(), nh.node_alloc()));
bool const was_this_non_null = !this->empty();
bool const was_nh_non_null = !nh.empty();
if(was_nh_non_null){
if(was_this_non_null){
- this->destroy_node();
- if(ator_traits::propagate_on_container_move_assignment::value){
+ this->destroy_deallocate_node();
+ if(nator_traits::propagate_on_container_move_assignment::value){
this->node_alloc() = ::boost::move(nh.node_alloc());
}
}
@@ -234,7 +236,7 @@ class node_handle
nh.destroy_alloc();
}
else if(was_this_non_null){
- this->destroy_node();
+ this->destroy_deallocate_node();
this->destroy_alloc();
m_ptr = node_pointer();
}
@@ -310,23 +312,23 @@ class node_handle
return !this->m_ptr;
}
- //! <b>Requires</b>: this->empty(), or nh.empty(), or ator_traits::propagate_on_container_swap is true, or
+ //! <b>Requires</b>: this->empty(), or nh.empty(), or nator_traits::propagate_on_container_swap is true, or
//! node_alloc() == nh.node_alloc().
//!
- //! <b>Effects</b>: Calls swap(m_ptr, nh.m_ptr). If this->empty(), or nh.empty(), or ator_traits::propagate_on_-
+ //! <b>Effects</b>: Calls swap(m_ptr, nh.m_ptr). If this->empty(), or nh.empty(), or nator_traits::propagate_on_-
//! container_swap is true calls swap(node_alloc(), nh.node_alloc()).
void swap(node_handle &nh)
- BOOST_NOEXCEPT_IF(ator_traits::propagate_on_container_swap::value || ator_traits::is_always_equal::value)
+ BOOST_NOEXCEPT_IF(nator_traits::propagate_on_container_swap::value || nator_traits::is_always_equal::value)
{
- BOOST_ASSERT(this->empty() || nh.empty() || ator_traits::propagate_on_container_swap::value
- || ator_traits::equal(node_alloc(), nh.node_alloc()));
+ BOOST_ASSERT(this->empty() || nh.empty() || nator_traits::propagate_on_container_swap::value
+ || nator_traits::equal(node_alloc(), nh.node_alloc()));
bool const was_this_non_null = !this->empty();
bool const was_nh_non_null = !nh.empty();
if(was_nh_non_null){
if(was_this_non_null){
- if(ator_traits::propagate_on_container_swap::value){
+ if(nator_traits::propagate_on_container_swap::value){
::boost::adl_move_swap(this->node_alloc(), nh.node_alloc());
}
}
@@ -337,11 +339,53 @@ class node_handle
}
else if(was_this_non_null){
nh.move_construct_alloc(this->node_alloc());
- nh.destroy_alloc();
+ this->destroy_alloc();
}
::boost::adl_move_swap(m_ptr, nh.m_ptr);
}
+ //! <b>Effects</b>: If this->empty() returns nullptr, otherwise returns m_ptr
+ //! resets m_ptr to nullptr and destroys the internal allocator.
+ //!
+ //! <b>Postcondition</b>: this->empty()
+ //!
+ //! <b>Note</b>: Non-standard extensions
+ node_pointer release() BOOST_NOEXCEPT
+ {
+ node_pointer p(m_ptr);
+ m_ptr = node_pointer();
+ if(p)
+ this->destroy_alloc();
+ return p;
+ }
+
+ //! <b>Effects</b>: Returns m_ptr.
+ //!
+ //! <b>Note</b>: Non-standard extensions
+ node_pointer get() const BOOST_NOEXCEPT
+ {
+ return m_ptr;
+ }
+
+ //! <b>Effects</b>: Returns a reference to the internal node allocator.
+ //!
+ //! <b>Note</b>: Non-standard extensions
+ nallocator_type &node_alloc() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(!empty());
+ return *static_cast<nallocator_type*>(m_nalloc_storage.address());
+ }
+
+
+ //! <b>Effects</b>: Returns a reference to the internal node allocator.
+ //!
+ //! <b>Note</b>: Non-standard extensions
+ const nallocator_type &node_alloc() const BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(!empty());
+ return *static_cast<const nallocator_type*>(m_nalloc_storage.address());
+ }
+
//! <b>Effects</b>: x.swap(y).
//!
friend void swap(node_handle & x, node_handle & y) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))