Support node_handle

This commit is contained in:
Daniel James
2017-02-27 03:59:02 +00:00
parent 9c4c3a754a
commit 21a24d6cd7
17 changed files with 2419 additions and 49 deletions

View File

@@ -3800,6 +3800,46 @@ struct table_impl : boost::unordered::detail::table<Types>
}
}
template <typename NodeType, typename InsertReturnType>
void move_insert_node_type(NodeType& np, InsertReturnType& result)
{
if (np) {
const_key_type& k = this->get_key(np.ptr_->value());
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
if (pos) {
result.node = boost::move(np);
result.position = iterator(pos);
} else {
this->reserve_for_insert(this->size_ + 1);
result.position = iterator(this->add_node(np.ptr_, key_hash));
result.inserted = true;
np.ptr_ = node_pointer();
}
}
}
template <typename NodeType>
iterator move_insert_node_type_with_hint(c_iterator hint, NodeType& np)
{
if (!np) {
return iterator();
}
const_key_type& k = this->get_key(np.ptr_->value());
if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
return iterator(hint.node_);
}
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
if (!pos) {
this->reserve_for_insert(this->size_ + 1);
pos = this->add_node(np.ptr_, key_hash);
np.ptr_ = node_pointer();
}
return iterator(pos);
}
////////////////////////////////////////////////////////////////////////
// Insert range methods
//
@@ -3876,39 +3916,87 @@ struct table_impl : boost::unordered::detail::table<Types>
} while (++i != j);
}
////////////////////////////////////////////////////////////////////////
// Extract
inline node_pointer extract_by_key(const_key_type& k)
{
if (!this->size_) {
return node_pointer();
}
std::size_t key_hash = this->hash(k);
std::size_t bucket_index = this->hash_to_bucket(key_hash);
link_pointer prev = find_previous_node(k, key_hash, bucket_index);
if (!prev) {
return node_pointer();
}
node_pointer n = next_node(prev);
prev->next_ = n->next_;
--this->size_;
this->fix_bucket(bucket_index, prev);
n->next_ = link_pointer();
return n;
}
inline node_pointer extract_by_iterator(c_iterator i)
{
node_pointer n = i.node_;
BOOST_ASSERT(n);
std::size_t key_hash = n->hash_;
std::size_t bucket_index = this->hash_to_bucket(key_hash);
link_pointer prev = this->get_previous_start(bucket_index);
while (prev->next_ != n) {
prev = prev->next_;
}
prev->next_ = n->next_;
--this->size_;
this->fix_bucket(bucket_index, prev);
n->next_ = link_pointer();
return n;
}
////////////////////////////////////////////////////////////////////////
// Erase
//
// no throw
link_pointer find_previous_node(
const_key_type& k, std::size_t key_hash, std::size_t bucket_index)
{
link_pointer prev = this->get_previous_start(bucket_index);
if (!prev) {
return prev;
}
for (;;) {
if (!prev->next_) {
return link_pointer();
}
std::size_t node_hash = next_node(prev)->hash_;
if (this->hash_to_bucket(node_hash) != bucket_index) {
return link_pointer();
}
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(next_node(prev)->value()))) {
return prev;
}
prev = prev->next_;
}
}
std::size_t erase_key(const_key_type& k)
{
if (!this->size_)
return 0;
std::size_t key_hash = this->hash(k);
std::size_t bucket_index = this->hash_to_bucket(key_hash);
link_pointer prev = this->get_previous_start(bucket_index);
link_pointer prev = find_previous_node(k, key_hash, bucket_index);
if (!prev)
return 0;
for (;;) {
if (!prev->next_)
return 0;
std::size_t node_hash = next_node(prev)->hash_;
if (this->hash_to_bucket(node_hash) != bucket_index)
return 0;
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(next_node(prev)->value())))
break;
prev = prev->next_;
}
link_pointer end = next_node(prev)->next_;
std::size_t deleted_count = this->delete_nodes(prev, end);
this->delete_nodes(prev, end);
this->fix_bucket(bucket_index, prev);
return deleted_count;
return 1;
}
iterator erase(c_iterator r)
@@ -4459,6 +4547,45 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
this->add_node(a.release(), key_hash, position);
}
template <typename NodeType> iterator move_insert_node_type(NodeType& np)
{
iterator result;
if (np) {
const_key_type& k = this->get_key(np.ptr_->value());
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
this->reserve_for_insert(this->size_ + 1);
result = iterator(this->add_node(np.ptr_, key_hash, pos));
np.ptr_ = node_pointer();
}
return result;
}
template <typename NodeType>
iterator move_insert_node_type_with_hint(c_iterator hint, NodeType& np)
{
iterator result;
if (np) {
const_key_type& k = this->get_key(np.ptr_->value());
if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
this->reserve_for_insert(this->size_ + 1);
result = iterator(this->add_using_hint(np.ptr_, hint.node_));
} else {
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
this->reserve_for_insert(this->size_ + 1);
result = iterator(this->add_node(np.ptr_, key_hash, pos));
}
np.ptr_ = node_pointer();
}
return result;
}
////////////////////////////////////////////////////////////////////////
// Insert range methods
@@ -4499,11 +4626,95 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
}
}
////////////////////////////////////////////////////////////////////////
// Extract
inline node_pointer extract_by_key(const_key_type& k)
{
if (!this->size_) {
return node_pointer();
}
std::size_t key_hash = this->hash(k);
std::size_t bucket_index = this->hash_to_bucket(key_hash);
link_pointer prev = find_previous_node(k, key_hash, bucket_index);
if (!prev) {
return node_pointer();
}
node_pointer n = next_node(prev);
if (n->group_prev_ != n) {
node_pointer next = next_node(n);
next->group_prev_ = n->group_prev_;
n->group_prev_ = n;
}
prev->next_ = n->next_;
--this->size_;
this->fix_bucket(bucket_index, prev);
n->next_ = link_pointer();
return n;
}
inline node_pointer extract_by_iterator(c_iterator n)
{
node_pointer i = n.node_;
BOOST_ASSERT(i);
node_pointer j(next_node(i));
std::size_t bucket_index = this->hash_to_bucket(i->hash_);
// Split the groups containing 'i' and 'j'.
// And get the pointer to the node before i while
// we're at it.
link_pointer prev = split_groups(i, j);
// If we don't have a 'prev' it means that i is at the
// beginning of a block, so search through the blocks in the
// same bucket.
if (!prev) {
prev = this->get_previous_start(bucket_index);
while (prev->next_ != i) {
prev = next_node(prev)->group_prev_;
}
}
prev->next_ = i->next_;
--this->size_;
this->fix_bucket(bucket_index, prev);
i->next_ = link_pointer();
return i;
}
////////////////////////////////////////////////////////////////////////
// Erase
//
// no throw
link_pointer find_previous_node(
const_key_type& k, std::size_t key_hash, std::size_t bucket_index)
{
link_pointer prev = this->get_previous_start(bucket_index);
if (!prev) {
return prev;
}
for (;;) {
if (!prev->next_) {
return link_pointer();
}
node_pointer first_node = next_node(prev);
std::size_t node_hash = first_node->hash_;
if (this->hash_to_bucket(node_hash) != bucket_index) {
return link_pointer();
}
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(first_node->value()))) {
return prev;
}
prev = first_node->group_prev_;
}
}
std::size_t erase_key(const_key_type& k)
{
if (!this->size_)
@@ -4511,25 +4722,11 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
std::size_t key_hash = this->hash(k);
std::size_t bucket_index = this->hash_to_bucket(key_hash);
link_pointer prev = this->get_previous_start(bucket_index);
link_pointer prev = find_previous_node(k, key_hash, bucket_index);
if (!prev)
return 0;
node_pointer first_node;
for (;;) {
if (!prev->next_)
return 0;
first_node = next_node(prev);
std::size_t node_hash = first_node->hash_;
if (this->hash_to_bucket(node_hash) != bucket_index)
return 0;
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(first_node->value())))
break;
prev = first_node->group_prev_;
}
node_pointer first_node = next_node(prev);
link_pointer end = first_node->group_prev_->next_;
std::size_t deleted_count = this->delete_nodes(prev, end);

View File

@@ -39,6 +39,10 @@ template <typename A, typename K, typename M, typename H, typename P> struct map
l_iterator;
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
cl_iterator;
typedef boost::unordered::node_handle_map<node, K, M, A> node_type;
typedef boost::unordered::insert_return_type_map<node, K, M, A>
insert_return_type;
};
template <typename A, typename K, typename M, typename H, typename P>
@@ -72,6 +76,25 @@ struct multimap
l_iterator;
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
cl_iterator;
typedef boost::unordered::node_handle_map<node, K, M, A> node_type;
};
template <typename K, typename M, typename H, typename P, typename A>
class instantiate_map
{
typedef boost::unordered_map<K, M, H, P, A> container;
container x;
typename container::node_type node_type;
typename container::insert_return_type insert_return_type;
};
template <typename K, typename M, typename H, typename P, typename A>
class instantiate_multimap
{
typedef boost::unordered_multimap<K, M, H, P, A> container;
container x;
typename container::node_type node_type;
};
}
}

View File

@@ -39,6 +39,10 @@ template <typename A, typename T, typename H, typename P> struct set
l_iterator;
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
cl_iterator;
typedef boost::unordered::node_handle_set<node, T, A> node_type;
typedef boost::unordered::insert_return_type_set<node, T, A>
insert_return_type;
};
template <typename A, typename T, typename H, typename P> struct multiset
@@ -71,6 +75,24 @@ template <typename A, typename T, typename H, typename P> struct multiset
l_iterator;
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
cl_iterator;
typedef boost::unordered::node_handle_set<node, T, A> node_type;
};
template <typename T, typename H, typename P, typename A> class instantiate_set
{
typedef boost::unordered_set<T, H, P, A> container;
container x;
typename container::node_type node_type;
typename container::insert_return_type insert_return_type;
};
template <typename T, typename H, typename P, typename A>
class instantiate_multiset
{
typedef boost::unordered_multiset<T, H, P, A> container;
container x;
typename container::node_type node_type;
};
}
}

View File

@@ -14,10 +14,10 @@
#pragma once
#endif
#include <boost/core/explicit_operator_bool.hpp>
#include <boost/functional/hash.hpp>
#include <boost/move/move.hpp>
#include <boost/unordered/detail/map.hpp>
#include <boost/unordered/unordered_map_fwd.hpp>
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
#include <initializer_list>
@@ -67,6 +67,8 @@ template <class K, class T, class H, class P, class A> class unordered_map
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_;
@@ -206,6 +208,19 @@ template <class K, class T, class H, class P, class A> class unordered_map
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)
@@ -572,6 +587,27 @@ template <class K, class T, class H, class P, class A> class unordered_map
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);
@@ -703,6 +739,7 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
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_;
@@ -843,6 +880,19 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
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)
@@ -977,6 +1027,25 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
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);
@@ -1816,6 +1885,199 @@ inline void swap(unordered_multimap<K, T, H, P, A>& m1,
m1.swap(m2);
}
template <typename N, class K, class T, class A> class node_handle_map
{
BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle_map)
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,
std::pair<K const, 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 K key_type;
typedef T mapped_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_map() BOOST_NOEXCEPT : ptr_(), has_alloc_(false)
{
}
/*BOOST_CONSTEXPR */ node_handle_map(
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_map()
{
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_map(BOOST_RV_REF(node_handle_map) 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_map& operator=(BOOST_RV_REF(node_handle_map) 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;
}
key_type& key() const { return const_cast<key_type&>(ptr_->value().first); }
mapped_type& mapped() const { return ptr_->value().second; }
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_map& 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_map& 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_map&, boost::unordered::detail::false_type) {}
void swap_impl(node_handle_map& n, boost::unordered::detail::true_type)
{
boost::swap(alloc_, n.alloc_);
}
};
template <class N, class K, class T, class A>
void swap(node_handle_map<N, K, T, A>& x, node_handle_map<N, K, T, A>& y)
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(x.swap(y)))
{
x.swap(y);
}
template <class N, class K, class T, class A> struct insert_return_type_map
{
private:
BOOST_MOVABLE_BUT_NOT_COPYABLE(insert_return_type_map)
typedef typename boost::unordered::detail::rebind_wrap<A,
std::pair<K const, T> >::type value_allocator;
typedef N node_;
public:
bool inserted;
boost::unordered::iterator_detail::iterator<node_> position;
boost::unordered::node_handle_map<N, K, T, A> node;
insert_return_type_map() : inserted(false), position(), node() {}
insert_return_type_map(BOOST_RV_REF(insert_return_type_map)
x) BOOST_NOEXCEPT : inserted(x.inserted),
position(x.position),
node(boost::move(x.node))
{
}
insert_return_type_map& operator=(BOOST_RV_REF(insert_return_type_map) x)
{
inserted = x.inserted;
position = x.position;
node = boost::move(x.node);
return *this;
}
};
template <class N, class K, class T, class A>
void swap(insert_return_type_map<N, K, T, A>& x,
insert_return_type_map<N, K, 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

View File

@@ -46,6 +46,9 @@ inline bool operator!=(unordered_multimap<K, T, H, P, A> const&,
template <class K, class T, class H, class P, class A>
inline void swap(
unordered_multimap<K, T, H, P, A>&, unordered_multimap<K, T, H, P, A>&);
template <class N, class K, class T, class A> class node_handle_map;
template <class N, class K, class T, class A> struct insert_return_type_map;
}
using boost::unordered::unordered_map;

View File

@@ -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

View File

@@ -44,6 +44,9 @@ inline bool operator!=(unordered_multiset<T, H, P, A> const&,
template <class T, class H, class P, class A>
inline void swap(
unordered_multiset<T, H, P, A>& m1, unordered_multiset<T, H, P, A>& m2);
template <class N, class T, class A> class node_handle_set;
template <class N, class T, class A> struct insert_return_type_set;
}
using boost::unordered::unordered_set;