forked from boostorg/unordered
Support node_handle
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/core/explicit_operator_bool.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/unordered/detail/set.hpp>
|
||||
@@ -64,6 +65,8 @@ template <class T, class H, class P, class A> class unordered_set
|
||||
typedef typename table::l_iterator local_iterator;
|
||||
typedef typename table::c_iterator const_iterator;
|
||||
typedef typename table::iterator iterator;
|
||||
typedef typename types::node_type node_type;
|
||||
typedef typename types::insert_return_type insert_return_type;
|
||||
|
||||
private:
|
||||
table table_;
|
||||
@@ -203,6 +206,19 @@ template <class T, class H, class P, class A> class unordered_set
|
||||
|
||||
const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); }
|
||||
|
||||
// extract
|
||||
|
||||
node_type extract(const_iterator position)
|
||||
{
|
||||
return node_type(
|
||||
table_.extract_by_iterator(position), table_.node_alloc());
|
||||
}
|
||||
|
||||
node_type extract(const key_type& k)
|
||||
{
|
||||
return node_type(table_.extract_by_key(k), table_.node_alloc());
|
||||
}
|
||||
|
||||
// emplace
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
@@ -345,6 +361,27 @@ template <class T, class H, class P, class A> class unordered_set
|
||||
void insert(std::initializer_list<value_type>);
|
||||
#endif
|
||||
|
||||
insert_return_type insert(BOOST_RV_REF(node_type) np)
|
||||
{
|
||||
insert_return_type result;
|
||||
table_.move_insert_node_type(np, result);
|
||||
return boost::move(result);
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, BOOST_RV_REF(node_type) np)
|
||||
{
|
||||
return table_.move_insert_node_type_with_hint(hint, np);
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
private:
|
||||
// Note: Use r-value node_type to insert.
|
||||
insert_return_type insert(node_type&);
|
||||
iterator insert(const_iterator, node_type& np);
|
||||
|
||||
public:
|
||||
#endif
|
||||
|
||||
iterator erase(const_iterator);
|
||||
size_type erase(const key_type&);
|
||||
iterator erase(const_iterator, const_iterator);
|
||||
@@ -464,6 +501,7 @@ template <class T, class H, class P, class A> class unordered_multiset
|
||||
typedef typename table::l_iterator local_iterator;
|
||||
typedef typename table::c_iterator const_iterator;
|
||||
typedef typename table::iterator iterator;
|
||||
typedef typename types::node_type node_type;
|
||||
|
||||
private:
|
||||
table table_;
|
||||
@@ -604,6 +642,19 @@ template <class T, class H, class P, class A> class unordered_multiset
|
||||
|
||||
const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); }
|
||||
|
||||
// extract
|
||||
|
||||
node_type extract(const_iterator position)
|
||||
{
|
||||
return node_type(
|
||||
table_.extract_by_iterator(position), table_.node_alloc());
|
||||
}
|
||||
|
||||
node_type extract(const key_type& k)
|
||||
{
|
||||
return node_type(table_.extract_by_key(k), table_.node_alloc());
|
||||
}
|
||||
|
||||
// emplace
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
@@ -738,6 +789,25 @@ template <class T, class H, class P, class A> class unordered_multiset
|
||||
void insert(std::initializer_list<value_type>);
|
||||
#endif
|
||||
|
||||
iterator insert(BOOST_RV_REF(node_type) np)
|
||||
{
|
||||
return table_.move_insert_node_type(np);
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, BOOST_RV_REF(node_type) np)
|
||||
{
|
||||
return table_.move_insert_node_type_with_hint(hint, np);
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
private:
|
||||
// Note: Use r-value node_type to insert.
|
||||
iterator insert(node_type&);
|
||||
iterator insert(const_iterator, node_type& np);
|
||||
|
||||
public:
|
||||
#endif
|
||||
|
||||
iterator erase(const_iterator);
|
||||
size_type erase(const key_type&);
|
||||
iterator erase(const_iterator, const_iterator);
|
||||
@@ -1494,6 +1564,197 @@ inline void swap(
|
||||
#endif
|
||||
m1.swap(m2);
|
||||
}
|
||||
|
||||
template <typename N, typename T, typename A> class node_handle_set
|
||||
{
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle_set)
|
||||
|
||||
template <typename Types>
|
||||
friend struct ::boost::unordered::detail::table_impl;
|
||||
template <typename Types>
|
||||
friend struct ::boost::unordered::detail::grouped_table_impl;
|
||||
|
||||
typedef typename boost::unordered::detail::rebind_wrap<A, T>::type
|
||||
value_allocator;
|
||||
typedef boost::unordered::detail::allocator_traits<value_allocator>
|
||||
value_allocator_traits;
|
||||
typedef N node;
|
||||
typedef typename boost::unordered::detail::rebind_wrap<A, node>::type
|
||||
node_allocator;
|
||||
typedef boost::unordered::detail::allocator_traits<node_allocator>
|
||||
node_allocator_traits;
|
||||
typedef typename node_allocator_traits::pointer node_pointer;
|
||||
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef A allocator_type;
|
||||
|
||||
private:
|
||||
node_pointer ptr_;
|
||||
bool has_alloc_;
|
||||
boost::unordered::detail::value_base<value_allocator> alloc_;
|
||||
|
||||
public:
|
||||
BOOST_CONSTEXPR node_handle_set() BOOST_NOEXCEPT : ptr_(), has_alloc_(false)
|
||||
{
|
||||
}
|
||||
|
||||
/*BOOST_CONSTEXPR */ node_handle_set(
|
||||
node_pointer ptr, allocator_type const& a)
|
||||
: ptr_(ptr), has_alloc_(false)
|
||||
{
|
||||
if (ptr_) {
|
||||
new ((void*)&alloc_) value_allocator(a);
|
||||
has_alloc_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
~node_handle_set()
|
||||
{
|
||||
if (has_alloc_ && ptr_) {
|
||||
node_allocator node_alloc(alloc_.value());
|
||||
boost::unordered::detail::node_tmp<node_allocator> tmp(
|
||||
ptr_, node_alloc);
|
||||
}
|
||||
if (has_alloc_) {
|
||||
alloc_.value_ptr()->~value_allocator();
|
||||
}
|
||||
}
|
||||
|
||||
node_handle_set(BOOST_RV_REF(node_handle_set) n) BOOST_NOEXCEPT
|
||||
: ptr_(n.ptr_),
|
||||
has_alloc_(false)
|
||||
{
|
||||
if (n.has_alloc_) {
|
||||
new ((void*)&alloc_) value_allocator(boost::move(n.alloc_.value()));
|
||||
has_alloc_ = true;
|
||||
n.ptr_ = node_pointer();
|
||||
n.alloc_.value_ptr()->~value_allocator();
|
||||
n.has_alloc_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
node_handle_set& operator=(BOOST_RV_REF(node_handle_set) n)
|
||||
{
|
||||
BOOST_ASSERT(!has_alloc_ ||
|
||||
value_allocator_traits::
|
||||
propagate_on_container_move_assignment::value ||
|
||||
(n.has_alloc_ && alloc_.value() == n.alloc_.value()));
|
||||
|
||||
if (ptr_) {
|
||||
node_allocator node_alloc(alloc_.value());
|
||||
boost::unordered::detail::node_tmp<node_allocator> tmp(
|
||||
ptr_, node_alloc);
|
||||
ptr_ = node_pointer();
|
||||
}
|
||||
|
||||
if (has_alloc_) {
|
||||
alloc_.value_ptr()->~value_allocator();
|
||||
has_alloc_ = false;
|
||||
}
|
||||
|
||||
if (!has_alloc_ && n.has_alloc_) {
|
||||
move_allocator(n);
|
||||
}
|
||||
|
||||
ptr_ = n.ptr_;
|
||||
n.ptr_ = node_pointer();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
value_type& value() const { return ptr_->value(); }
|
||||
|
||||
allocator_type get_allocator() const { return alloc_.value(); }
|
||||
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
|
||||
|
||||
bool operator!() const BOOST_NOEXCEPT { return ptr_ ? 0 : 1; }
|
||||
|
||||
bool empty() const BOOST_NOEXCEPT { return ptr_ ? 0 : 1; }
|
||||
|
||||
void swap(node_handle_set& n) BOOST_NOEXCEPT_IF(
|
||||
value_allocator_traits::propagate_on_container_swap::value
|
||||
/* || value_allocator_traits::is_always_equal::value */)
|
||||
{
|
||||
if (!has_alloc_) {
|
||||
if (n.has_alloc_) {
|
||||
move_allocator(n);
|
||||
}
|
||||
} else if (!n.has_alloc_) {
|
||||
n.move_allocator(*this);
|
||||
} else {
|
||||
swap_impl(n, boost::unordered::detail::integral_constant<bool,
|
||||
value_allocator_traits::
|
||||
propagate_on_container_swap::value>());
|
||||
}
|
||||
boost::swap(ptr_, n.ptr_);
|
||||
}
|
||||
|
||||
private:
|
||||
void move_allocator(node_handle_set& n)
|
||||
{
|
||||
new ((void*)&alloc_) value_allocator(boost::move(n.alloc_.value()));
|
||||
n.alloc_.value_ptr()->~value_allocator();
|
||||
has_alloc_ = true;
|
||||
n.has_alloc_ = false;
|
||||
}
|
||||
|
||||
void swap_impl(node_handle_set&, boost::unordered::detail::false_type) {}
|
||||
|
||||
void swap_impl(node_handle_set& n, boost::unordered::detail::true_type)
|
||||
{
|
||||
boost::swap(alloc_, n.alloc_);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename N, typename T, typename A>
|
||||
void swap(node_handle_set<N, T, A>& x, node_handle_set<N, T, A>& y)
|
||||
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(x.swap(y)))
|
||||
{
|
||||
x.swap(y);
|
||||
}
|
||||
|
||||
template <typename N, typename T, typename A> struct insert_return_type_set
|
||||
{
|
||||
private:
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(insert_return_type_set)
|
||||
|
||||
typedef typename boost::unordered::detail::rebind_wrap<A, T>::type
|
||||
value_allocator;
|
||||
typedef N node_;
|
||||
|
||||
public:
|
||||
bool inserted;
|
||||
boost::unordered::iterator_detail::c_iterator<node_> position;
|
||||
boost::unordered::node_handle_set<N, T, A> node;
|
||||
|
||||
insert_return_type_set() : inserted(false), position(), node() {}
|
||||
|
||||
insert_return_type_set(BOOST_RV_REF(insert_return_type_set)
|
||||
x) BOOST_NOEXCEPT : inserted(x.inserted),
|
||||
position(x.position),
|
||||
node(boost::move(x.node))
|
||||
{
|
||||
}
|
||||
|
||||
insert_return_type_set& operator=(BOOST_RV_REF(insert_return_type_set) x)
|
||||
{
|
||||
inserted = x.inserted;
|
||||
position = x.position;
|
||||
node = boost::move(x.node);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename N, typename T, typename A>
|
||||
void swap(
|
||||
insert_return_type_set<N, T, A>& x, insert_return_type_set<N, T, A>& y)
|
||||
{
|
||||
boost::swap(x.node, y.node);
|
||||
boost::swap(x.inserted, y.inserted);
|
||||
boost::swap(x.position, y.position);
|
||||
}
|
||||
} // namespace unordered
|
||||
} // namespace boost
|
||||
|
||||
|
Reference in New Issue
Block a user