mirror of
https://github.com/boostorg/unordered.git
synced 2025-05-11 13:34:06 +00:00
Since all the compilers support out of line template members use them
and lots of other things. [SVN r56329]
This commit is contained in:
parent
491fa330f6
commit
78b078f41d
@ -99,7 +99,8 @@ namespace boost { namespace unordered_detail {
|
||||
}
|
||||
private:
|
||||
allocator_array_constructor(allocator_array_constructor const&);
|
||||
allocator_array_constructor& operator=(allocator_array_constructor const&);
|
||||
allocator_array_constructor& operator=(
|
||||
allocator_array_constructor const&);
|
||||
};
|
||||
}}
|
||||
|
||||
|
@ -14,23 +14,123 @@
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Explicitly call a destructor
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# define BOOST_UNORDERED_DESTRUCT(x, type) (x)->~type();
|
||||
#else
|
||||
# define BOOST_UNORDERED_DESTRUCT(x, type) boost::unordered_detail::destroy(x)
|
||||
template <class T>
|
||||
void destroy(T* x) {
|
||||
x->~T();
|
||||
// Buckets
|
||||
// TODO: Are these needed?
|
||||
|
||||
template <class A, class G>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
|
||||
hash_buckets<A, G>::get_bucket(std::size_t n) const
|
||||
{
|
||||
return buckets_ + static_cast<std::ptrdiff_t>(n);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Constructors
|
||||
|
||||
template <class A, class G>
|
||||
hash_buckets<A, G>::hash_buckets(node_allocator const& a, std::size_t bucket_count)
|
||||
: buckets_(), allocators_(a,a)
|
||||
inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
|
||||
hash_buckets<A, G>::bucket_ptr_from_hash(std::size_t hashed) const
|
||||
{
|
||||
return get_bucket(hashed % bucket_count_);
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline std::size_t hash_buckets<A, G>::bucket_size(std::size_t index) const
|
||||
{
|
||||
if(!buckets_) return 0;
|
||||
bucket_ptr ptr = get_bucket(index)->next_;
|
||||
std::size_t count = 0;
|
||||
while(ptr) {
|
||||
++count;
|
||||
ptr = ptr->next_;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::node_ptr
|
||||
hash_buckets<A, G>::bucket_begin(std::size_t n) const
|
||||
{
|
||||
return buckets_ ? get_bucket(n)->next_ : node_ptr();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Delete
|
||||
|
||||
template <class A, class G>
|
||||
inline void hash_buckets<A, G>::delete_node(node_ptr b)
|
||||
{
|
||||
node* raw_ptr = static_cast<node*>(&*b);
|
||||
boost::unordered_detail::destroy(&raw_ptr->value());
|
||||
real_node_ptr n(node_alloc().address(*raw_ptr));
|
||||
node_alloc().destroy(n);
|
||||
node_alloc().deallocate(n, 1);
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline void hash_buckets<A, G>::clear_bucket(bucket_ptr b)
|
||||
{
|
||||
node_ptr node_it = b->next_;
|
||||
b->next_ = node_ptr();
|
||||
|
||||
while(node_it) {
|
||||
node_ptr node_to_delete = node_it;
|
||||
node_it = node_it->next_;
|
||||
delete_node(node_to_delete);
|
||||
}
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline void hash_buckets<A, G>::delete_buckets()
|
||||
{
|
||||
bucket_ptr end = this->get_bucket(this->bucket_count_);
|
||||
|
||||
for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
|
||||
clear_bucket(begin);
|
||||
}
|
||||
|
||||
// Destroy the buckets (including the sentinel bucket).
|
||||
++end;
|
||||
for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
|
||||
bucket_alloc().destroy(begin);
|
||||
}
|
||||
|
||||
bucket_alloc().deallocate(this->buckets_, this->bucket_count_ + 1);
|
||||
|
||||
this->buckets_ = bucket_ptr();
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline std::size_t hash_buckets<A, G>::delete_nodes(
|
||||
node_ptr begin, node_ptr end)
|
||||
{
|
||||
std::size_t count = 0;
|
||||
while(begin != end) {
|
||||
node_ptr node = begin;
|
||||
begin = begin->next_;
|
||||
delete_node(node);
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Constructors and Destructors
|
||||
|
||||
template <class A, class G>
|
||||
inline hash_buckets<A, G>::hash_buckets(
|
||||
node_allocator const& a, std::size_t bucket_count)
|
||||
: buckets_(),
|
||||
bucket_count_(bucket_count),
|
||||
allocators_(a,a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline hash_buckets<A, G>::~hash_buckets()
|
||||
{
|
||||
if(this->buckets_) { this->delete_buckets(); }
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline void hash_buckets<A, G>::create_buckets()
|
||||
{
|
||||
// The array constructor will clean up in the event of an
|
||||
// exception.
|
||||
@ -38,52 +138,27 @@ namespace boost { namespace unordered_detail {
|
||||
constructor(bucket_alloc());
|
||||
|
||||
// Creates an extra bucket to act as a sentinel.
|
||||
constructor.construct(bucket(), bucket_count + 1);
|
||||
constructor.construct(bucket(), this->bucket_count_ + 1);
|
||||
|
||||
// Set up the sentinel (node_ptr cast)
|
||||
bucket_ptr sentinel = constructor.get() + static_cast<ptrdiff_t>(bucket_count);
|
||||
bucket_ptr sentinel = constructor.get() +
|
||||
static_cast<ptrdiff_t>(this->bucket_count_);
|
||||
sentinel->next_ = sentinel;
|
||||
|
||||
// Only release the buckets once everything is successfully
|
||||
// done.
|
||||
this->buckets_ = constructor.release();
|
||||
this->bucket_count_ = bucket_count;
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
hash_buckets<A, G>::hash_buckets(hash_buckets& x, move_tag)
|
||||
: buckets_(), allocators_(x.allocators_)
|
||||
{
|
||||
this->buckets_ = x.buckets_;
|
||||
this->bucket_count_ = x.bucket_count_;
|
||||
x.buckets_ = bucket_ptr();
|
||||
x.bucket_count_ = 0;
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
hash_buckets<A, G>::hash_buckets(hash_buckets& x, value_allocator const& a, move_tag) :
|
||||
buckets_(), allocators_(a,a)
|
||||
{
|
||||
if(this->node_alloc() == x.node_alloc()) {
|
||||
this->buckets_ = x.buckets_;
|
||||
this->bucket_count_ = x.bucket_count_;
|
||||
x.buckets_ = bucket_ptr();
|
||||
x.bucket_count_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
hash_buckets<A, G>::~hash_buckets()
|
||||
{
|
||||
if(this->buckets_) { delete_buckets(); }
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Constructors and Destructors
|
||||
|
||||
// no throw
|
||||
template <class A, class G>
|
||||
inline void hash_buckets<A, G>::move(hash_buckets& other)
|
||||
{
|
||||
BOOST_ASSERT(node_alloc() == other.node_alloc());
|
||||
delete_buckets();
|
||||
if(this->buckets_) { this->delete_buckets(); }
|
||||
this->buckets_ = other.buckets_;
|
||||
this->bucket_count_ = other.bucket_count_;
|
||||
other.buckets_ = bucket_ptr();
|
||||
@ -97,166 +172,6 @@ namespace boost { namespace unordered_detail {
|
||||
std::swap(buckets_, other.buckets_);
|
||||
std::swap(bucket_count_, other.bucket_count_);
|
||||
}
|
||||
|
||||
// Buckets
|
||||
|
||||
template <class A, class G>
|
||||
inline std::size_t hash_buckets<A, G>::bucket_count() const
|
||||
{
|
||||
return bucket_count_;
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline std::size_t hash_buckets<A, G>::bucket_from_hash(std::size_t hashed) const
|
||||
{
|
||||
return hashed % bucket_count_;
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
|
||||
hash_buckets<A, G>::bucket_ptr_from_hash(std::size_t hashed) const
|
||||
{
|
||||
return buckets_ + static_cast<std::ptrdiff_t>(
|
||||
bucket_from_hash(hashed));
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
|
||||
hash_buckets<A, G>::buckets_begin() const
|
||||
{
|
||||
return buckets_;
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
|
||||
hash_buckets<A, G>::buckets_end() const
|
||||
{
|
||||
return buckets_ + static_cast<std::ptrdiff_t>(bucket_count_);
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline std::size_t hash_buckets<A, G>::bucket_size(std::size_t index) const
|
||||
{
|
||||
bucket_ptr ptr = (buckets_ + static_cast<std::ptrdiff_t>(index))->next_;
|
||||
std::size_t count = 0;
|
||||
while(ptr) {
|
||||
++count;
|
||||
ptr = next_node(ptr);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
|
||||
hash_buckets<A, G>::get_bucket(std::size_t n) const
|
||||
{
|
||||
return buckets_ + static_cast<std::ptrdiff_t>(n);
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::node_ptr
|
||||
hash_buckets<A, G>::bucket_begin(std::size_t n) const
|
||||
{
|
||||
return (buckets_ + static_cast<std::ptrdiff_t>(n))->next_;
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::node_ptr
|
||||
hash_buckets<A, G>::bucket_end(std::size_t) const
|
||||
{
|
||||
return node_ptr();
|
||||
}
|
||||
|
||||
// Construct/destruct
|
||||
|
||||
template <class A, class G>
|
||||
inline void hash_buckets<A, G>::destruct_node(node_ptr b)
|
||||
{
|
||||
node* raw_ptr = static_cast<node*>(&*b);
|
||||
BOOST_UNORDERED_DESTRUCT(&raw_ptr->value(), value_type);
|
||||
real_node_ptr n(node_alloc().address(*raw_ptr));
|
||||
node_alloc().destroy(n);
|
||||
node_alloc().deallocate(n, 1);
|
||||
}
|
||||
|
||||
// Delete and clear buckets
|
||||
|
||||
template <class A, class G>
|
||||
inline void hash_buckets<A, G>::delete_group(node_ptr first_node)
|
||||
{
|
||||
delete_nodes(first_node, node::next_group(first_node));
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline void hash_buckets<A, G>::delete_nodes(node_ptr begin, node_ptr end)
|
||||
{
|
||||
while(begin != end) {
|
||||
node_ptr node = begin;
|
||||
begin = next_node(begin);
|
||||
destruct_node(node);
|
||||
}
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline void hash_buckets<A, G>::delete_to_bucket_end(node_ptr begin)
|
||||
{
|
||||
while(BOOST_UNORDERED_BORLAND_BOOL(begin)) {
|
||||
node_ptr node = begin;
|
||||
begin = next_node(begin);
|
||||
destruct_node(node);
|
||||
}
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline void hash_buckets<A, G>::clear_bucket(bucket_ptr b)
|
||||
{
|
||||
node_ptr node_it = b->next_;
|
||||
b->next_ = node_ptr();
|
||||
|
||||
while(node_it) {
|
||||
node_ptr node_to_destruct = node_it;
|
||||
node_it = next_node(node_it);
|
||||
destruct_node(node_to_destruct);
|
||||
}
|
||||
}
|
||||
|
||||
template <class A, class G>
|
||||
inline void hash_buckets<A, G>::delete_buckets()
|
||||
{
|
||||
for(bucket_ptr begin = this->buckets_begin(), end = this->buckets_end(); begin != end; ++begin) {
|
||||
clear_bucket(begin);
|
||||
}
|
||||
|
||||
// Destroy the buckets (including the sentinel bucket).
|
||||
bucket_ptr end = this->buckets_end();
|
||||
++end;
|
||||
for(bucket_ptr begin = this->buckets_begin(); begin != end; ++begin) {
|
||||
bucket_alloc().destroy(begin);
|
||||
}
|
||||
|
||||
bucket_alloc().deallocate(this->buckets_begin(), this->bucket_count() + 1);
|
||||
|
||||
this->buckets_ = bucket_ptr();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// hash_iterator_base implementation
|
||||
|
||||
template <class BucketPtr>
|
||||
inline void hash_iterator_base<BucketPtr>::increment(node_ptr node) {
|
||||
while(!node) {
|
||||
++bucket_;
|
||||
node = bucket_->next_;
|
||||
}
|
||||
|
||||
node_ = node;
|
||||
}
|
||||
|
||||
template <class BucketPtr>
|
||||
inline void hash_iterator_base<BucketPtr>::increment()
|
||||
{
|
||||
increment(next_node(node_));
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
271
include/boost/unordered/detail/equivalent.hpp
Normal file
271
include/boost/unordered/detail/equivalent.hpp
Normal file
@ -0,0 +1,271 @@
|
||||
|
||||
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
||||
// Copyright (C) 2005-2009 Daniel James
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
|
||||
|
||||
#include <boost/unordered/detail/table.hpp>
|
||||
#include <boost/unordered/detail/extract_key.hpp>
|
||||
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Equality
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
bool hash_equivalent_table<H, P, A, K>
|
||||
::equals(hash_equivalent_table<H, P, A, K> const& other) const
|
||||
{
|
||||
if(this->size_ != other.size_) return false;
|
||||
if(!this->size_) return true;
|
||||
|
||||
bucket_ptr end = this->get_bucket(this->bucket_count_);
|
||||
for(bucket_ptr i = this->cached_begin_bucket_; i != end; ++i)
|
||||
{
|
||||
node_ptr it1 = i->next_;
|
||||
while(BOOST_UNORDERED_BORLAND_BOOL(it1))
|
||||
{
|
||||
node_ptr it2 = other.find_iterator(get_key_from_ptr(it1));
|
||||
if(!BOOST_UNORDERED_BORLAND_BOOL(it2)) return false;
|
||||
|
||||
node_ptr end1 = node::next_group(it1);
|
||||
node_ptr end2 = node::next_group(it2);
|
||||
|
||||
do {
|
||||
if(!extractor::compare_mapped(
|
||||
node::get_value(it1), node::get_value(it2)))
|
||||
return false;
|
||||
it1 = it1->next_;
|
||||
it2 = it2->next_;
|
||||
} while(it1 != end1 && it2 != end2);
|
||||
if(it1 != end1 || it2 != end2) return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// A convenience method for adding nodes.
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::node_ptr
|
||||
hash_equivalent_table<H, P, A, K>
|
||||
::add_node(node_constructor& a, bucket_ptr bucket, node_ptr pos)
|
||||
{
|
||||
node_ptr n = a.release();
|
||||
if(BOOST_UNORDERED_BORLAND_BOOL(pos)) {
|
||||
node::add_after_node(n, pos);
|
||||
}
|
||||
else {
|
||||
node::add_to_bucket(n, *bucket);
|
||||
if(bucket < this->cached_begin_bucket_)
|
||||
this->cached_begin_bucket_ = bucket;
|
||||
}
|
||||
++this->size_;
|
||||
return n;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Insert methods
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
inline BOOST_DEDUCED_TYPENAME
|
||||
hash_equivalent_table<H, P, A, K>::iterator_base
|
||||
hash_equivalent_table<H, P, A, K>::emplace_impl(node_constructor& a)
|
||||
{
|
||||
key_type const& k = get_key(a.value());
|
||||
std::size_t hash_value = this->hash_function()(k);
|
||||
|
||||
if(!this->size_) {
|
||||
return this->emplace_empty_impl_with_node(a, 1);
|
||||
}
|
||||
else {
|
||||
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
node_ptr position = find_iterator(bucket, k);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
if(this->reserve_for_insert(this->size_ + 1))
|
||||
bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
|
||||
return iterator_base(bucket, add_node(a, bucket, position));
|
||||
}
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
inline BOOST_DEDUCED_TYPENAME
|
||||
hash_equivalent_table<H, P, A, K>::iterator_base
|
||||
hash_equivalent_table<H, P, A, K>
|
||||
::emplace_hint_impl(iterator_base const& it, node_constructor& a)
|
||||
{
|
||||
// equal can throw, but with no effects
|
||||
if (!it.node_ || !equal(get_key(a.value()), *it)) {
|
||||
// Use the standard emplace if the iterator doesn't point
|
||||
// to a matching key.
|
||||
return emplace_impl(a);
|
||||
}
|
||||
else {
|
||||
// Find the first node in the group - so that the node
|
||||
// will be added at the end of the group.
|
||||
|
||||
node_ptr start = node::first_in_group(it.node_);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
bucket_ptr bucket = this->reserve_for_insert(this->size_ + 1) ?
|
||||
get_bucket(this->bucket_index(get_key(a.value()))) :
|
||||
it.bucket_;
|
||||
|
||||
// Nothing after this point can throw
|
||||
|
||||
return iterator_base(bucket, add_node(a, bucket, start));
|
||||
}
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
inline void hash_equivalent_table<H, P, A, K>
|
||||
::emplace_impl_no_rehash(node_constructor& a)
|
||||
{
|
||||
key_type const& k = get_key(a.value());
|
||||
bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
|
||||
add_node(a, bucket, find_iterator(bucket, k));
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
// Emplace (equivalent key containers)
|
||||
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
|
||||
|
||||
// if hash function throws, basic exception safety
|
||||
// strong otherwise
|
||||
template <class H, class P, class A, class K>
|
||||
template <class... Args>
|
||||
BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::iterator_base
|
||||
hash_equivalent_table<H, P, A, K>
|
||||
::emplace(Args&&... args)
|
||||
{
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
node_constructor a(*this);
|
||||
a.construct(std::forward<Args>(args)...);
|
||||
|
||||
return emplace_impl(a);
|
||||
}
|
||||
|
||||
// Emplace (equivalent key containers)
|
||||
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
|
||||
|
||||
// if hash function throws, basic exception safety
|
||||
// strong otherwise
|
||||
template <class H, class P, class A, class K>
|
||||
template <class... Args>
|
||||
BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::iterator_base
|
||||
hash_equivalent_table<H, P, A, K>
|
||||
::emplace_hint(iterator_base const& it, Args&&... args)
|
||||
{
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
node_constructor a(*this);
|
||||
a.construct(std::forward<Args>(args)...);
|
||||
|
||||
return emplace_hint_impl(it, a);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
|
||||
template <class H, class P, class A, class K> \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::iterator_base \
|
||||
hash_equivalent_table<H, P, A, K> \
|
||||
::emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
|
||||
{ \
|
||||
node_constructor a(*this); \
|
||||
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
|
||||
return emplace_impl(a); \
|
||||
} \
|
||||
\
|
||||
template <class H, class P, class A, class K> \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::iterator_base \
|
||||
hash_equivalent_table<H, P, A, K> \
|
||||
::emplace_hint(iterator_base const& it, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
|
||||
{ \
|
||||
node_constructor a(*this); \
|
||||
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
|
||||
return emplace_hint_impl(it, a); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_INSERT_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_INSERT_IMPL
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Insert range methods
|
||||
|
||||
// if hash function throws, or inserting > 1 element, basic exception safety
|
||||
// strong otherwise
|
||||
template <class H, class P, class A, class K>
|
||||
template <class I>
|
||||
inline void hash_equivalent_table<H, P, A, K>
|
||||
::insert_for_range(I i, I j, forward_traversal_tag)
|
||||
{
|
||||
if(i == j) return;
|
||||
std::size_t distance = unordered_detail::distance(i, j);
|
||||
if(distance == 1) {
|
||||
emplace(*i);
|
||||
}
|
||||
else {
|
||||
node_constructor a(*this);
|
||||
|
||||
// Only require basic exception safety here
|
||||
if(this->size_) {
|
||||
this->reserve_for_insert(this->size_ + distance);
|
||||
}
|
||||
else {
|
||||
a.construct(*i++);
|
||||
this->emplace_empty_impl_with_node(a, distance);
|
||||
}
|
||||
|
||||
for (; i != j; ++i) {
|
||||
a.construct(*i);
|
||||
emplace_impl_no_rehash(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if hash function throws, or inserting > 1 element, basic exception safety
|
||||
// strong otherwise
|
||||
template <class H, class P, class A, class K>
|
||||
template <class I>
|
||||
inline void hash_equivalent_table<H, P, A, K>
|
||||
::insert_for_range(I i, I j, boost::incrementable_traversal_tag)
|
||||
{
|
||||
node_constructor a(*this);
|
||||
for (; i != j; ++i) {
|
||||
a.construct(*i);
|
||||
emplace_impl(a);
|
||||
}
|
||||
}
|
||||
|
||||
// if hash function throws, or inserting > 1 element, basic exception safety
|
||||
// strong otherwise
|
||||
// TODO: Should I special case an empty container?
|
||||
template <class H, class P, class A, class K>
|
||||
template <class I>
|
||||
void hash_equivalent_table<H, P, A, K>::insert_range(I i, I j)
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME boost::iterator_traversal<I>::type
|
||||
iterator_traversal_tag;
|
||||
insert_for_range(i, j, iterator_traversal_tag);
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
@ -66,6 +66,11 @@ namespace unordered_detail {
|
||||
return no_key();
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool compare_mapped(value_type const&, value_type const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@ -75,7 +80,9 @@ namespace unordered_detail {
|
||||
struct apply
|
||||
{
|
||||
typedef ValueType value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME remove_const<BOOST_DEDUCED_TYPENAME ValueType::first_type>::type key_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
remove_const<BOOST_DEDUCED_TYPENAME ValueType::first_type>::type
|
||||
key_type;
|
||||
|
||||
static key_type const& extract(value_type const& v)
|
||||
{
|
||||
@ -94,19 +101,22 @@ namespace unordered_detail {
|
||||
}
|
||||
|
||||
template <class Second>
|
||||
static key_type const& extract(std::pair<key_type const, Second> const& v)
|
||||
static key_type const& extract(
|
||||
std::pair<key_type const, Second> const& v)
|
||||
{
|
||||
return v.first;
|
||||
}
|
||||
/*
|
||||
template <class Second>
|
||||
static key_type const& extract(std::pair<key_type&, Second> const& v)
|
||||
static key_type const& extract(
|
||||
std::pair<key_type&, Second> const& v)
|
||||
{
|
||||
return v.first;
|
||||
}
|
||||
|
||||
template <class Second>
|
||||
static key_type const& extract(std::pair<key_type const&, Second> const& v)
|
||||
static key_type const& extract(
|
||||
std::pair<key_type const&, Second> const& v)
|
||||
{
|
||||
return v.first;
|
||||
}
|
||||
@ -114,7 +124,8 @@ namespace unordered_detail {
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
template <class Arg1, class... Args>
|
||||
static key_type const& extract(key_type const& k, Arg1 const&, Args const&...)
|
||||
static key_type const& extract(key_type const& k,
|
||||
Arg1 const&, Args const&...)
|
||||
{
|
||||
return k;
|
||||
}
|
||||
@ -149,6 +160,10 @@ namespace unordered_detail {
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool compare_mapped(value_type const& x, value_type const& y)
|
||||
{
|
||||
return x.second == y.second;
|
||||
}
|
||||
};
|
||||
};
|
||||
}}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <boost/type_traits/aligned_storage.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/unordered/detail/allocator_helpers.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
// This header defines most of the classes used to implement the unordered
|
||||
// containers. It doesn't include the insert methods as they require a lot
|
||||
@ -31,8 +32,6 @@
|
||||
// G = Grouped/Ungrouped
|
||||
// K = Key Extractor
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
|
||||
# if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
|
||||
// STLport doesn't have std::forward.
|
||||
@ -45,12 +44,51 @@
|
||||
#define BOOST_UNORDERED_EMPLACE_LIMIT 10
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
|
||||
#define BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, class Arg)
|
||||
#define BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, const& arg)
|
||||
#define BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, arg)
|
||||
|
||||
#endif
|
||||
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
static const float minimum_max_load_factor = 1e-3f;
|
||||
static const std::size_t default_initial_bucket_count = 11;
|
||||
static const std::size_t default_bucket_count = 11;
|
||||
struct move_tag {};
|
||||
|
||||
template <class Alloc, class Grouped>
|
||||
class hash_node_constructor;
|
||||
struct set_extractor;
|
||||
struct map_extractor;
|
||||
struct no_key;
|
||||
|
||||
// Explicitly call a destructor
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#if BOOST_MSVC >= 1400
|
||||
#pragma warning(disable:4100) // unreferenced formal parameter
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline void destroy(T* x) {
|
||||
x->~T();
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
// hash_bucket
|
||||
|
||||
template <class A>
|
||||
@ -70,8 +108,11 @@ namespace boost { namespace unordered_detail {
|
||||
hash_bucket() : next_() {}
|
||||
|
||||
// Only copy construct when allocating.
|
||||
hash_bucket(hash_bucket const& x) : next_()
|
||||
{ BOOST_ASSERT(!x.next_); }
|
||||
hash_bucket(hash_bucket const& x)
|
||||
: next_()
|
||||
{
|
||||
BOOST_ASSERT(!x.next_);
|
||||
}
|
||||
};
|
||||
|
||||
template <class A>
|
||||
@ -84,12 +125,10 @@ namespace boost { namespace unordered_detail {
|
||||
static inline node_ptr& next_group(node_ptr ptr);
|
||||
static inline std::size_t group_count(node_ptr ptr);
|
||||
static inline void add_to_bucket(node_ptr n, bucket& b);
|
||||
static inline void add_group_to_bucket(node_ptr n, bucket& b);
|
||||
static inline void add_after_node(node_ptr n, node_ptr position);
|
||||
static void unlink_node(bucket& b, node_ptr node);
|
||||
static void unlink_nodes(bucket& b, node_ptr begin, node_ptr end);
|
||||
static void unlink_nodes(bucket& b, node_ptr end);
|
||||
static inline void unlink_group(node_ptr* b);
|
||||
};
|
||||
|
||||
template <class A>
|
||||
@ -102,21 +141,20 @@ namespace boost { namespace unordered_detail {
|
||||
node_ptr group_prev_;
|
||||
|
||||
grouped_node_base() : bucket(), group_prev_() {}
|
||||
static inline node_ptr& group_prev(node_ptr ptr);
|
||||
static inline node_ptr& next_group(node_ptr ptr);
|
||||
static inline node_ptr first_in_group(node_ptr n);
|
||||
static inline std::size_t group_count(node_ptr ptr);
|
||||
static inline void add_to_bucket(node_ptr n, bucket& b);
|
||||
static inline void add_group_to_bucket(node_ptr n, bucket& b);
|
||||
static inline void add_after_node(node_ptr n, node_ptr position);
|
||||
static void unlink_node(bucket& b, node_ptr node);
|
||||
static void unlink_nodes(bucket& b, node_ptr begin, node_ptr end);
|
||||
static void unlink_nodes(bucket& b, node_ptr end);
|
||||
static inline void unlink_group(node_ptr* b);
|
||||
|
||||
private:
|
||||
static inline node_ptr split_group(node_ptr split);
|
||||
static inline grouped_node_base& get(node_ptr ptr)
|
||||
{ return static_cast<grouped_node_base&>(*ptr); }
|
||||
static inline grouped_node_base& get(node_ptr ptr) {
|
||||
return static_cast<grouped_node_base&>(*ptr);
|
||||
}
|
||||
};
|
||||
|
||||
struct ungrouped
|
||||
@ -143,44 +181,73 @@ namespace boost { namespace unordered_detail {
|
||||
sizeof(value_type),
|
||||
::boost::alignment_of<value_type>::value>::type data_;
|
||||
|
||||
void* address() { return this; }
|
||||
value_type& value() { return *(ValueType*) this; }
|
||||
void* address() {
|
||||
return this;
|
||||
}
|
||||
value_type& value() {
|
||||
return *(ValueType*) this;
|
||||
}
|
||||
};
|
||||
|
||||
// Node
|
||||
|
||||
template <class NodeBase, class ValueType>
|
||||
class hash_node : public NodeBase, public value_base<ValueType>
|
||||
|
||||
template <class A, class G>
|
||||
class hash_node :
|
||||
public G::BOOST_NESTED_TEMPLATE base<A>::type,
|
||||
public value_base<BOOST_DEDUCED_TYPENAME A::value_type>
|
||||
{
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME NodeBase::node_ptr node_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME hash_bucket<A>::node_ptr node_ptr;
|
||||
|
||||
static value_type& get_value(node_ptr p) { return static_cast<hash_node&>(*p).value(); }
|
||||
static value_type& get_value(node_ptr p) {
|
||||
return static_cast<hash_node&>(*p).value();
|
||||
}
|
||||
};
|
||||
|
||||
// Iterator Base
|
||||
|
||||
template <class BucketPtr>
|
||||
template <class A, class G>
|
||||
class hash_iterator_base
|
||||
{
|
||||
public:
|
||||
typedef BucketPtr bucket_ptr;
|
||||
typedef BucketPtr node_ptr;
|
||||
typedef A value_allocator;
|
||||
typedef hash_bucket<A> bucket;
|
||||
typedef hash_node<A, G> node;
|
||||
typedef BOOST_DEDUCED_TYPENAME node::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME node::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME node::node_ptr node_ptr;
|
||||
|
||||
bucket_ptr bucket_;
|
||||
node_ptr node_;
|
||||
|
||||
hash_iterator_base() : bucket_(), node_() {}
|
||||
explicit hash_iterator_base(bucket_ptr b) : bucket_(b), node_(b->next_) {}
|
||||
hash_iterator_base(bucket_ptr b, node_ptr n) : bucket_(b), node_(n) {}
|
||||
explicit hash_iterator_base(bucket_ptr b)
|
||||
: bucket_(b),
|
||||
node_(b ? b->next_ : node_ptr()) {}
|
||||
hash_iterator_base(bucket_ptr b, node_ptr n)
|
||||
: bucket_(b),
|
||||
node_(n) {}
|
||||
|
||||
bool operator==(hash_iterator_base const& x) const { return node_ == x.node_; }
|
||||
bool operator!=(hash_iterator_base const& x) const { return node_ != x.node_; }
|
||||
bool is_end() const { return node_ == bucket_; }
|
||||
node_ptr get() const { return node_; }
|
||||
void increment(node_ptr node);
|
||||
void increment();
|
||||
bool operator==(hash_iterator_base const& x) const {
|
||||
return node_ == x.node_; }
|
||||
bool operator!=(hash_iterator_base const& x) const {
|
||||
return node_ != x.node_; }
|
||||
value_type& operator*() const {
|
||||
return node::get_value(node_);
|
||||
}
|
||||
|
||||
void increment_bucket(node_ptr node) {
|
||||
while(!node) {
|
||||
++bucket_;
|
||||
node = bucket_->next_;
|
||||
}
|
||||
node_ = bucket_ == node ? node_ptr() : node;
|
||||
}
|
||||
|
||||
void increment() {
|
||||
increment_bucket(node_->next_);
|
||||
}
|
||||
};
|
||||
|
||||
// hash_buckets
|
||||
@ -188,9 +255,10 @@ namespace boost { namespace unordered_detail {
|
||||
// This is responsible for allocating and deallocating buckets and nodes.
|
||||
//
|
||||
// Notes:
|
||||
// 1. For the sake exception safety the allocators themselves don't allocate anything.
|
||||
// 2. It's the callers responsibility to allocate the buckets before calling any of the
|
||||
// methods (other than getters and setters).
|
||||
// 1. For the sake exception safety the allocators themselves don't allocate
|
||||
// anything.
|
||||
// 2. It's the callers responsibility to allocate the buckets before calling
|
||||
// any of the methods (other than getters and setters).
|
||||
|
||||
template <class A, class G>
|
||||
class hash_buckets
|
||||
@ -201,22 +269,19 @@ namespace boost { namespace unordered_detail {
|
||||
// Types
|
||||
|
||||
typedef A value_allocator;
|
||||
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
|
||||
|
||||
typedef hash_bucket<A> bucket;
|
||||
typedef BOOST_DEDUCED_TYPENAME G::BOOST_NESTED_TEMPLATE base<A>::type
|
||||
node_base;
|
||||
typedef hash_node<node_base, value_type> node;
|
||||
typedef hash_iterator_base<A, G> iterator_base;
|
||||
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME iterator_base::node node;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME node::bucket_allocator bucket_allocator;
|
||||
typedef BOOST_DEDUCED_TYPENAME node::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME node::node_ptr node_ptr;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME rebind_wrap<value_allocator, node>::type node_allocator;
|
||||
typedef BOOST_DEDUCED_TYPENAME rebind_wrap<value_allocator, node>::type
|
||||
node_allocator;
|
||||
typedef BOOST_DEDUCED_TYPENAME node_allocator::pointer real_node_ptr;
|
||||
|
||||
typedef hash_iterator_base<bucket_ptr> iterator_base;
|
||||
|
||||
// Members
|
||||
|
||||
bucket_ptr buckets_;
|
||||
@ -225,124 +290,194 @@ namespace boost { namespace unordered_detail {
|
||||
|
||||
// Data access
|
||||
|
||||
bucket_allocator const& bucket_alloc() const { return allocators_.first(); }
|
||||
node_allocator const& node_alloc() const { return allocators_.second(); }
|
||||
bucket_allocator& bucket_alloc() { return allocators_.first(); }
|
||||
node_allocator& node_alloc() { return allocators_.second(); }
|
||||
bucket_allocator const& bucket_alloc() const {
|
||||
return allocators_.first(); }
|
||||
node_allocator const& node_alloc() const {
|
||||
return allocators_.second(); }
|
||||
bucket_allocator& bucket_alloc() {
|
||||
return allocators_.first(); }
|
||||
node_allocator& node_alloc() {
|
||||
return allocators_.second(); }
|
||||
std::size_t max_bucket_count() const {
|
||||
// -1 to account for the sentinel.
|
||||
return prev_prime(this->bucket_alloc().max_size() - 1);
|
||||
}
|
||||
|
||||
// Constructors
|
||||
//
|
||||
// The copy constructor doesn't copy the buckets.
|
||||
|
||||
hash_buckets(node_allocator const& a, std::size_t n);
|
||||
hash_buckets(hash_buckets& x, move_tag m);
|
||||
hash_buckets(hash_buckets& x, value_allocator const& a, move_tag m);
|
||||
void create_buckets();
|
||||
~hash_buckets();
|
||||
|
||||
// no throw
|
||||
void swap(hash_buckets& other);
|
||||
void move(hash_buckets& other);
|
||||
|
||||
// Buckets
|
||||
// For the remaining functions, buckets_ must not be null.
|
||||
|
||||
std::size_t bucket_count() const;
|
||||
std::size_t bucket_from_hash(std::size_t hashed) const;
|
||||
bucket_ptr bucket_ptr_from_hash(std::size_t hashed) const;
|
||||
bucket_ptr buckets_begin() const;
|
||||
bucket_ptr buckets_end() const;
|
||||
std::size_t bucket_size(std::size_t index) const;
|
||||
bucket_ptr get_bucket(std::size_t n) const;
|
||||
bucket_ptr bucket_ptr_from_hash(std::size_t hashed) const;
|
||||
std::size_t bucket_size(std::size_t index) const;
|
||||
node_ptr bucket_begin(std::size_t n) const;
|
||||
node_ptr bucket_end(std::size_t) const;
|
||||
|
||||
// Alloc/Dealloc
|
||||
|
||||
void destruct_node(node_ptr);
|
||||
void delete_node(node_ptr);
|
||||
|
||||
//
|
||||
void delete_buckets();
|
||||
void clear_bucket(bucket_ptr);
|
||||
void delete_group(node_ptr first_node);
|
||||
void delete_nodes(node_ptr begin, node_ptr end);
|
||||
void delete_to_bucket_end(node_ptr begin);
|
||||
std::size_t delete_nodes(node_ptr begin, node_ptr end);
|
||||
std::size_t delete_to_bucket_end(node_ptr begin);
|
||||
};
|
||||
|
||||
template <class H, class P> class set_hash_functions;
|
||||
|
||||
template <class H, class P>
|
||||
class hash_buffered_functions
|
||||
{
|
||||
friend class set_hash_functions<H, P>;
|
||||
hash_buffered_functions& operator=(hash_buffered_functions const&);
|
||||
|
||||
typedef boost::compressed_pair<H, P> function_pair;
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::aligned_storage<
|
||||
sizeof(function_pair),
|
||||
::boost::alignment_of<function_pair>::value>::type aligned_function;
|
||||
|
||||
bool current_; // The currently active functions.
|
||||
aligned_function funcs_[2];
|
||||
|
||||
function_pair const& current() const {
|
||||
return *static_cast<function_pair const*>(
|
||||
static_cast<void const*>(&funcs_[current_]));
|
||||
}
|
||||
|
||||
void construct(bool which, H const& hf, P const& eq)
|
||||
{
|
||||
new((void*) &funcs_[which]) function_pair(hf, eq);
|
||||
}
|
||||
|
||||
void construct(bool which, function_pair const& f)
|
||||
{
|
||||
new((void*) &funcs_[which]) function_pair(f);
|
||||
}
|
||||
|
||||
void destroy(bool which)
|
||||
{
|
||||
boost::unordered_detail::destroy((function_pair*)(&funcs_[which]));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
hash_buffered_functions(H const& hf, P const& eq)
|
||||
: current_(false)
|
||||
{
|
||||
construct(current_, hf, eq);
|
||||
}
|
||||
|
||||
hash_buffered_functions(hash_buffered_functions const& bf)
|
||||
: current_(false)
|
||||
{
|
||||
construct(current_, bf.current());
|
||||
}
|
||||
|
||||
~hash_buffered_functions() {
|
||||
destroy(current_);
|
||||
}
|
||||
|
||||
H const& hash_function() const {
|
||||
return current().first();
|
||||
}
|
||||
|
||||
P const& key_eq() const {
|
||||
return current().second();
|
||||
}
|
||||
};
|
||||
|
||||
template <class H, class P>
|
||||
class set_hash_functions
|
||||
{
|
||||
set_hash_functions(set_hash_functions const&);
|
||||
set_hash_functions& operator=(set_hash_functions const&);
|
||||
|
||||
typedef hash_buffered_functions<H, P> buffered_functions;
|
||||
buffered_functions& buffered_functions_;
|
||||
bool tmp_functions_;
|
||||
|
||||
public:
|
||||
|
||||
set_hash_functions(buffered_functions& f, H const& h, P const& p)
|
||||
: buffered_functions_(f),
|
||||
tmp_functions_(!f.current_)
|
||||
{
|
||||
f.construct(tmp_functions_, h, p);
|
||||
}
|
||||
|
||||
set_hash_functions(buffered_functions& f,
|
||||
buffered_functions const& other)
|
||||
: buffered_functions_(f),
|
||||
tmp_functions_(!f.current_)
|
||||
{
|
||||
f.construct(tmp_functions_, other.current());
|
||||
}
|
||||
|
||||
~set_hash_functions()
|
||||
{
|
||||
buffered_functions_.destroy(tmp_functions_);
|
||||
}
|
||||
|
||||
void commit()
|
||||
{
|
||||
buffered_functions_.current_ = tmp_functions_;
|
||||
tmp_functions_ = !tmp_functions_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class H, class P, class A, class G, class K>
|
||||
class hash_table :
|
||||
public hash_buckets<A, G>
|
||||
|
||||
public hash_buckets<A, G>,
|
||||
public hash_buffered_functions<H, P>
|
||||
{
|
||||
hash_table(hash_table const&);
|
||||
public:
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef A value_allocator;
|
||||
typedef G grouped;
|
||||
typedef K key_extractor;
|
||||
typedef hash_buffered_functions<H, P> base;
|
||||
typedef hash_buckets<A, G> buckets;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME key_extractor::BOOST_NESTED_TEMPLATE apply<value_type>
|
||||
extractor;
|
||||
typedef BOOST_DEDUCED_TYPENAME key_extractor::BOOST_NESTED_TEMPLATE
|
||||
apply<value_type> extractor;
|
||||
typedef BOOST_DEDUCED_TYPENAME extractor::key_type key_type;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::bucket bucket;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::bucket_ptr bucket_ptr;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::iterator_base iterator_base;
|
||||
|
||||
// Types for storing functions
|
||||
|
||||
typedef boost::compressed_pair<hasher, key_equal> functions;
|
||||
typedef bool functions_ptr;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::aligned_storage<
|
||||
sizeof(functions),
|
||||
::boost::alignment_of<functions>::value>::type aligned_function;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node_allocator node_allocator;
|
||||
typedef hash_node_constructor<A, G> node_constructor;
|
||||
typedef std::pair<iterator_base, iterator_base> iterator_pair;
|
||||
|
||||
// Members
|
||||
|
||||
bool func_; // The currently active functions.
|
||||
aligned_function funcs_[2];
|
||||
bucket_ptr cached_begin_bucket_;
|
||||
std::size_t size_;
|
||||
float mlf_;
|
||||
// Cached data - invalid if !this->buckets_
|
||||
bucket_ptr cached_begin_bucket_;
|
||||
std::size_t max_load_;
|
||||
|
||||
// Buffered Functions
|
||||
|
||||
functions* get_functions(bool which) {
|
||||
return static_cast<functions*>(static_cast<void*>(&this->funcs_[which]));
|
||||
}
|
||||
functions const* get_functions(bool which) const {
|
||||
return static_cast<functions const*>(static_cast<void const*>(&this->funcs_[which]));
|
||||
}
|
||||
functions const& current() const {
|
||||
return *this->get_functions(this->func_);
|
||||
}
|
||||
hasher const& hash_function() const {
|
||||
return this->current().first();
|
||||
}
|
||||
key_equal const& key_eq() const {
|
||||
return this->current().second();
|
||||
}
|
||||
functions_ptr buffer_functions(hash_table const& x) {
|
||||
functions_ptr ptr = !func_;
|
||||
*this->get_functions(ptr) = x.current();
|
||||
return ptr;
|
||||
}
|
||||
void set_functions(functions_ptr ptr) {
|
||||
BOOST_ASSERT(ptr != func_);
|
||||
func_ = ptr;
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
|
||||
key_type const& get_key(value_type const& v) const {
|
||||
return extractor::extract(v);
|
||||
}
|
||||
key_type const& get_key_from_ptr(node_ptr n) const {
|
||||
return extractor::extract(node::get_value(n));
|
||||
}
|
||||
bool equal(key_type const& k, value_type const& v) const;
|
||||
node_ptr find_iterator(bucket_ptr bucket, key_type const& k) const;
|
||||
node_ptr find_iterator(key_type const& k) const;
|
||||
@ -354,31 +489,40 @@ namespace boost { namespace unordered_detail {
|
||||
std::size_t bucket_index(key_type const& k) const;
|
||||
void max_load_factor(float z);
|
||||
std::size_t min_buckets_for_size(std::size_t n) const;
|
||||
void calculate_max_load();
|
||||
std::size_t calculate_max_load();
|
||||
|
||||
// Constructors
|
||||
|
||||
hash_table(std::size_t n, hasher const& hf, key_equal const& eq, value_allocator const& a);
|
||||
hash_table(hash_table const& x);
|
||||
hash_table(hash_table const& x, value_allocator const& a);
|
||||
hash_table(std::size_t n, hasher const& hf, key_equal const& eq,
|
||||
node_allocator const& a);
|
||||
hash_table(hash_table const& x, node_allocator const& a);
|
||||
hash_table(hash_table& x, move_tag m);
|
||||
hash_table(hash_table& x, value_allocator const& a, move_tag m);
|
||||
~hash_table();
|
||||
hash_table(hash_table& x, node_allocator const& a, move_tag m);
|
||||
~hash_table() {}
|
||||
hash_table& operator=(hash_table const&);
|
||||
|
||||
// Iterators
|
||||
|
||||
iterator_base begin() const { return iterator_base(this->cached_begin_bucket_); }
|
||||
iterator_base end() const { return iterator_base(this->buckets_end()); }
|
||||
iterator_base begin() const {
|
||||
return this->size_ ?
|
||||
iterator_base(this->cached_begin_bucket_) :
|
||||
iterator_base();
|
||||
}
|
||||
iterator_base end() const {
|
||||
return iterator_base();
|
||||
}
|
||||
|
||||
// Swap & Move
|
||||
|
||||
void swap(hash_table& x);
|
||||
void fast_swap(hash_table& other);
|
||||
void slow_swap(hash_table& other);
|
||||
void partial_swap(hash_table& other);
|
||||
void move(hash_table& x);
|
||||
|
||||
// Reserve and rehash
|
||||
|
||||
bool reserve(std::size_t n);
|
||||
void create_for_insert(std::size_t n);
|
||||
bool reserve_for_insert(std::size_t n);
|
||||
void rehash(std::size_t n);
|
||||
void rehash_impl(std::size_t n);
|
||||
@ -393,7 +537,7 @@ namespace boost { namespace unordered_detail {
|
||||
std::size_t count(key_type const& k) const;
|
||||
iterator_base find(key_type const& k) const;
|
||||
value_type& at(key_type const& k) const;
|
||||
std::pair<iterator_base, iterator_base> equal_range(key_type const& k) const;
|
||||
iterator_pair equal_range(key_type const& k) const;
|
||||
|
||||
// Erase
|
||||
//
|
||||
@ -407,7 +551,7 @@ namespace boost { namespace unordered_detail {
|
||||
|
||||
// recompute_begin_bucket
|
||||
|
||||
void recompute_begin_bucket();
|
||||
void init_buckets();
|
||||
|
||||
// After an erase cached_begin_bucket_ might be left pointing to
|
||||
// an empty bucket, so this is called to update it
|
||||
@ -424,6 +568,203 @@ namespace boost { namespace unordered_detail {
|
||||
|
||||
// no throw
|
||||
float load_factor() const;
|
||||
|
||||
iterator_base emplace_empty_impl_with_node(
|
||||
node_constructor&, std::size_t);
|
||||
};
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
class hash_unique_table :
|
||||
public hash_table<H, P, A, boost::unordered_detail::ungrouped, K>
|
||||
|
||||
{
|
||||
public:
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef A value_allocator;
|
||||
typedef K key_extractor;
|
||||
|
||||
typedef hash_table<H, P, A, ungrouped, K> table;
|
||||
typedef hash_node_constructor<A, ungrouped> node_constructor;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME table::key_type key_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::node node;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::node_ptr node_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::extractor extractor;
|
||||
|
||||
typedef std::pair<iterator_base, bool> emplace_return;
|
||||
|
||||
// Constructors
|
||||
|
||||
hash_unique_table(std::size_t n, hasher const& hf, key_equal const& eq,
|
||||
value_allocator const& a)
|
||||
: table(n, hf, eq, a) {}
|
||||
hash_unique_table(hash_unique_table const& x)
|
||||
: table(x, x.node_alloc()) {}
|
||||
hash_unique_table(hash_unique_table const& x, value_allocator const& a)
|
||||
: table(x, a) {}
|
||||
hash_unique_table(hash_unique_table& x, move_tag m)
|
||||
: table(x, m) {}
|
||||
hash_unique_table(hash_unique_table& x, value_allocator const& a,
|
||||
move_tag m)
|
||||
: table(x, a, m) {}
|
||||
~hash_unique_table() {}
|
||||
|
||||
// Insert methods
|
||||
|
||||
emplace_return emplace_impl_with_node(node_constructor& a);
|
||||
value_type& operator[](key_type const& k);
|
||||
|
||||
// equals
|
||||
|
||||
bool equals(hash_unique_table const&) const;
|
||||
|
||||
node_ptr add_node(node_constructor& a, bucket_ptr bucket);
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
template<class... Args>
|
||||
emplace_return emplace(Args&&... args);
|
||||
template<class... Args>
|
||||
iterator_base emplace_hint(iterator_base const&, Args&&... args);
|
||||
template<class... Args>
|
||||
emplace_return emplace_impl(key_type const& k, Args&&... args);
|
||||
template<class... Args>
|
||||
emplace_return emplace_impl(no_key, Args&&... args);
|
||||
template<class... Args>
|
||||
emplace_return emplace_empty_impl(Args&&... args);
|
||||
#else
|
||||
template <class Arg0>
|
||||
emplace_return emplace(Arg0 const& arg0);
|
||||
template <class Arg0>
|
||||
iterator_base emplace_hint(iterator_base const&, Arg0 const& arg0);
|
||||
|
||||
#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
emplace_return emplace( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
iterator_base emplace_hint(iterator_base const& it, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \
|
||||
BOOST_UNORDERED_INSERT_IMPL2(z, n, _)
|
||||
|
||||
#define BOOST_UNORDERED_INSERT_IMPL2(z, n, _) \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
emplace_return emplace_impl(key_type const& k, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
emplace_return emplace_impl(no_key, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
emplace_return emplace_empty_impl( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n));
|
||||
|
||||
BOOST_UNORDERED_INSERT_IMPL2(1, 1, _)
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_INSERT_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_INSERT_IMPL
|
||||
#undef BOOST_UNORDERED_INSERT_IMPL2
|
||||
|
||||
#endif
|
||||
|
||||
// if hash function throws, or inserting > 1 element, basic exception
|
||||
// safety strong otherwise
|
||||
template <class InputIt>
|
||||
void insert_range(InputIt i, InputIt j);
|
||||
template <class InputIt>
|
||||
void insert_range_impl(key_type const&, InputIt i, InputIt j);
|
||||
template <class InputIt>
|
||||
void insert_range_impl(no_key, InputIt i, InputIt j);
|
||||
};
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
class hash_equivalent_table :
|
||||
public hash_table<H, P, A, boost::unordered_detail::grouped, K>
|
||||
|
||||
{
|
||||
public:
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef A value_allocator;
|
||||
typedef K key_extractor;
|
||||
|
||||
typedef hash_table<H, P, A, boost::unordered_detail::grouped, K> table;
|
||||
typedef hash_node_constructor<A, boost::unordered_detail::grouped>
|
||||
node_constructor;
|
||||
typedef hash_iterator_base<A, grouped> iterator_base;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME table::key_type key_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::node node;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::node_ptr node_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::extractor extractor;
|
||||
|
||||
// Constructors
|
||||
|
||||
hash_equivalent_table(std::size_t n,
|
||||
hasher const& hf, key_equal const& eq, value_allocator const& a)
|
||||
: table(n, hf, eq, a) {}
|
||||
hash_equivalent_table(hash_equivalent_table const& x)
|
||||
: table(x, x.node_alloc()) {}
|
||||
hash_equivalent_table(hash_equivalent_table const& x,
|
||||
value_allocator const& a)
|
||||
: table(x, a) {}
|
||||
hash_equivalent_table(hash_equivalent_table& x, move_tag m)
|
||||
: table(x, m) {}
|
||||
hash_equivalent_table(hash_equivalent_table& x,
|
||||
value_allocator const& a, move_tag m)
|
||||
: table(x, a, m) {}
|
||||
~hash_equivalent_table() {}
|
||||
|
||||
// Insert methods
|
||||
|
||||
iterator_base emplace_impl(node_constructor& a);
|
||||
iterator_base emplace_hint_impl(iterator_base const& it,
|
||||
node_constructor& a);
|
||||
void emplace_impl_no_rehash(node_constructor& a);
|
||||
|
||||
// equals
|
||||
|
||||
bool equals(hash_equivalent_table const&) const;
|
||||
|
||||
inline node_ptr add_node(node_constructor& a,
|
||||
bucket_ptr bucket, node_ptr pos);
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
template <class... Args>
|
||||
iterator_base emplace(Args&&... args);
|
||||
template <class... Args>
|
||||
iterator_base emplace_hint(iterator_base const& it, Args&&... args);
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
iterator_base emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \
|
||||
\
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
iterator_base emplace_hint(iterator_base const& it, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n));
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_INSERT_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_INSERT_IMPL
|
||||
#endif
|
||||
|
||||
template <class I>
|
||||
void insert_for_range(I i, I j, forward_traversal_tag);
|
||||
template <class I>
|
||||
void insert_for_range(I i, I j, boost::incrementable_traversal_tag);
|
||||
template <class I>
|
||||
void insert_range(I i, I j);
|
||||
};
|
||||
|
||||
// Iterator Access
|
||||
@ -432,7 +773,9 @@ namespace boost { namespace unordered_detail {
|
||||
{
|
||||
public:
|
||||
template <class Iterator>
|
||||
static BOOST_DEDUCED_TYPENAME Iterator::base const& get(Iterator const& it) {
|
||||
static BOOST_DEDUCED_TYPENAME Iterator::base const&
|
||||
get(Iterator const& it)
|
||||
{
|
||||
return it.base_;
|
||||
}
|
||||
};
|
||||
@ -462,25 +805,39 @@ namespace boost { namespace unordered_detail {
|
||||
|
||||
private:
|
||||
typedef hash_buckets<A, G> buckets;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
|
||||
typedef hash_const_local_iterator<A, G> const_local_iterator;
|
||||
|
||||
friend class hash_const_local_iterator<A, G>;
|
||||
ptr ptr_;
|
||||
node_ptr ptr_;
|
||||
|
||||
public:
|
||||
hash_local_iterator() : ptr_() {}
|
||||
explicit hash_local_iterator(ptr x) : ptr_(x) {}
|
||||
BOOST_DEDUCED_TYPENAME A::reference operator*() const
|
||||
{ return node::get_value(ptr_); }
|
||||
value_type* operator->() const { return &node::get_value(ptr_); }
|
||||
hash_local_iterator& operator++() { ptr_ = next_node(ptr_); return *this; }
|
||||
hash_local_iterator operator++(int) { hash_local_iterator tmp(ptr_); ptr_ = next_node(ptr_); return tmp; }
|
||||
bool operator==(hash_local_iterator x) const { return ptr_ == x.ptr_; }
|
||||
bool operator==(const_local_iterator x) const { return ptr_ == x.ptr_; }
|
||||
bool operator!=(hash_local_iterator x) const { return ptr_ != x.ptr_; }
|
||||
bool operator!=(const_local_iterator x) const { return ptr_ != x.ptr_; }
|
||||
explicit hash_local_iterator(node_ptr x) : ptr_(x) {}
|
||||
BOOST_DEDUCED_TYPENAME A::reference operator*() const {
|
||||
return node::get_value(ptr_);
|
||||
}
|
||||
value_type* operator->() const {
|
||||
return &node::get_value(ptr_);
|
||||
}
|
||||
hash_local_iterator& operator++() {
|
||||
ptr_ = ptr_->next_; return *this;
|
||||
}
|
||||
hash_local_iterator operator++(int) {
|
||||
hash_local_iterator tmp(ptr_); ptr_ = ptr_->next_; return tmp; }
|
||||
bool operator==(hash_local_iterator x) const {
|
||||
return ptr_ == x.ptr_;
|
||||
}
|
||||
bool operator==(const_local_iterator x) const {
|
||||
return ptr_ == x.ptr_;
|
||||
}
|
||||
bool operator!=(hash_local_iterator x) const {
|
||||
return ptr_ != x.ptr_;
|
||||
}
|
||||
bool operator!=(const_local_iterator x) const {
|
||||
return ptr_ != x.ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class A, class G>
|
||||
@ -508,14 +865,30 @@ namespace boost { namespace unordered_detail {
|
||||
explicit hash_const_local_iterator(ptr x) : ptr_(x) {}
|
||||
hash_const_local_iterator(local_iterator x) : ptr_(x.ptr_) {}
|
||||
BOOST_DEDUCED_TYPENAME A::const_reference
|
||||
operator*() const { return node::get_value(ptr_); }
|
||||
value_type const* operator->() const { return &node::get_value(ptr_); }
|
||||
hash_const_local_iterator& operator++() { ptr_ = next_node(ptr_); return *this; }
|
||||
hash_const_local_iterator operator++(int) { hash_const_local_iterator tmp(ptr_); ptr_ = next_node(ptr_); return tmp; }
|
||||
bool operator==(local_iterator x) const { return ptr_ == x.ptr_; }
|
||||
bool operator==(hash_const_local_iterator x) const { return ptr_ == x.ptr_; }
|
||||
bool operator!=(local_iterator x) const { return ptr_ != x.ptr_; }
|
||||
bool operator!=(hash_const_local_iterator x) const { return ptr_ != x.ptr_; }
|
||||
operator*() const {
|
||||
return node::get_value(ptr_);
|
||||
}
|
||||
value_type const* operator->() const {
|
||||
return &node::get_value(ptr_);
|
||||
}
|
||||
hash_const_local_iterator& operator++() {
|
||||
ptr_ = ptr_->next_; return *this;
|
||||
}
|
||||
hash_const_local_iterator operator++(int) {
|
||||
hash_const_local_iterator tmp(ptr_); ptr_ = ptr_->next_; return tmp;
|
||||
}
|
||||
bool operator==(local_iterator x) const {
|
||||
return ptr_ == x.ptr_;
|
||||
}
|
||||
bool operator==(hash_const_local_iterator x) const {
|
||||
return ptr_ == x.ptr_;
|
||||
}
|
||||
bool operator!=(local_iterator x) const {
|
||||
return ptr_ != x.ptr_;
|
||||
}
|
||||
bool operator!=(hash_const_local_iterator x) const {
|
||||
return ptr_ != x.ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
// iterators
|
||||
@ -547,15 +920,30 @@ namespace boost { namespace unordered_detail {
|
||||
|
||||
hash_iterator() : base_() {}
|
||||
explicit hash_iterator(base const& x) : base_(x) {}
|
||||
BOOST_DEDUCED_TYPENAME A::reference
|
||||
operator*() const { return node::get_value(base_.get()); }
|
||||
value_type* operator->() const { return &node::get_value(base_.get()); }
|
||||
hash_iterator& operator++() { base_.increment(); return *this; }
|
||||
hash_iterator operator++(int) { hash_iterator tmp(base_); base_.increment(); return tmp; }
|
||||
bool operator==(hash_iterator const& x) const { return base_ == x.base_; }
|
||||
bool operator==(const_iterator const& x) const { return base_ == x.base_; }
|
||||
bool operator!=(hash_iterator const& x) const { return base_ != x.base_; }
|
||||
bool operator!=(const_iterator const& x) const { return base_ != x.base_; }
|
||||
BOOST_DEDUCED_TYPENAME A::reference operator*() const {
|
||||
return *base_;
|
||||
}
|
||||
value_type* operator->() const {
|
||||
return &*base_;
|
||||
}
|
||||
hash_iterator& operator++() {
|
||||
base_.increment(); return *this;
|
||||
}
|
||||
hash_iterator operator++(int) {
|
||||
hash_iterator tmp(base_); base_.increment(); return tmp;
|
||||
}
|
||||
bool operator==(hash_iterator const& x) const {
|
||||
return base_ == x.base_;
|
||||
}
|
||||
bool operator==(const_iterator const& x) const {
|
||||
return base_ == x.base_;
|
||||
}
|
||||
bool operator!=(hash_iterator const& x) const {
|
||||
return base_ != x.base_;
|
||||
}
|
||||
bool operator!=(const_iterator const& x) const {
|
||||
return base_ != x.base_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class A, class G>
|
||||
@ -584,15 +972,30 @@ namespace boost { namespace unordered_detail {
|
||||
hash_const_iterator() : base_() {}
|
||||
explicit hash_const_iterator(base const& x) : base_(x) {}
|
||||
hash_const_iterator(iterator const& x) : base_(x.base_) {}
|
||||
BOOST_DEDUCED_TYPENAME A::const_reference
|
||||
operator*() const { return node::get_value(base_.get()); }
|
||||
value_type const* operator->() const { return &node::get_value(base_.get()); }
|
||||
hash_const_iterator& operator++() { base_.increment(); return *this; }
|
||||
hash_const_iterator operator++(int) { hash_const_iterator tmp(base_); base_.increment(); return tmp; }
|
||||
bool operator==(iterator const& x) const { return base_ == x.base_; }
|
||||
bool operator==(hash_const_iterator const& x) const { return base_ == x.base_; }
|
||||
bool operator!=(iterator const& x) const { return base_ != x.base_; }
|
||||
bool operator!=(hash_const_iterator const& x) const { return base_ != x.base_; }
|
||||
BOOST_DEDUCED_TYPENAME A::const_reference operator*() const {
|
||||
return *base_;
|
||||
}
|
||||
value_type const* operator->() const {
|
||||
return &*base_;
|
||||
}
|
||||
hash_const_iterator& operator++() {
|
||||
base_.increment(); return *this;
|
||||
}
|
||||
hash_const_iterator operator++(int) {
|
||||
hash_const_iterator tmp(base_); base_.increment(); return tmp;
|
||||
}
|
||||
bool operator==(iterator const& x) const {
|
||||
return base_ == x.base_;
|
||||
}
|
||||
bool operator==(hash_const_iterator const& x) const {
|
||||
return base_ == x.base_;
|
||||
}
|
||||
bool operator!=(iterator const& x) const {
|
||||
return base_ != x.base_;
|
||||
}
|
||||
bool operator!=(hash_const_iterator const& x) const {
|
||||
return base_ != x.base_;
|
||||
}
|
||||
};
|
||||
}}
|
||||
|
||||
|
@ -1,678 +0,0 @@
|
||||
|
||||
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
||||
// Copyright (C) 2005-2009 Daniel James
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_INSERT_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_INSERT_HPP_INCLUDED
|
||||
|
||||
#include <boost/unordered/detail/table.hpp>
|
||||
#include <boost/unordered/detail/extract_key.hpp>
|
||||
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// A couple of convenience methods for adding nodes.
|
||||
|
||||
// H = Has Func
|
||||
// P = Predicate
|
||||
// A = Value Allocator
|
||||
// K = Key Extractor
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
class hash_unique_table :
|
||||
public hash_table<H, P, A, boost::unordered_detail::ungrouped, K>
|
||||
|
||||
{
|
||||
public:
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef A value_allocator;
|
||||
typedef K key_extractor;
|
||||
|
||||
typedef hash_table<H, P, A, boost::unordered_detail::ungrouped, K> table;
|
||||
typedef hash_node_constructor<A, boost::unordered_detail::ungrouped> node_constructor;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME table::key_type key_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::node node;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::node_ptr node_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::extractor extractor;
|
||||
|
||||
// Constructors
|
||||
|
||||
hash_unique_table(std::size_t n, hasher const& hf, key_equal const& eq, value_allocator const& a)
|
||||
: table(n, hf, eq, a) {}
|
||||
hash_unique_table(hash_unique_table const& x)
|
||||
: table(x) {}
|
||||
hash_unique_table(hash_unique_table const& x, value_allocator const& a)
|
||||
: table(x, a) {}
|
||||
hash_unique_table(hash_unique_table& x, move_tag m)
|
||||
: table(x, m) {}
|
||||
hash_unique_table(hash_unique_table& x, value_allocator const& a, move_tag m)
|
||||
: table(x, a, m) {}
|
||||
~hash_unique_table() {}
|
||||
|
||||
// Insert methods
|
||||
|
||||
std::pair<iterator_base, bool> emplace_impl_with_node(node_constructor& a);
|
||||
value_type& operator[](key_type const& k);
|
||||
|
||||
// equals
|
||||
|
||||
bool equals(hash_unique_table const&) const;
|
||||
static bool group_equals(node_ptr it1, node_ptr it2, set_extractor*);
|
||||
static bool group_equals(node_ptr it1, node_ptr it2, map_extractor*);
|
||||
|
||||
inline node_ptr add_node(node_constructor& a, bucket_ptr bucket)
|
||||
{
|
||||
node_ptr n = a.release();
|
||||
node::add_to_bucket(n, *bucket);
|
||||
++this->size_;
|
||||
if(bucket < this->cached_begin_bucket_) this->cached_begin_bucket_ = bucket;
|
||||
return n;
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
// Emplace (unique keys)
|
||||
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
|
||||
|
||||
// if hash function throws, basic exception safety
|
||||
// strong otherwise
|
||||
template<class... Args>
|
||||
std::pair<iterator_base, bool> emplace(Args&&... args)
|
||||
{
|
||||
return emplace_impl(
|
||||
extractor::extract(std::forward<Args>(args)...),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Insert (unique keys)
|
||||
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
|
||||
// I'm just ignoring hints here for now.
|
||||
|
||||
// if hash function throws, basic exception safety
|
||||
// strong otherwise
|
||||
template<class... Args>
|
||||
iterator_base emplace_hint(iterator_base const&, Args&&... args)
|
||||
{
|
||||
return emplace_impl(
|
||||
extractor::extract(std::forward<Args>(args)...),
|
||||
std::forward<Args>(args)...).first;
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
std::pair<iterator_base, bool> emplace_impl(key_type const& k, Args&&... args)
|
||||
{
|
||||
// No side effects in this initial code
|
||||
std::size_t hash_value = this->hash_function()(k);
|
||||
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
node_ptr pos = find_iterator(bucket, k);
|
||||
|
||||
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
|
||||
// Found an existing key, return it (no throw).
|
||||
return std::pair<iterator_base, bool>(
|
||||
iterator_base(bucket, pos), false);
|
||||
|
||||
} else {
|
||||
// Doesn't already exist, add to bucket.
|
||||
// Side effects only in this block.
|
||||
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
node_constructor a(*this);
|
||||
a.construct(std::forward<Args>(args)...);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
if(reserve_for_insert(this->size_ + 1))
|
||||
bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
|
||||
// Nothing after this point can throw.
|
||||
|
||||
return std::pair<iterator_base, bool>(iterator_base(bucket,
|
||||
add_node(a, bucket)), true);
|
||||
}
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
std::pair<iterator_base, bool> emplace_impl(no_key, Args&&... args)
|
||||
{
|
||||
// Construct the node regardless - in order to get the key.
|
||||
// It will be discarded if it isn't used
|
||||
node_constructor a(*this);
|
||||
a.construct(std::forward<Args>(args)...);
|
||||
return emplace_impl_with_node(a);
|
||||
}
|
||||
#else
|
||||
template <class Arg0>
|
||||
std::pair<iterator_base, bool> emplace(Arg0 const& arg0)
|
||||
{
|
||||
return emplace_impl(extractor::extract(arg0), arg0);
|
||||
}
|
||||
|
||||
template <class Arg0>
|
||||
iterator_base emplace_hint(iterator_base const&, Arg0 const& arg0)
|
||||
{
|
||||
return emplace_impl(extractor::extract(arg0), arg0).first;
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
std::pair<iterator_base, bool> emplace( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return emplace_impl(extractor::extract(arg0, arg1), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n)); \
|
||||
} \
|
||||
\
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
iterator_base emplace_hint(iterator_base const& it, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return emplace_impl(extractor::extract(arg0, arg1), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n)).first; \
|
||||
} \
|
||||
BOOST_UNORDERED_INSERT_IMPL2(z, n, _)
|
||||
|
||||
#define BOOST_UNORDERED_INSERT_IMPL2(z, n, _) \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
std::pair<iterator_base, bool> emplace_impl(key_type const& k, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
std::size_t hash_value = this->hash_function()(k); \
|
||||
bucket_ptr bucket \
|
||||
= this->bucket_ptr_from_hash(hash_value); \
|
||||
node_ptr pos = find_iterator(bucket, k); \
|
||||
\
|
||||
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) { \
|
||||
return std::pair<iterator_base, bool>( \
|
||||
iterator_base(bucket, pos), false); \
|
||||
} else { \
|
||||
node_constructor a(*this); \
|
||||
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
|
||||
\
|
||||
if(reserve_for_insert(this->size_ + 1)) \
|
||||
bucket = this->bucket_ptr_from_hash(hash_value); \
|
||||
\
|
||||
return std::pair<iterator_base, bool>(iterator_base(bucket, \
|
||||
add_node(a, bucket)), true); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
std::pair<iterator_base, bool> emplace_impl(no_key, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
|
||||
{ \
|
||||
node_constructor a(*this); \
|
||||
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
|
||||
return emplace_impl_with_node(a); \
|
||||
}
|
||||
|
||||
BOOST_UNORDERED_INSERT_IMPL2(1, 1, _)
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_INSERT_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_INSERT_IMPL
|
||||
|
||||
#endif
|
||||
|
||||
// if hash function throws, or inserting > 1 element, basic exception safety
|
||||
// strong otherwise
|
||||
template <class InputIterator>
|
||||
void insert_range(InputIterator i, InputIterator j)
|
||||
{
|
||||
if(i != j)
|
||||
return insert_range_impl(extractor::extract(*i), i, j);
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
void insert_range_impl(key_type const&, InputIterator i, InputIterator j)
|
||||
{
|
||||
node_constructor a(*this);
|
||||
|
||||
for (; i != j; ++i) {
|
||||
// No side effects in this initial code
|
||||
std::size_t hash_value = this->hash_function()(extractor::extract(*i));
|
||||
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
node_ptr pos = find_iterator(bucket, extractor::extract(*i));
|
||||
|
||||
if (!BOOST_UNORDERED_BORLAND_BOOL(pos)) {
|
||||
// Doesn't already exist, add to bucket.
|
||||
// Side effects only in this block.
|
||||
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
a.construct(*i);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
if(this->size_ + 1 >= this->max_load_) {
|
||||
reserve_for_insert(this->size_ + insert_size(i, j));
|
||||
bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
}
|
||||
|
||||
// Nothing after this point can throw.
|
||||
add_node(a, bucket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
void insert_range_impl(no_key, InputIterator i, InputIterator j)
|
||||
{
|
||||
node_constructor a(*this);
|
||||
|
||||
for (; i != j; ++i) {
|
||||
// No side effects in this initial code
|
||||
a.construct(*i);
|
||||
emplace_impl_with_node(a);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
class hash_equivalent_table :
|
||||
public hash_table<H, P, A, boost::unordered_detail::grouped, K>
|
||||
|
||||
{
|
||||
public:
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef A value_allocator;
|
||||
typedef K key_extractor;
|
||||
|
||||
typedef hash_table<H, P, A, boost::unordered_detail::grouped, K> table;
|
||||
typedef hash_node_constructor<A, boost::unordered_detail::grouped> node_constructor;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME table::key_type key_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::node node;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::node_ptr node_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::bucket_ptr bucket_ptr;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::extractor extractor;
|
||||
|
||||
// Constructors
|
||||
|
||||
hash_equivalent_table(std::size_t n, hasher const& hf, key_equal const& eq, value_allocator const& a)
|
||||
: table(n, hf, eq, a) {}
|
||||
hash_equivalent_table(hash_equivalent_table const& x)
|
||||
: table(x) {}
|
||||
hash_equivalent_table(hash_equivalent_table const& x, value_allocator const& a)
|
||||
: table(x, a) {}
|
||||
hash_equivalent_table(hash_equivalent_table& x, move_tag m)
|
||||
: table(x, m) {}
|
||||
hash_equivalent_table(hash_equivalent_table& x, value_allocator const& a, move_tag m)
|
||||
: table(x, a, m) {}
|
||||
~hash_equivalent_table() {}
|
||||
|
||||
// Insert methods
|
||||
|
||||
iterator_base emplace_impl(node_constructor& a);
|
||||
iterator_base emplace_hint_impl(iterator_base const& it, node_constructor& a);
|
||||
void emplace_impl_no_rehash(node_constructor& a);
|
||||
|
||||
// equals
|
||||
|
||||
bool equals(hash_equivalent_table const&) const;
|
||||
static bool group_equals(node_ptr it1, node_ptr it2, set_extractor*);
|
||||
static bool group_equals(node_ptr it1, node_ptr it2, map_extractor*);
|
||||
|
||||
inline node_ptr add_node(node_constructor& a, bucket_ptr bucket, node_ptr pos)
|
||||
{
|
||||
node_ptr n = a.release();
|
||||
if(BOOST_UNORDERED_BORLAND_BOOL(pos)) {
|
||||
node::add_after_node(n, pos);
|
||||
}
|
||||
else {
|
||||
node::add_to_bucket(n, *bucket);
|
||||
if(bucket < this->cached_begin_bucket_) this->cached_begin_bucket_ = bucket;
|
||||
}
|
||||
++this->size_;
|
||||
return n;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// Insert functions
|
||||
//
|
||||
// basic exception safety, if hash function throws
|
||||
// strong otherwise.
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
// Emplace (equivalent key containers)
|
||||
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
|
||||
|
||||
// if hash function throws, basic exception safety
|
||||
// strong otherwise
|
||||
template <class... Args>
|
||||
iterator_base emplace(Args&&... args)
|
||||
{
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
node_constructor a(*this);
|
||||
a.construct(std::forward<Args>(args)...);
|
||||
|
||||
return emplace_impl(a);
|
||||
}
|
||||
|
||||
// Emplace (equivalent key containers)
|
||||
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
|
||||
|
||||
// if hash function throws, basic exception safety
|
||||
// strong otherwise
|
||||
template <class... Args>
|
||||
iterator_base emplace_hint(iterator_base const& it, Args&&... args)
|
||||
{
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
node_constructor a(*this);
|
||||
a.construct(std::forward<Args>(args)...);
|
||||
|
||||
return emplace_hint_impl(it, a);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
iterator_base emplace( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
node_constructor a(*this); \
|
||||
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
|
||||
return emplace_impl(a); \
|
||||
} \
|
||||
\
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
iterator_base emplace_hint(iterator_base const& it, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
node_constructor a(*this); \
|
||||
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
|
||||
return emplace_hint_impl(it, a); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_INSERT_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_INSERT_IMPL
|
||||
#endif
|
||||
|
||||
// Insert from iterator range (equivalent key containers)
|
||||
|
||||
private:
|
||||
|
||||
// if hash function throws, or inserting > 1 element, basic exception safety
|
||||
// strong otherwise
|
||||
template <class I>
|
||||
void insert_for_range(I i, I j, forward_traversal_tag)
|
||||
{
|
||||
std::size_t distance = unordered_detail::distance(i, j);
|
||||
if(distance == 1) {
|
||||
emplace(*i);
|
||||
}
|
||||
else {
|
||||
// Only require basic exception safety here
|
||||
reserve_for_insert(this->size_ + distance);
|
||||
node_constructor a(*this);
|
||||
|
||||
for (; i != j; ++i) {
|
||||
a.construct(*i);
|
||||
emplace_impl_no_rehash(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if hash function throws, or inserting > 1 element, basic exception safety
|
||||
// strong otherwise
|
||||
template <class I>
|
||||
void insert_for_range(I i, I j,
|
||||
boost::incrementable_traversal_tag)
|
||||
{
|
||||
node_constructor a(*this);
|
||||
for (; i != j; ++i) {
|
||||
a.construct(*i);
|
||||
emplace_impl(a);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// if hash function throws, or inserting > 1 element, basic exception safety
|
||||
// strong otherwise
|
||||
template <class I>
|
||||
void insert_range(I i, I j)
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME boost::iterator_traversal<I>::type
|
||||
iterator_traversal_tag;
|
||||
insert_for_range(i, j, iterator_traversal_tag);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Unique insert methods
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
std::pair<
|
||||
BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::iterator_base,
|
||||
bool>
|
||||
hash_unique_table<H, P, A, K>
|
||||
::emplace_impl_with_node(node_constructor& a)
|
||||
{
|
||||
// No side effects in this initial code
|
||||
key_type const& k = extractor::extract(a.get()->value());
|
||||
std::size_t hash_value = this->hash_function()(k);
|
||||
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
node_ptr pos = find_iterator(bucket, k);
|
||||
|
||||
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
|
||||
// Found an existing key, return it (no throw).
|
||||
return std::pair<iterator_base, bool>(
|
||||
iterator_base(bucket, pos), false);
|
||||
} else {
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
if(reserve_for_insert(this->size_ + 1))
|
||||
bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
|
||||
// Nothing after this point can throw.
|
||||
|
||||
return std::pair<iterator_base, bool>(iterator_base(bucket,
|
||||
add_node(a, bucket)), true);
|
||||
}
|
||||
}
|
||||
|
||||
// if hash function throws, basic exception safety
|
||||
// strong otherwise
|
||||
template <class H, class P, class A, class K>
|
||||
BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::value_type&
|
||||
hash_unique_table<H, P, A, K>
|
||||
::operator[](key_type const& k)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME value_type::second_type mapped_type;
|
||||
|
||||
std::size_t hash_value = this->hash_function()(k);
|
||||
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
node_ptr pos = find_iterator(bucket, k);
|
||||
|
||||
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
|
||||
return node::get_value(pos);
|
||||
}
|
||||
else {
|
||||
// Side effects only in this block.
|
||||
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
node_constructor a(*this);
|
||||
a.construct_pair(k, (mapped_type*) 0);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
if(reserve_for_insert(this->size_ + 1))
|
||||
bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
|
||||
// Nothing after this point can throw.
|
||||
|
||||
return node::get_value(add_node(a, bucket));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Insert methods
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::iterator_base
|
||||
hash_equivalent_table<H, P, A, K>
|
||||
::emplace_impl(node_constructor& a)
|
||||
{
|
||||
key_type const& k = extractor::extract(a.get()->value());
|
||||
std::size_t hash_value = this->hash_function()(k);
|
||||
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
node_ptr position = find_iterator(bucket, k);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
if(reserve_for_insert(this->size_ + 1))
|
||||
bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
|
||||
// I'm relying on node_ptr not being invalidated by
|
||||
// the rehash here.
|
||||
return iterator_base(bucket, add_node(a, bucket, position));
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
BOOST_DEDUCED_TYPENAME hash_equivalent_table<H, P, A, K>::iterator_base
|
||||
hash_equivalent_table<H, P, A, K>
|
||||
::emplace_hint_impl(iterator_base const& it, node_constructor& a)
|
||||
{
|
||||
// equal can throw, but with no effects
|
||||
if (it.is_end() ||
|
||||
!equal(extractor::extract(a.get()->value()), node::get_value(it.get()))) {
|
||||
// Use the standard emplace if the iterator doesn't point
|
||||
// to a matching key.
|
||||
return emplace_impl(a);
|
||||
}
|
||||
else {
|
||||
// Find the first node in the group - so that the node
|
||||
// will be added at the end of the group.
|
||||
|
||||
node_ptr start(it.node_);
|
||||
while(node::next_group(start) == start)
|
||||
start = node::group_prev(start);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
bucket_ptr bucket = reserve_for_insert(this->size_ + 1) ?
|
||||
get_bucket(this->bucket_index(
|
||||
extractor::extract(a.get()->value()))) : it.bucket_;
|
||||
|
||||
// Nothing after this point can throw
|
||||
|
||||
return iterator_base(bucket, add_node(a, bucket, start));
|
||||
}
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
void hash_equivalent_table<H, P, A, K>
|
||||
::emplace_impl_no_rehash(node_constructor& a)
|
||||
{
|
||||
key_type const& k = extractor::extract(a.get()->value());
|
||||
bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
|
||||
add_node(a, bucket, find_iterator(bucket, k));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Equalilty check
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
inline bool hash_equivalent_table<H, P, A, K>
|
||||
::group_equals(node_ptr it1, node_ptr it2, set_extractor*)
|
||||
{
|
||||
return node::group_count(it1) == node::group_count(it2);
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
inline bool hash_equivalent_table<H, P, A, K>
|
||||
::group_equals(node_ptr it1, node_ptr it2, map_extractor*)
|
||||
{
|
||||
node_ptr end1 = node::next_group(it1);
|
||||
node_ptr end2 = node::next_group(it2);
|
||||
|
||||
do {
|
||||
if(node::get_value(it1).second != node::get_value(it2).second) return false;
|
||||
it1 = next_node(it1);
|
||||
it2 = next_node(it2);
|
||||
} while(it1 != end1 && it2 != end2);
|
||||
return it1 == end1 && it2 == end2;
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
bool hash_equivalent_table<H, P, A, K>
|
||||
::equals(hash_equivalent_table<H, P, A, K> const& other) const
|
||||
{
|
||||
if(this->size_ != other.size_) return false;
|
||||
|
||||
for(bucket_ptr i = this->cached_begin_bucket_, j = this->buckets_end(); i != j; ++i)
|
||||
{
|
||||
for(node_ptr it(i->next_); BOOST_UNORDERED_BORLAND_BOOL(it); it = node::next_group(it))
|
||||
{
|
||||
node_ptr other_pos = other.find_iterator(extractor::extract(node::get_value(it)));
|
||||
if(!BOOST_UNORDERED_BORLAND_BOOL(other_pos) ||
|
||||
!group_equals(it, other_pos, (K*)0))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
inline bool hash_unique_table<H, P, A, K>
|
||||
::group_equals(node_ptr, node_ptr, set_extractor*)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
inline bool hash_unique_table<H, P, A, K>
|
||||
::group_equals(node_ptr it1, node_ptr it2, map_extractor*)
|
||||
{
|
||||
return node::get_value(it1).second == node::get_value(it2).second;
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
bool hash_unique_table<H, P, A, K>
|
||||
::equals(hash_unique_table<H, P, A, K> const& other) const
|
||||
{
|
||||
if(this->size_ != other.size_) return false;
|
||||
|
||||
for(bucket_ptr i = this->cached_begin_bucket_, j = this->buckets_end(); i != j; ++i)
|
||||
{
|
||||
for(node_ptr it(i->next_); BOOST_UNORDERED_BORLAND_BOOL(it); it = node::next_group(it))
|
||||
{
|
||||
node_ptr other_pos = other.find_iterator(extractor::extract(node::get_value(it)));
|
||||
if(!BOOST_UNORDERED_BORLAND_BOOL(other_pos) ||
|
||||
!group_equals(it, other_pos, (K*)0))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
@ -109,6 +109,8 @@ struct move_from
|
||||
{
|
||||
explicit move_from(T& x) : source(x) { }
|
||||
T& source;
|
||||
private:
|
||||
move_from& operator=(move_from const&);
|
||||
};
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -24,23 +24,6 @@
|
||||
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
template <class BucketPtr>
|
||||
inline BucketPtr& next_node(BucketPtr ptr)
|
||||
{
|
||||
return ptr->next_;
|
||||
}
|
||||
|
||||
template <class BucketPtr>
|
||||
inline std::size_t node_count(BucketPtr ptr, BucketPtr end)
|
||||
{
|
||||
std::size_t count = 0;
|
||||
while(ptr != end) {
|
||||
++count;
|
||||
ptr = next_node(ptr);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// ungrouped node implementation
|
||||
|
||||
@ -48,7 +31,7 @@ namespace boost { namespace unordered_detail {
|
||||
inline BOOST_DEDUCED_TYPENAME ungrouped_node_base<A>::node_ptr&
|
||||
ungrouped_node_base<A>::next_group(node_ptr ptr)
|
||||
{
|
||||
return next_node(ptr);
|
||||
return ptr->next_;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
@ -60,35 +43,24 @@ namespace boost { namespace unordered_detail {
|
||||
template <class A>
|
||||
inline void ungrouped_node_base<A>::add_to_bucket(node_ptr n, bucket& b)
|
||||
{
|
||||
next_node(n) = b.next_;
|
||||
n->next_ = b.next_;
|
||||
b.next_ = n;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void ungrouped_node_base<A>::add_group_to_bucket(node_ptr n, bucket& b)
|
||||
inline void ungrouped_node_base<A>::add_after_node(node_ptr n,
|
||||
node_ptr position)
|
||||
{
|
||||
next_node(n) = b.next_;
|
||||
b.next_ = n;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void ungrouped_node_base<A>::add_after_node(node_ptr n, node_ptr position)
|
||||
{
|
||||
next_node(n) = next_node(position);
|
||||
next_node(position) = position;
|
||||
n->next_ = position->next_;
|
||||
position->next_ = position;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void ungrouped_node_base<A>::unlink_node(bucket& b, node_ptr node)
|
||||
{
|
||||
unlink_nodes(b, node, next_node(node));
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void ungrouped_node_base<A>::unlink_nodes(bucket& b, node_ptr begin, node_ptr end)
|
||||
inline void ungrouped_node_base<A>::unlink_nodes(bucket& b,
|
||||
node_ptr begin, node_ptr end)
|
||||
{
|
||||
node_ptr* pos = &b.next_;
|
||||
while(*pos != begin) pos = &next_node(*pos);
|
||||
while(*pos != begin) pos = &(*pos)->next_;
|
||||
*pos = end;
|
||||
}
|
||||
|
||||
@ -99,26 +71,30 @@ namespace boost { namespace unordered_detail {
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void ungrouped_node_base<A>::unlink_group(node_ptr* b)
|
||||
inline void ungrouped_node_base<A>::unlink_node(bucket& b, node_ptr node)
|
||||
{
|
||||
*b = next_node(*b);
|
||||
unlink_nodes(b, node, node->next_);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// grouped node implementation
|
||||
|
||||
template <class A>
|
||||
inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr&
|
||||
grouped_node_base<A>::group_prev(node_ptr ptr)
|
||||
{
|
||||
return get(ptr).group_prev_;
|
||||
}
|
||||
|
||||
// If ptr is the first element in a group, return pointer to next group.
|
||||
// Otherwise returns a pointer to ptr.
|
||||
template <class A>
|
||||
inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr&
|
||||
grouped_node_base<A>::next_group(node_ptr ptr)
|
||||
{
|
||||
return next_node(group_prev(ptr));
|
||||
return get(ptr).group_prev_->next_;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr
|
||||
grouped_node_base<A>::first_in_group(node_ptr ptr)
|
||||
{
|
||||
while(next_group(ptr) == ptr)
|
||||
ptr = get(ptr).group_prev_;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
@ -128,7 +104,7 @@ namespace boost { namespace unordered_detail {
|
||||
std::size_t size = 0;
|
||||
do {
|
||||
++size;
|
||||
ptr = group_prev(ptr);
|
||||
ptr = get(ptr).group_prev_;
|
||||
} while(ptr != start);
|
||||
return size;
|
||||
}
|
||||
@ -136,25 +112,18 @@ namespace boost { namespace unordered_detail {
|
||||
template <class A>
|
||||
inline void grouped_node_base<A>::add_to_bucket(node_ptr n, bucket& b)
|
||||
{
|
||||
next_node(n) = b.next_;
|
||||
group_prev(n) = n;
|
||||
n->next_ = b.next_;
|
||||
get(n).group_prev_ = n;
|
||||
b.next_ = n;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void grouped_node_base<A>::add_group_to_bucket(node_ptr n, bucket& b)
|
||||
inline void grouped_node_base<A>::add_after_node(node_ptr n, node_ptr pos)
|
||||
{
|
||||
next_group(n) = b.next_;
|
||||
b.next_ = n;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void grouped_node_base<A>::add_after_node(node_ptr n, node_ptr position)
|
||||
{
|
||||
next_node(n) = next_group(position);
|
||||
group_prev(n) = group_prev(position);
|
||||
next_group(position) = n;
|
||||
group_prev(position) = n;
|
||||
n->next_ = next_group(pos);
|
||||
get(n).group_prev_ = get(pos).group_prev_;
|
||||
next_group(pos) = n;
|
||||
get(pos).group_prev_ = n;
|
||||
}
|
||||
|
||||
// Break a ciruclar list into two, with split as the beginning
|
||||
@ -164,29 +133,21 @@ namespace boost { namespace unordered_detail {
|
||||
inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr
|
||||
grouped_node_base<A>::split_group(node_ptr split)
|
||||
{
|
||||
// If split is at the beginning of the group then there's
|
||||
// nothing to split.
|
||||
if(next_node(group_prev(split)) != split)
|
||||
return split;
|
||||
node_ptr first = first_in_group(split);
|
||||
if(first == split) return split;
|
||||
|
||||
// Find the start of the group.
|
||||
node_ptr start = split;
|
||||
do {
|
||||
start = group_prev(start);
|
||||
} while(next_node(group_prev(start)) == start);
|
||||
node_ptr last = get(first).group_prev_;
|
||||
get(first).group_prev_ = get(split).group_prev_;
|
||||
get(split).group_prev_ = last;
|
||||
|
||||
node_ptr last = group_prev(start);
|
||||
group_prev(start) = group_prev(split);
|
||||
group_prev(split) = last;
|
||||
|
||||
return start;
|
||||
return first;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
void grouped_node_base<A>::unlink_node(bucket& b, node_ptr node)
|
||||
{
|
||||
node_ptr next = next_node(node);
|
||||
node_ptr* pos = &next_node(group_prev(node));
|
||||
node_ptr next = node->next_;
|
||||
node_ptr* pos = &next_group(node);
|
||||
|
||||
if(*pos != node) {
|
||||
// The node is at the beginning of a group.
|
||||
@ -196,31 +157,37 @@ namespace boost { namespace unordered_detail {
|
||||
while(*pos != node) pos = &next_group(*pos);
|
||||
|
||||
// Remove from group
|
||||
if(BOOST_UNORDERED_BORLAND_BOOL(next) && group_prev(next) == node)
|
||||
group_prev(next) = group_prev(node);
|
||||
if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
|
||||
get(next).group_prev_ == node)
|
||||
{
|
||||
get(next).group_prev_ = get(node).group_prev_;
|
||||
}
|
||||
}
|
||||
else if(BOOST_UNORDERED_BORLAND_BOOL(next) && group_prev(next) == node) {
|
||||
else if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
|
||||
get(next).group_prev_ == node)
|
||||
{
|
||||
// The deleted node is not at the end of the group, so
|
||||
// change the link from the next node.
|
||||
group_prev(next) = group_prev(node);
|
||||
get(next).group_prev_ = get(node).group_prev_;
|
||||
}
|
||||
else {
|
||||
// The deleted node is at the end of the group, so the
|
||||
// first node in the group is pointing to it.
|
||||
// Find that to change its pointer.
|
||||
node_ptr x = group_prev(node);
|
||||
while(group_prev(x) != node) {
|
||||
x = group_prev(x);
|
||||
node_ptr x = get(node).group_prev_;
|
||||
while(get(x).group_prev_ != node) {
|
||||
x = get(x).group_prev_;
|
||||
}
|
||||
group_prev(x) = group_prev(node);
|
||||
get(x).group_prev_ = get(node).group_prev_;
|
||||
}
|
||||
*pos = next;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
void grouped_node_base<A>::unlink_nodes(bucket& b, node_ptr begin, node_ptr end)
|
||||
void grouped_node_base<A>::unlink_nodes(bucket& b,
|
||||
node_ptr begin, node_ptr end)
|
||||
{
|
||||
node_ptr* pos = &next_node(group_prev(begin));
|
||||
node_ptr* pos = &next_group(begin);
|
||||
|
||||
if(*pos != begin) {
|
||||
// The node is at the beginning of a group.
|
||||
@ -238,10 +205,10 @@ namespace boost { namespace unordered_detail {
|
||||
node_ptr group2 = split_group(end);
|
||||
|
||||
if(begin == group2) {
|
||||
node_ptr end1 = group_prev(group1);
|
||||
node_ptr end2 = group_prev(group2);
|
||||
group_prev(group1) = end2;
|
||||
group_prev(group2) = end1;
|
||||
node_ptr end1 = get(group1).group_prev_;
|
||||
node_ptr end2 = get(group2).group_prev_;
|
||||
get(group1).group_prev_ = end2;
|
||||
get(group2).group_prev_ = end1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -254,12 +221,6 @@ namespace boost { namespace unordered_detail {
|
||||
split_group(end);
|
||||
b.next_ = end;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline void grouped_node_base<A>::unlink_group(node_ptr* b)
|
||||
{
|
||||
*b = next_group(*b);
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
431
include/boost/unordered/detail/unique.hpp
Normal file
431
include/boost/unordered/detail/unique.hpp
Normal file
@ -0,0 +1,431 @@
|
||||
|
||||
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
||||
// Copyright (C) 2005-2009 Daniel James
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
|
||||
#define BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
|
||||
|
||||
#include <boost/unordered/detail/table.hpp>
|
||||
#include <boost/unordered/detail/extract_key.hpp>
|
||||
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Equality
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
bool hash_unique_table<H, P, A, K>
|
||||
::equals(hash_unique_table<H, P, A, K> const& other) const
|
||||
{
|
||||
if(this->size_ != other.size_) return false;
|
||||
if(!this->size_) return true;
|
||||
|
||||
bucket_ptr end = this->get_bucket(this->bucket_count_);
|
||||
for(bucket_ptr i = this->cached_begin_bucket_; i != end; ++i)
|
||||
{
|
||||
node_ptr it1 = i->next_;
|
||||
while(BOOST_UNORDERED_BORLAND_BOOL(it1))
|
||||
{
|
||||
node_ptr it2 = other.find_iterator(get_key_from_ptr(it1));
|
||||
if(!BOOST_UNORDERED_BORLAND_BOOL(it2)) return false;
|
||||
if(!extractor::compare_mapped(
|
||||
node::get_value(it1), node::get_value(it2)))
|
||||
return false;
|
||||
it1 = it1->next_;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// A convenience method for adding nodes.
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::node_ptr
|
||||
hash_unique_table<H, P, A, K>::add_node(node_constructor& a,
|
||||
bucket_ptr bucket)
|
||||
{
|
||||
node_ptr n = a.release();
|
||||
node::add_to_bucket(n, *bucket);
|
||||
++this->size_;
|
||||
if(bucket < this->cached_begin_bucket_)
|
||||
this->cached_begin_bucket_ = bucket;
|
||||
return n;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Insert methods
|
||||
|
||||
// if hash function throws, basic exception safety
|
||||
// strong otherwise
|
||||
template <class H, class P, class A, class K>
|
||||
BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::value_type&
|
||||
hash_unique_table<H, P, A, K>::operator[](key_type const& k)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME value_type::second_type mapped_type;
|
||||
|
||||
std::size_t hash_value = this->hash_function()(k);
|
||||
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
|
||||
if(!this->buckets_) {
|
||||
node_constructor a(*this);
|
||||
a.construct_pair(k, (mapped_type*) 0);
|
||||
return *this->emplace_empty_impl_with_node(a, 1);
|
||||
}
|
||||
|
||||
node_ptr pos = find_iterator(bucket, k);
|
||||
|
||||
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
|
||||
return node::get_value(pos);
|
||||
}
|
||||
else {
|
||||
// Side effects only in this block.
|
||||
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
node_constructor a(*this);
|
||||
a.construct_pair(k, (mapped_type*) 0);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
if(this->reserve_for_insert(this->size_ + 1))
|
||||
bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
|
||||
// Nothing after this point can throw.
|
||||
|
||||
return node::get_value(add_node(a, bucket));
|
||||
}
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
|
||||
hash_unique_table<H, P, A, K>
|
||||
::emplace_impl_with_node(node_constructor& a)
|
||||
{
|
||||
// No side effects in this initial code
|
||||
key_type const& k = get_key(a.value());
|
||||
std::size_t hash_value = this->hash_function()(k);
|
||||
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
node_ptr pos = find_iterator(bucket, k);
|
||||
|
||||
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
|
||||
// Found an existing key, return it (no throw).
|
||||
return emplace_return(iterator_base(bucket, pos), false);
|
||||
} else {
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
if(this->reserve_for_insert(this->size_ + 1))
|
||||
bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
|
||||
// Nothing after this point can throw.
|
||||
|
||||
return emplace_return(
|
||||
iterator_base(bucket, add_node(a, bucket)),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
template<class... Args>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
|
||||
hash_unique_table<H, P, A, K>::emplace_impl(key_type const& k,
|
||||
Args&&... args)
|
||||
{
|
||||
// No side effects in this initial code
|
||||
std::size_t hash_value = this->hash_function()(k);
|
||||
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
node_ptr pos = find_iterator(bucket, k);
|
||||
|
||||
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
|
||||
// Found an existing key, return it (no throw).
|
||||
return emplace_return(iterator_base(bucket, pos), false);
|
||||
|
||||
} else {
|
||||
// Doesn't already exist, add to bucket.
|
||||
// Side effects only in this block.
|
||||
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
node_constructor a(*this);
|
||||
a.construct(std::forward<Args>(args)...);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
if(this->reserve_for_insert(this->size_ + 1))
|
||||
bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
|
||||
// Nothing after this point can throw.
|
||||
|
||||
return emplace_return(
|
||||
iterator_base(bucket, add_node(a, bucket)),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
template<class... Args>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
|
||||
hash_unique_table<H, P, A, K>::emplace_impl(no_key, Args&&... args)
|
||||
{
|
||||
// Construct the node regardless - in order to get the key.
|
||||
// It will be discarded if it isn't used
|
||||
node_constructor a(*this);
|
||||
a.construct(std::forward<Args>(args)...);
|
||||
return emplace_impl_with_node(a);
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
template<class... Args>
|
||||
inline BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
|
||||
hash_unique_table<H, P, A, K>::emplace_empty_impl(Args&&... args)
|
||||
{
|
||||
node_constructor a(*this);
|
||||
a.construct(std::forward<Args>(args)...);
|
||||
return emplace_return(this->emplace_empty_impl_with_node(a, 1), true);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
|
||||
template <class H, class P, class A, class K> \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
inline BOOST_DEDUCED_TYPENAME \
|
||||
hash_unique_table<H, P, A, K>::emplace_return \
|
||||
hash_unique_table<H, P, A, K>::emplace_impl( \
|
||||
key_type const& k, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
|
||||
{ \
|
||||
std::size_t hash_value = this->hash_function()(k); \
|
||||
bucket_ptr bucket \
|
||||
= this->bucket_ptr_from_hash(hash_value); \
|
||||
node_ptr pos = find_iterator(bucket, k); \
|
||||
\
|
||||
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) { \
|
||||
return emplace_return(iterator_base(bucket, pos), false); \
|
||||
} else { \
|
||||
node_constructor a(*this); \
|
||||
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
|
||||
\
|
||||
if(this->reserve_for_insert(this->size_ + 1)) \
|
||||
bucket = this->bucket_ptr_from_hash(hash_value); \
|
||||
\
|
||||
return emplace_return(iterator_base(bucket, \
|
||||
add_node(a, bucket)), true); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
template <class H, class P, class A, class K> \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
inline BOOST_DEDUCED_TYPENAME \
|
||||
hash_unique_table<H, P, A, K>::emplace_return \
|
||||
hash_unique_table<H, P, A, K>:: \
|
||||
emplace_impl(no_key, BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
|
||||
{ \
|
||||
node_constructor a(*this); \
|
||||
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
|
||||
return emplace_impl_with_node(a); \
|
||||
} \
|
||||
\
|
||||
template <class H, class P, class A, class K> \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
inline BOOST_DEDUCED_TYPENAME \
|
||||
hash_unique_table<H, P, A, K>::emplace_return \
|
||||
hash_unique_table<H, P, A, K>:: \
|
||||
emplace_empty_impl(BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
|
||||
{ \
|
||||
node_constructor a(*this); \
|
||||
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, n)); \
|
||||
return emplace_return(this->emplace_empty_impl_with_node(a, 1), true); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_INSERT_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_INSERT_IMPL
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
// Emplace (unique keys)
|
||||
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
|
||||
|
||||
// if hash function throws, basic exception safety
|
||||
// strong otherwise
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
template<class... Args>
|
||||
BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
|
||||
hash_unique_table<H, P, A, K>::emplace(Args&&... args)
|
||||
{
|
||||
return this->size_ ?
|
||||
emplace_impl(
|
||||
extractor::extract(std::forward<Args>(args)...),
|
||||
std::forward<Args>(args)...) :
|
||||
emplace_empty_impl(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Insert (unique keys)
|
||||
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
|
||||
// I'm just ignoring hints here for now.
|
||||
|
||||
// if hash function throws, basic exception safety
|
||||
// strong otherwise
|
||||
template <class H, class P, class A, class K>
|
||||
template<class... Args>
|
||||
BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::iterator_base
|
||||
hash_unique_table<H, P, A, K>::emplace_hint(iterator_base const&,
|
||||
Args&&... args)
|
||||
{
|
||||
return this->size_ ?
|
||||
emplace_impl(
|
||||
extractor::extract(std::forward<Args>(args)...),
|
||||
std::forward<Args>(args)...).first :
|
||||
emplace_empty_impl(std::forward<Args>(args)...).first;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
template <class Arg0>
|
||||
BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return
|
||||
hash_unique_table<H, P, A, K>::emplace(Arg0 const& arg0)
|
||||
{
|
||||
return this->size_ ?
|
||||
emplace_impl(extractor::extract(arg0), arg0) :
|
||||
emplace_empty_impl(arg0);
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
template <class Arg0>
|
||||
BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::iterator_base
|
||||
hash_unique_table<H, P, A, K>::emplace_hint(iterator_base const&,
|
||||
Arg0 const& arg0)
|
||||
{
|
||||
return this->size_ ?
|
||||
emplace_impl(extractor::extract(arg0), arg0).first :
|
||||
emplace_empty_impl(arg0).first;
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
|
||||
template <class H, class P, class A, class K> \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::emplace_return \
|
||||
hash_unique_table<H, P, A, K>::emplace( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
|
||||
{ \
|
||||
return this->size_ ? \
|
||||
emplace_impl(extractor::extract(arg0, arg1), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n)) : \
|
||||
emplace_empty_impl( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n)); \
|
||||
} \
|
||||
\
|
||||
template <class H, class P, class A, class K> \
|
||||
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
|
||||
BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::iterator_base \
|
||||
hash_unique_table<H, P, A, K>:: \
|
||||
emplace_hint(iterator_base const& it, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
|
||||
{ \
|
||||
return this->size_ ? \
|
||||
emplace_impl(extractor::extract(arg0, arg1), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n)) : \
|
||||
emplace_empty_impl( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n)); \
|
||||
} \
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
BOOST_UNORDERED_INSERT_IMPL, _)
|
||||
|
||||
#undef BOOST_UNORDERED_INSERT_IMPL
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Insert range methods
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
template <class InputIt>
|
||||
inline void hash_unique_table<H, P, A, K>::insert_range_impl(
|
||||
key_type const&, InputIt i, InputIt j)
|
||||
{
|
||||
node_constructor a(*this);
|
||||
|
||||
if(!this->size_) {
|
||||
a.construct(*i);
|
||||
this->emplace_empty_impl_with_node(a, 1);
|
||||
++i;
|
||||
if(i == j) return;
|
||||
}
|
||||
|
||||
do {
|
||||
// No side effects in this initial code
|
||||
// Note: can't use get_key as '*i' might not be value_type.
|
||||
// TODO: Check if std::pair has an appropriate constructor. If not
|
||||
// that might not be true.
|
||||
// TODO: Test this line better.
|
||||
key_type const& k = extractor::extract(*i);
|
||||
std::size_t hash_value = this->hash_function()(k);
|
||||
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
node_ptr pos = find_iterator(bucket, k);
|
||||
|
||||
if (!BOOST_UNORDERED_BORLAND_BOOL(pos)) {
|
||||
// Doesn't already exist, add to bucket.
|
||||
// Side effects only in this block.
|
||||
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
a.construct(*i);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
if(this->size_ + 1 >= this->max_load_) {
|
||||
this->reserve_for_insert(this->size_ + insert_size(i, j));
|
||||
bucket = this->bucket_ptr_from_hash(hash_value);
|
||||
}
|
||||
|
||||
// Nothing after this point can throw.
|
||||
add_node(a, bucket);
|
||||
}
|
||||
} while(++i != j);
|
||||
}
|
||||
|
||||
template <class H, class P, class A, class K>
|
||||
template <class InputIt>
|
||||
inline void hash_unique_table<H, P, A, K>::insert_range_impl(
|
||||
no_key, InputIt i, InputIt j)
|
||||
{
|
||||
node_constructor a(*this);
|
||||
|
||||
if(!this->size_) {
|
||||
a.construct(*i);
|
||||
this->emplace_empty_impl_with_node(a, 1);
|
||||
++i;
|
||||
if(i == j) return;
|
||||
}
|
||||
|
||||
do {
|
||||
// No side effects in this initial code
|
||||
a.construct(*i);
|
||||
emplace_impl_with_node(a);
|
||||
} while(++i != j);
|
||||
}
|
||||
|
||||
// if hash function throws, or inserting > 1 element, basic exception safety
|
||||
// strong otherwise
|
||||
template <class H, class P, class A, class K>
|
||||
template <class InputIt>
|
||||
void hash_unique_table<H, P, A, K>::insert_range(InputIt i, InputIt j)
|
||||
{
|
||||
if(i != j)
|
||||
return insert_range_impl(extractor::extract(*i), i, j);
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
@ -14,22 +14,7 @@
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
#include <boost/preprocessor/seq/size.hpp>
|
||||
#include <boost/preprocessor/seq/enum.hpp>
|
||||
#include <boost/unordered/detail/buckets.hpp>
|
||||
|
||||
#if !defined(BOOST_UNORDERED_STD_FORWARD)
|
||||
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
|
||||
#define BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, class Arg)
|
||||
#define BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, const& arg)
|
||||
#define BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
BOOST_PP_ENUM_PARAMS_Z(z, n, arg)
|
||||
|
||||
#endif
|
||||
#include <boost/unordered/detail/fwd.hpp>
|
||||
|
||||
namespace boost { namespace unordered_detail {
|
||||
|
||||
@ -38,7 +23,8 @@ namespace boost { namespace unordered_detail {
|
||||
|
||||
inline std::size_t double_to_size_t(double f)
|
||||
{
|
||||
return f >= static_cast<double>((std::numeric_limits<std::size_t>::max)()) ?
|
||||
return f >= static_cast<double>(
|
||||
(std::numeric_limits<std::size_t>::max)()) ?
|
||||
(std::numeric_limits<std::size_t>::max)() :
|
||||
static_cast<std::size_t>(f);
|
||||
}
|
||||
@ -143,7 +129,7 @@ namespace boost { namespace unordered_detail {
|
||||
|
||||
template <class I>
|
||||
inline std::size_t initial_size(I i, I j,
|
||||
std::size_t n = boost::unordered_detail::default_initial_bucket_count)
|
||||
std::size_t n = boost::unordered_detail::default_bucket_count)
|
||||
{
|
||||
return (std::max)(static_cast<std::size_t>(insert_size(i, j)) + 1, n);
|
||||
}
|
||||
@ -172,29 +158,29 @@ namespace boost { namespace unordered_detail {
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, n, _) \
|
||||
template < \
|
||||
class T, \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
inline void construct_impl( \
|
||||
T*, void* address, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
new(address) T( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n)); \
|
||||
} \
|
||||
\
|
||||
template <class First, class Second, class Key, \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
inline void construct_impl( \
|
||||
std::pair<First, Second>*, void* address, \
|
||||
Key const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
|
||||
{ \
|
||||
new(address) std::pair<First, Second>(k, \
|
||||
Second(BOOST_UNORDERED_CALL_PARAMS(z, n))); \
|
||||
#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, n, _) \
|
||||
template < \
|
||||
class T, \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
inline void construct_impl( \
|
||||
T*, void* address, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
new(address) T( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n)); \
|
||||
} \
|
||||
\
|
||||
template <class First, class Second, class Key, \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
inline void construct_impl( \
|
||||
std::pair<First, Second>*, void* address, \
|
||||
Key const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, n)) \
|
||||
{ \
|
||||
new(address) std::pair<First, Second>(k, \
|
||||
Second(BOOST_UNORDERED_CALL_PARAMS(z, n))); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
@ -244,20 +230,20 @@ namespace boost { namespace unordered_detail {
|
||||
}
|
||||
#else
|
||||
|
||||
#define BOOST_UNORDERED_CONSTRUCT(z, n, _) \
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
void construct( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
construct_preamble(); \
|
||||
construct_impl( \
|
||||
(value_type*) 0, node_->address(), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
); \
|
||||
value_constructed_ = true; \
|
||||
#define BOOST_UNORDERED_CONSTRUCT(z, n, _) \
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
void construct( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
construct_preamble(); \
|
||||
construct_impl( \
|
||||
(value_type*) 0, node_->address(), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
); \
|
||||
value_constructed_ = true; \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
@ -274,10 +260,10 @@ namespace boost { namespace unordered_detail {
|
||||
value_constructed_ = true;
|
||||
}
|
||||
|
||||
real_node_ptr get() const
|
||||
value_type& value() const
|
||||
{
|
||||
BOOST_ASSERT(node_);
|
||||
return node_;
|
||||
return node_->value();
|
||||
}
|
||||
|
||||
// no throw
|
||||
@ -297,11 +283,11 @@ namespace boost { namespace unordered_detail {
|
||||
// hash_node_constructor
|
||||
|
||||
template <class Alloc, class Grouped>
|
||||
hash_node_constructor<Alloc, Grouped>::~hash_node_constructor()
|
||||
inline hash_node_constructor<Alloc, Grouped>::~hash_node_constructor()
|
||||
{
|
||||
if (node_) {
|
||||
if (value_constructed_) {
|
||||
BOOST_UNORDERED_DESTRUCT(&node_->value(), value_type);
|
||||
boost::unordered_detail::destroy(&node_->value());
|
||||
}
|
||||
|
||||
if (node_constructed_)
|
||||
@ -312,7 +298,7 @@ namespace boost { namespace unordered_detail {
|
||||
}
|
||||
|
||||
template <class Alloc, class Grouped>
|
||||
void hash_node_constructor<Alloc, Grouped>::construct_preamble()
|
||||
inline void hash_node_constructor<Alloc, Grouped>::construct_preamble()
|
||||
{
|
||||
if(!node_) {
|
||||
node_constructed_ = false;
|
||||
@ -324,7 +310,7 @@ namespace boost { namespace unordered_detail {
|
||||
}
|
||||
else {
|
||||
BOOST_ASSERT(node_constructed_ && value_constructed_);
|
||||
BOOST_UNORDERED_DESTRUCT(&node_->value(), value_type);
|
||||
boost::unordered_detail::destroy(&node_->value());
|
||||
value_constructed_ = false;
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,8 @@
|
||||
#include <boost/unordered/unordered_map_fwd.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/unordered/detail/allocator_helpers.hpp>
|
||||
#include <boost/unordered/detail/insert.hpp>
|
||||
#include <boost/unordered/detail/equivalent.hpp>
|
||||
#include <boost/unordered/detail/unique.hpp>
|
||||
|
||||
#if !defined(BOOST_HAS_RVALUE_REFS)
|
||||
#include <boost/unordered/detail/move.hpp>
|
||||
@ -53,32 +54,41 @@ namespace boost
|
||||
#endif
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::unordered_detail::rebind_wrap<allocator_type, value_type>::type
|
||||
boost::unordered_detail::rebind_wrap<
|
||||
allocator_type, value_type>::type
|
||||
value_allocator;
|
||||
|
||||
typedef boost::unordered_detail::hash_unique_table<Hash, Pred, value_allocator,
|
||||
boost::unordered_detail::map_extractor> table;
|
||||
typedef boost::unordered_detail::hash_unique_table<Hash, Pred,
|
||||
value_allocator, boost::unordered_detail::map_extractor> table;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base;
|
||||
|
||||
public:
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::pointer pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::const_pointer const_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::reference reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::const_reference const_reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::pointer pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::const_pointer const_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::reference reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::const_reference const_reference;
|
||||
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef boost::unordered_detail::hash_const_local_iterator<
|
||||
value_allocator, boost::unordered_detail::ungrouped> const_local_iterator;
|
||||
value_allocator, boost::unordered_detail::ungrouped>
|
||||
const_local_iterator;
|
||||
typedef boost::unordered_detail::hash_local_iterator<
|
||||
value_allocator, boost::unordered_detail::ungrouped> local_iterator;
|
||||
value_allocator, boost::unordered_detail::ungrouped>
|
||||
local_iterator;
|
||||
typedef boost::unordered_detail::hash_const_iterator<
|
||||
value_allocator, boost::unordered_detail::ungrouped> const_iterator;
|
||||
value_allocator, boost::unordered_detail::ungrouped>
|
||||
const_iterator;
|
||||
typedef boost::unordered_detail::hash_iterator<
|
||||
value_allocator, boost::unordered_detail::ungrouped> iterator;
|
||||
value_allocator, boost::unordered_detail::ungrouped>
|
||||
iterator;
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
||||
private:
|
||||
@ -97,49 +107,51 @@ namespace boost
|
||||
// construct/destroy/copy
|
||||
|
||||
explicit unordered_map(
|
||||
size_type n = boost::unordered_detail::default_initial_bucket_count,
|
||||
size_type n = boost::unordered_detail::default_bucket_count,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: table_(n, hf, eql, a)
|
||||
: table_(n, hf, eql, a)
|
||||
{
|
||||
}
|
||||
|
||||
explicit unordered_map(allocator_type const& a)
|
||||
: table_(boost::unordered_detail::default_initial_bucket_count,
|
||||
: table_(boost::unordered_detail::default_bucket_count,
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
unordered_map(unordered_map const& other, allocator_type const& a)
|
||||
: table_(other.table_, a)
|
||||
: table_(other.table_, a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_map(InputIterator f, InputIterator l)
|
||||
: table_(boost::unordered_detail::initial_size(f, l), hasher(), key_equal(), allocator_type())
|
||||
template <class InputIt>
|
||||
unordered_map(InputIt f, InputIt l)
|
||||
: table_(boost::unordered_detail::initial_size(f, l),
|
||||
hasher(), key_equal(), allocator_type())
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_map(InputIterator f, InputIterator l,
|
||||
template <class InputIt>
|
||||
unordered_map(InputIt f, InputIt l,
|
||||
size_type n,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal())
|
||||
: table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, allocator_type())
|
||||
: table_(boost::unordered_detail::initial_size(f, l, n),
|
||||
hf, eql, allocator_type())
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_map(InputIterator f, InputIterator l,
|
||||
template <class InputIt>
|
||||
unordered_map(InputIt f, InputIt l,
|
||||
size_type n,
|
||||
const hasher &hf,
|
||||
const key_equal &eql,
|
||||
const allocator_type &a)
|
||||
: table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, a)
|
||||
: table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, a)
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
@ -148,12 +160,12 @@ namespace boost
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS)
|
||||
unordered_map(unordered_map&& other)
|
||||
: table_(other.table_, boost::unordered_detail::move_tag())
|
||||
: table_(other.table_, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
unordered_map(unordered_map&& other, allocator_type const& a)
|
||||
: table_(other.table_, a, boost::unordered_detail::move_tag())
|
||||
: table_(other.table_, a, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
@ -163,8 +175,10 @@ namespace boost
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_map(boost::unordered_detail::move_from<unordered_map<Key, T, Hash, Pred, Alloc> > other)
|
||||
: table_(other.source.table_, boost::unordered_detail::move_tag())
|
||||
unordered_map(boost::unordered_detail::move_from<
|
||||
unordered_map<Key, T, Hash, Pred, Alloc>
|
||||
> other)
|
||||
: table_(other.source.table_, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
@ -179,11 +193,13 @@ namespace boost
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
unordered_map(std::initializer_list<value_type> list,
|
||||
size_type n = boost::unordered_detail::default_initial_bucket_count,
|
||||
size_type n = boost::unordered_detail::default_bucket_count,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: table_(boost::unordered_detail::initial_size(list.begin(), list.end(), n), hf, eql, allocator_type())
|
||||
: table_(boost::unordered_detail::initial_size(
|
||||
list.begin(), list.end(), n),
|
||||
hf, eql, allocator_type())
|
||||
{
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
@ -263,7 +279,8 @@ namespace boost
|
||||
template <class... Args>
|
||||
iterator emplace_hint(const_iterator hint, Args&&... args)
|
||||
{
|
||||
return iterator(table_.emplace_hint(get(hint), std::forward<Args>(args)...));
|
||||
return iterator(
|
||||
table_.emplace_hint(get(hint), std::forward<Args>(args)...));
|
||||
}
|
||||
#else
|
||||
|
||||
@ -273,35 +290,36 @@ namespace boost
|
||||
table_.emplace(v));
|
||||
}
|
||||
|
||||
iterator emplace_hint(const_iterator hint, value_type const& v = value_type())
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
value_type const& v = value_type())
|
||||
{
|
||||
return iterator(table_.emplace_hint(get(hint), v));
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
std::pair<iterator, bool> emplace( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return boost::unordered_detail::pair_cast<iterator, bool>( \
|
||||
table_.emplace( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
)); \
|
||||
} \
|
||||
\
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
iterator emplace_hint(const_iterator hint, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return iterator(table_.emplace_hint(get(hint), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
)); \
|
||||
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
std::pair<iterator, bool> emplace( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return boost::unordered_detail::pair_cast<iterator, bool>( \
|
||||
table_.emplace( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
)); \
|
||||
} \
|
||||
\
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
iterator emplace_hint(const_iterator hint, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return iterator(table_.emplace_hint(get(hint), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
)); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
@ -322,8 +340,8 @@ namespace boost
|
||||
return iterator(table_.emplace_hint(get(hint), obj));
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
void insert(InputIterator first, InputIterator last)
|
||||
template <class InputIt>
|
||||
void insert(InputIt first, InputIt last)
|
||||
{
|
||||
table_.insert_range(first, last);
|
||||
}
|
||||
@ -400,14 +418,16 @@ namespace boost
|
||||
std::pair<iterator, iterator>
|
||||
equal_range(const key_type& k)
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<iterator, iterator>(
|
||||
return boost::unordered_detail::pair_cast<
|
||||
iterator, iterator>(
|
||||
table_.equal_range(k));
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const key_type& k) const
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
|
||||
return boost::unordered_detail::pair_cast<
|
||||
const_iterator, const_iterator>(
|
||||
table_.equal_range(k));
|
||||
}
|
||||
|
||||
@ -415,7 +435,7 @@ namespace boost
|
||||
|
||||
size_type bucket_count() const
|
||||
{
|
||||
return table_.bucket_count();
|
||||
return table_.bucket_count_;
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const
|
||||
@ -443,14 +463,14 @@ namespace boost
|
||||
return const_local_iterator(table_.bucket_begin(n));
|
||||
}
|
||||
|
||||
local_iterator end(size_type n)
|
||||
local_iterator end(size_type)
|
||||
{
|
||||
return local_iterator(table_.bucket_end(n));
|
||||
return local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator end(size_type n) const
|
||||
const_local_iterator end(size_type) const
|
||||
{
|
||||
return const_local_iterator(table_.bucket_end(n));
|
||||
return const_local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator cbegin(size_type n) const
|
||||
@ -458,9 +478,9 @@ namespace boost
|
||||
return const_local_iterator(table_.bucket_begin(n));
|
||||
}
|
||||
|
||||
const_local_iterator cend(size_type n) const
|
||||
const_local_iterator cend(size_type) const
|
||||
{
|
||||
return const_local_iterator(table_.bucket_end(n));
|
||||
return const_local_iterator();
|
||||
}
|
||||
|
||||
// hash policy
|
||||
@ -486,8 +506,10 @@ namespace boost
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
||||
friend bool operator==<Key, T, Hash, Pred, Alloc>(unordered_map const&, unordered_map const&);
|
||||
friend bool operator!=<Key, T, Hash, Pred, Alloc>(unordered_map const&, unordered_map const&);
|
||||
friend bool operator==<Key, T, Hash, Pred, Alloc>(
|
||||
unordered_map const&, unordered_map const&);
|
||||
friend bool operator!=<Key, T, Hash, Pred, Alloc>(
|
||||
unordered_map const&, unordered_map const&);
|
||||
#endif
|
||||
}; // class template unordered_map
|
||||
|
||||
@ -528,31 +550,40 @@ namespace boost
|
||||
private:
|
||||
#endif
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::unordered_detail::rebind_wrap<allocator_type, value_type>::type
|
||||
boost::unordered_detail::rebind_wrap<
|
||||
allocator_type, value_type>::type
|
||||
value_allocator;
|
||||
|
||||
typedef boost::unordered_detail::hash_equivalent_table<Hash, Pred, value_allocator,
|
||||
boost::unordered_detail::map_extractor> table;
|
||||
typedef boost::unordered_detail::hash_equivalent_table<Hash, Pred,
|
||||
value_allocator, boost::unordered_detail::map_extractor> table;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base;
|
||||
|
||||
public:
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::pointer pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::const_pointer const_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::reference reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::const_reference const_reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::pointer pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::const_pointer const_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::reference reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::const_reference const_reference;
|
||||
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef boost::unordered_detail::hash_const_local_iterator<
|
||||
value_allocator, boost::unordered_detail::grouped> const_local_iterator;
|
||||
value_allocator, boost::unordered_detail::grouped>
|
||||
const_local_iterator;
|
||||
typedef boost::unordered_detail::hash_local_iterator<
|
||||
value_allocator, boost::unordered_detail::grouped> local_iterator;
|
||||
value_allocator, boost::unordered_detail::grouped>
|
||||
local_iterator;
|
||||
typedef boost::unordered_detail::hash_const_iterator<
|
||||
value_allocator, boost::unordered_detail::grouped> const_iterator;
|
||||
value_allocator, boost::unordered_detail::grouped>
|
||||
const_iterator;
|
||||
typedef boost::unordered_detail::hash_iterator<
|
||||
value_allocator, boost::unordered_detail::grouped> iterator;
|
||||
value_allocator, boost::unordered_detail::grouped>
|
||||
iterator;
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
||||
private:
|
||||
@ -571,7 +602,7 @@ namespace boost
|
||||
// construct/destroy/copy
|
||||
|
||||
explicit unordered_multimap(
|
||||
size_type n = boost::unordered_detail::default_initial_bucket_count,
|
||||
size_type n = boost::unordered_detail::default_bucket_count,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
@ -580,35 +611,38 @@ namespace boost
|
||||
}
|
||||
|
||||
explicit unordered_multimap(allocator_type const& a)
|
||||
: table_(boost::unordered_detail::default_initial_bucket_count,
|
||||
: table_(boost::unordered_detail::default_bucket_count,
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
unordered_multimap(unordered_multimap const& other, allocator_type const& a)
|
||||
: table_(other.table_, a)
|
||||
unordered_multimap(unordered_multimap const& other,
|
||||
allocator_type const& a)
|
||||
: table_(other.table_, a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_multimap(InputIterator f, InputIterator l)
|
||||
: table_(boost::unordered_detail::initial_size(f, l), hasher(), key_equal(), allocator_type())
|
||||
template <class InputIt>
|
||||
unordered_multimap(InputIt f, InputIt l)
|
||||
: table_(boost::unordered_detail::initial_size(f, l),
|
||||
hasher(), key_equal(), allocator_type())
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_multimap(InputIterator f, InputIterator l,
|
||||
template <class InputIt>
|
||||
unordered_multimap(InputIt f, InputIt l,
|
||||
size_type n,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal())
|
||||
: table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, allocator_type())
|
||||
: table_(boost::unordered_detail::initial_size(f, l, n),
|
||||
hf, eql, allocator_type())
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_multimap(InputIterator f, InputIterator l,
|
||||
template <class InputIt>
|
||||
unordered_multimap(InputIt f, InputIt l,
|
||||
size_type n,
|
||||
const hasher &hf,
|
||||
const key_equal &eql,
|
||||
@ -622,12 +656,12 @@ namespace boost
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS)
|
||||
unordered_multimap(unordered_multimap&& other)
|
||||
: table_(other.table_, boost::unordered_detail::move_tag())
|
||||
: table_(other.table_, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
unordered_multimap(unordered_multimap&& other, allocator_type const& a)
|
||||
: table_(other.table_, a, boost::unordered_detail::move_tag())
|
||||
: table_(other.table_, a, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
@ -637,8 +671,10 @@ namespace boost
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_multimap(boost::unordered_detail::move_from<unordered_multimap<Key, T, Hash, Pred, Alloc> > other)
|
||||
: table_(other.source.table_, boost::unordered_detail::move_tag())
|
||||
unordered_multimap(boost::unordered_detail::move_from<
|
||||
unordered_multimap<Key, T, Hash, Pred, Alloc>
|
||||
> other)
|
||||
: table_(other.source.table_, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
@ -653,11 +689,13 @@ namespace boost
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
unordered_multimap(std::initializer_list<value_type> list,
|
||||
size_type n = boost::unordered_detail::default_initial_bucket_count,
|
||||
size_type n = boost::unordered_detail::default_bucket_count,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: table_(boost::unordered_detail::initial_size(list.begin(), list.end(), n), hf, eql, allocator_type())
|
||||
: table_(boost::unordered_detail::initial_size(
|
||||
list.begin(), list.end(), n),
|
||||
hf, eql, allocator_type())
|
||||
{
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
@ -736,7 +774,8 @@ namespace boost
|
||||
template <class... Args>
|
||||
iterator emplace_hint(const_iterator hint, Args&&... args)
|
||||
{
|
||||
return iterator(table_.emplace_hint(get(hint), std::forward<Args>(args)...));
|
||||
return iterator(table_.emplace_hint(get(hint),
|
||||
std::forward<Args>(args)...));
|
||||
}
|
||||
#else
|
||||
|
||||
@ -745,36 +784,37 @@ namespace boost
|
||||
return iterator(table_.emplace(v));
|
||||
}
|
||||
|
||||
iterator emplace_hint(const_iterator hint, value_type const& v = value_type())
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
value_type const& v = value_type())
|
||||
{
|
||||
return iterator(table_.emplace_hint(get(hint), v));
|
||||
}
|
||||
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
iterator emplace( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return iterator( \
|
||||
table_.emplace( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
)); \
|
||||
} \
|
||||
\
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
iterator emplace_hint(const_iterator hint, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return iterator(table_.emplace_hint(get(hint), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
)); \
|
||||
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
iterator emplace( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return iterator( \
|
||||
table_.emplace( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
)); \
|
||||
} \
|
||||
\
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
iterator emplace_hint(const_iterator hint, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return iterator(table_.emplace_hint(get(hint), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
)); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
@ -794,8 +834,8 @@ namespace boost
|
||||
return iterator(table_.emplace_hint(get(hint), obj));
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
void insert(InputIterator first, InputIterator last)
|
||||
template <class InputIt>
|
||||
void insert(InputIt first, InputIt last)
|
||||
{
|
||||
table_.insert_range(first, last);
|
||||
}
|
||||
@ -857,14 +897,16 @@ namespace boost
|
||||
std::pair<iterator, iterator>
|
||||
equal_range(const key_type& k)
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<iterator, iterator>(
|
||||
return boost::unordered_detail::pair_cast<
|
||||
iterator, iterator>(
|
||||
table_.equal_range(k));
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const key_type& k) const
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
|
||||
return boost::unordered_detail::pair_cast<
|
||||
const_iterator, const_iterator>(
|
||||
table_.equal_range(k));
|
||||
}
|
||||
|
||||
@ -872,7 +914,7 @@ namespace boost
|
||||
|
||||
size_type bucket_count() const
|
||||
{
|
||||
return table_.bucket_count();
|
||||
return table_.bucket_count_;
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const
|
||||
@ -900,14 +942,14 @@ namespace boost
|
||||
return const_local_iterator(table_.bucket_begin(n));
|
||||
}
|
||||
|
||||
local_iterator end(size_type n)
|
||||
local_iterator end(size_type)
|
||||
{
|
||||
return local_iterator(table_.bucket_end(n));
|
||||
return local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator end(size_type n) const
|
||||
const_local_iterator end(size_type) const
|
||||
{
|
||||
return const_local_iterator(table_.bucket_end(n));
|
||||
return const_local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator cbegin(size_type n) const
|
||||
@ -915,9 +957,9 @@ namespace boost
|
||||
return const_local_iterator(table_.bucket_begin(n));
|
||||
}
|
||||
|
||||
const_local_iterator cend(size_type n) const
|
||||
const_local_iterator cend(size_type) const
|
||||
{
|
||||
return const_local_iterator(table_.bucket_end(n));
|
||||
return const_local_iterator();
|
||||
}
|
||||
|
||||
// hash policy
|
||||
@ -943,8 +985,10 @@ namespace boost
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
||||
friend bool operator==<Key, T, Hash, Pred, Alloc>(unordered_multimap const&, unordered_multimap const&);
|
||||
friend bool operator!=<Key, T, Hash, Pred, Alloc>(unordered_multimap const&, unordered_multimap const&);
|
||||
friend bool operator==<Key, T, Hash, Pred, Alloc>(
|
||||
unordered_multimap const&, unordered_multimap const&);
|
||||
friend bool operator!=<Key, T, Hash, Pred, Alloc>(
|
||||
unordered_multimap const&, unordered_multimap const&);
|
||||
#endif
|
||||
}; // class template unordered_multimap
|
||||
|
||||
|
@ -16,7 +16,8 @@
|
||||
#include <boost/unordered/unordered_set_fwd.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/unordered/detail/allocator_helpers.hpp>
|
||||
#include <boost/unordered/detail/insert.hpp>
|
||||
#include <boost/unordered/detail/equivalent.hpp>
|
||||
#include <boost/unordered/detail/unique.hpp>
|
||||
|
||||
#if !defined(BOOST_HAS_RVALUE_REFS)
|
||||
#include <boost/unordered/detail/move.hpp>
|
||||
@ -53,27 +54,34 @@ namespace boost
|
||||
#endif
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::unordered_detail::rebind_wrap<allocator_type, value_type>::type
|
||||
boost::unordered_detail::rebind_wrap<
|
||||
allocator_type, value_type>::type
|
||||
value_allocator;
|
||||
|
||||
typedef boost::unordered_detail::hash_unique_table<Hash, Pred, value_allocator,
|
||||
boost::unordered_detail::set_extractor> table;
|
||||
typedef boost::unordered_detail::hash_unique_table<Hash, Pred,
|
||||
value_allocator, boost::unordered_detail::set_extractor> table;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base;
|
||||
|
||||
public:
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::pointer pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::const_pointer const_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::reference reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::const_reference const_reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::pointer pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::const_pointer const_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::reference reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::const_reference const_reference;
|
||||
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef boost::unordered_detail::hash_const_local_iterator<
|
||||
value_allocator, boost::unordered_detail::ungrouped> const_local_iterator;
|
||||
value_allocator, boost::unordered_detail::ungrouped>
|
||||
const_local_iterator;
|
||||
typedef boost::unordered_detail::hash_const_iterator<
|
||||
value_allocator, boost::unordered_detail::ungrouped> const_iterator;
|
||||
value_allocator, boost::unordered_detail::ungrouped>
|
||||
const_iterator;
|
||||
typedef const_local_iterator local_iterator;
|
||||
typedef const_iterator iterator;
|
||||
|
||||
@ -94,47 +102,49 @@ namespace boost
|
||||
// construct/destroy/copy
|
||||
|
||||
explicit unordered_set(
|
||||
size_type n = boost::unordered_detail::default_initial_bucket_count,
|
||||
size_type n = boost::unordered_detail::default_bucket_count,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: table_(n, hf, eql, a)
|
||||
: table_(n, hf, eql, a)
|
||||
{
|
||||
}
|
||||
|
||||
explicit unordered_set(allocator_type const& a)
|
||||
: table_(boost::unordered_detail::default_initial_bucket_count,
|
||||
: table_(boost::unordered_detail::default_bucket_count,
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
unordered_set(unordered_set const& other, allocator_type const& a)
|
||||
: table_(other.table_, a)
|
||||
: table_(other.table_, a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_set(InputIterator f, InputIterator l)
|
||||
: table_(boost::unordered_detail::initial_size(f, l), hasher(), key_equal(), allocator_type())
|
||||
template <class InputIt>
|
||||
unordered_set(InputIt f, InputIt l)
|
||||
: table_(boost::unordered_detail::initial_size(f, l),
|
||||
hasher(), key_equal(), allocator_type())
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_set(InputIterator f, InputIterator l, size_type n,
|
||||
template <class InputIt>
|
||||
unordered_set(InputIt f, InputIt l, size_type n,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal())
|
||||
: table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, allocator_type())
|
||||
: table_(boost::unordered_detail::initial_size(f, l, n),
|
||||
hf, eql, allocator_type())
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_set(InputIterator f, InputIterator l, size_type n,
|
||||
template <class InputIt>
|
||||
unordered_set(InputIt f, InputIt l, size_type n,
|
||||
const hasher &hf,
|
||||
const key_equal &eql,
|
||||
const allocator_type &a)
|
||||
: table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, a)
|
||||
: table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, a)
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
@ -143,12 +153,12 @@ namespace boost
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS)
|
||||
unordered_set(unordered_set&& other)
|
||||
: table_(other.table_, boost::unordered_detail::move_tag())
|
||||
: table_(other.table_, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
unordered_set(unordered_set&& other, allocator_type const& a)
|
||||
: table_(other.table_, a, boost::unordered_detail::move_tag())
|
||||
: table_(other.table_, a, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
@ -158,8 +168,10 @@ namespace boost
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_set(boost::unordered_detail::move_from<unordered_set<Value, Hash, Pred, Alloc> > other)
|
||||
: table_(other.source.table_, boost::unordered_detail::move_tag())
|
||||
unordered_set(boost::unordered_detail::move_from<
|
||||
unordered_set<Value, Hash, Pred, Alloc>
|
||||
> other)
|
||||
: table_(other.source.table_, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
@ -174,11 +186,13 @@ namespace boost
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
unordered_set(std::initializer_list<value_type> list,
|
||||
size_type n = boost::unordered_detail::default_initial_bucket_count,
|
||||
size_type n = boost::unordered_detail::default_bucket_count,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: table_(boost::unordered_detail::initial_size(list.begin(), list.end(), n), hf, eql, allocator_type())
|
||||
: table_(boost::unordered_detail::initial_size(
|
||||
list.begin(), list.end(), n),
|
||||
hf, eql, allocator_type())
|
||||
{
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
@ -269,35 +283,36 @@ namespace boost
|
||||
table_.emplace(v));
|
||||
}
|
||||
|
||||
iterator emplace_hint(const_iterator hint, value_type const& v = value_type())
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
value_type const& v = value_type())
|
||||
{
|
||||
return iterator(table_.emplace_hint(get(hint), v));
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
std::pair<iterator, bool> emplace( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return boost::unordered_detail::pair_cast<iterator, bool>( \
|
||||
table_.emplace( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
)); \
|
||||
} \
|
||||
\
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
iterator emplace_hint(const_iterator hint, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return iterator(table_.emplace_hint(get(hint), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
)); \
|
||||
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
std::pair<iterator, bool> emplace( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return boost::unordered_detail::pair_cast<iterator, bool>( \
|
||||
table_.emplace( \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
)); \
|
||||
} \
|
||||
\
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
iterator emplace_hint(const_iterator hint, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return iterator(table_.emplace_hint(get(hint), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
)); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
@ -318,8 +333,8 @@ namespace boost
|
||||
return iterator(table_.emplace_hint(get(hint), obj));
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
void insert(InputIterator first, InputIterator last)
|
||||
template <class InputIt>
|
||||
void insert(InputIt first, InputIt last)
|
||||
{
|
||||
table_.insert_range(first, last);
|
||||
}
|
||||
@ -376,7 +391,8 @@ namespace boost
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const key_type& k) const
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
|
||||
return boost::unordered_detail::pair_cast<
|
||||
const_iterator, const_iterator>(
|
||||
table_.equal_range(k));
|
||||
}
|
||||
|
||||
@ -384,7 +400,7 @@ namespace boost
|
||||
|
||||
size_type bucket_count() const
|
||||
{
|
||||
return table_.bucket_count();
|
||||
return table_.bucket_count_;
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const
|
||||
@ -412,14 +428,14 @@ namespace boost
|
||||
return const_local_iterator(table_.bucket_begin(n));
|
||||
}
|
||||
|
||||
local_iterator end(size_type n)
|
||||
local_iterator end(size_type)
|
||||
{
|
||||
return local_iterator(table_.bucket_end(n));
|
||||
return local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator end(size_type n) const
|
||||
const_local_iterator end(size_type) const
|
||||
{
|
||||
return const_local_iterator(table_.bucket_end(n));
|
||||
return const_local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator cbegin(size_type n) const
|
||||
@ -427,9 +443,9 @@ namespace boost
|
||||
return const_local_iterator(table_.bucket_begin(n));
|
||||
}
|
||||
|
||||
const_local_iterator cend(size_type n) const
|
||||
const_local_iterator cend(size_type) const
|
||||
{
|
||||
return const_local_iterator(table_.bucket_end(n));
|
||||
return const_local_iterator();
|
||||
}
|
||||
|
||||
// hash policy
|
||||
@ -455,8 +471,10 @@ namespace boost
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
||||
friend bool operator==<Value, Hash, Pred, Alloc>(unordered_set const&, unordered_set const&);
|
||||
friend bool operator!=<Value, Hash, Pred, Alloc>(unordered_set const&, unordered_set const&);
|
||||
friend bool operator==<Value, Hash, Pred, Alloc>(
|
||||
unordered_set const&, unordered_set const&);
|
||||
friend bool operator!=<Value, Hash, Pred, Alloc>(
|
||||
unordered_set const&, unordered_set const&);
|
||||
#endif
|
||||
}; // class template unordered_set
|
||||
|
||||
@ -496,27 +514,34 @@ namespace boost
|
||||
private:
|
||||
#endif
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::unordered_detail::rebind_wrap<allocator_type, value_type>::type
|
||||
boost::unordered_detail::rebind_wrap<
|
||||
allocator_type, value_type>::type
|
||||
value_allocator;
|
||||
|
||||
typedef boost::unordered_detail::hash_equivalent_table<Hash, Pred, value_allocator,
|
||||
boost::unordered_detail::set_extractor> table;
|
||||
typedef boost::unordered_detail::hash_equivalent_table<Hash, Pred,
|
||||
value_allocator, boost::unordered_detail::set_extractor> table;
|
||||
typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base;
|
||||
|
||||
public:
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::pointer pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::const_pointer const_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::reference reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME value_allocator::const_reference const_reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::pointer pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::const_pointer const_pointer;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::reference reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
value_allocator::const_reference const_reference;
|
||||
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef boost::unordered_detail::hash_const_local_iterator<
|
||||
value_allocator, boost::unordered_detail::grouped> const_local_iterator;
|
||||
value_allocator, boost::unordered_detail::grouped>
|
||||
const_local_iterator;
|
||||
typedef boost::unordered_detail::hash_const_iterator<
|
||||
value_allocator, boost::unordered_detail::grouped> const_iterator;
|
||||
value_allocator, boost::unordered_detail::grouped>
|
||||
const_iterator;
|
||||
typedef const_local_iterator local_iterator;
|
||||
typedef const_iterator iterator;
|
||||
|
||||
@ -537,7 +562,7 @@ namespace boost
|
||||
// construct/destroy/copy
|
||||
|
||||
explicit unordered_multiset(
|
||||
size_type n = boost::unordered_detail::default_initial_bucket_count,
|
||||
size_type n = boost::unordered_detail::default_bucket_count,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
@ -546,34 +571,37 @@ namespace boost
|
||||
}
|
||||
|
||||
explicit unordered_multiset(allocator_type const& a)
|
||||
: table_(boost::unordered_detail::default_initial_bucket_count,
|
||||
: table_(boost::unordered_detail::default_bucket_count,
|
||||
hasher(), key_equal(), a)
|
||||
{
|
||||
}
|
||||
|
||||
unordered_multiset(unordered_multiset const& other, allocator_type const& a)
|
||||
: table_(other.table_, a)
|
||||
unordered_multiset(unordered_multiset const& other,
|
||||
allocator_type const& a)
|
||||
: table_(other.table_, a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_multiset(InputIterator f, InputIterator l)
|
||||
: table_(boost::unordered_detail::initial_size(f, l), hasher(), key_equal(), allocator_type())
|
||||
template <class InputIt>
|
||||
unordered_multiset(InputIt f, InputIt l)
|
||||
: table_(boost::unordered_detail::initial_size(f, l),
|
||||
hasher(), key_equal(), allocator_type())
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_multiset(InputIterator f, InputIterator l, size_type n,
|
||||
template <class InputIt>
|
||||
unordered_multiset(InputIt f, InputIt l, size_type n,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal())
|
||||
: table_(boost::unordered_detail::initial_size(f, l, n), hf, eql, allocator_type())
|
||||
: table_(boost::unordered_detail::initial_size(f, l, n),
|
||||
hf, eql, allocator_type())
|
||||
{
|
||||
table_.insert_range(f, l);
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
unordered_multiset(InputIterator f, InputIterator l, size_type n,
|
||||
template <class InputIt>
|
||||
unordered_multiset(InputIt f, InputIt l, size_type n,
|
||||
const hasher &hf,
|
||||
const key_equal &eql,
|
||||
const allocator_type &a)
|
||||
@ -586,12 +614,12 @@ namespace boost
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS)
|
||||
unordered_multiset(unordered_multiset&& other)
|
||||
: table_(other.table_, boost::unordered_detail::move_tag())
|
||||
: table_(other.table_, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
unordered_multiset(unordered_multiset&& other, allocator_type const& a)
|
||||
: table_(other.table_, a, boost::unordered_detail::move_tag())
|
||||
: table_(other.table_, a, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
@ -601,8 +629,10 @@ namespace boost
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_multiset(boost::unordered_detail::move_from<unordered_multiset<Value, Hash, Pred, Alloc> > other)
|
||||
: table_(other.source.table_, boost::unordered_detail::move_tag())
|
||||
unordered_multiset(boost::unordered_detail::move_from<
|
||||
unordered_multiset<Value, Hash, Pred, Alloc>
|
||||
> other)
|
||||
: table_(other.source.table_, boost::unordered_detail::move_tag())
|
||||
{
|
||||
}
|
||||
|
||||
@ -617,11 +647,13 @@ namespace boost
|
||||
|
||||
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
|
||||
unordered_multiset(std::initializer_list<value_type> list,
|
||||
size_type n = boost::unordered_detail::default_initial_bucket_count,
|
||||
size_type n = boost::unordered_detail::default_bucket_count,
|
||||
const hasher &hf = hasher(),
|
||||
const key_equal &eql = key_equal(),
|
||||
const allocator_type &a = allocator_type())
|
||||
: table_(boost::unordered_detail::initial_size(list.begin(), list.end(), n), hf, eql, allocator_type())
|
||||
: table_(boost::unordered_detail::initial_size(
|
||||
list.begin(), list.end(), n),
|
||||
hf, eql, allocator_type())
|
||||
{
|
||||
table_.insert_range(list.begin(), list.end());
|
||||
}
|
||||
@ -700,7 +732,8 @@ namespace boost
|
||||
template <class... Args>
|
||||
iterator emplace_hint(const_iterator hint, Args&&... args)
|
||||
{
|
||||
return iterator(table_.emplace_hint(get(hint), std::forward<Args>(args)...));
|
||||
return iterator(table_.emplace_hint(get(hint),
|
||||
std::forward<Args>(args)...));
|
||||
}
|
||||
#else
|
||||
|
||||
@ -709,33 +742,34 @@ namespace boost
|
||||
return iterator(table_.emplace(v));
|
||||
}
|
||||
|
||||
iterator emplace_hint(const_iterator hint, value_type const& v = value_type())
|
||||
iterator emplace_hint(const_iterator hint,
|
||||
value_type const& v = value_type())
|
||||
{
|
||||
return iterator(table_.emplace_hint(get(hint), v));
|
||||
}
|
||||
|
||||
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
iterator emplace( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return iterator( \
|
||||
table_.emplace(BOOST_UNORDERED_CALL_PARAMS(z, n))); \
|
||||
} \
|
||||
\
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
iterator emplace_hint(const_iterator hint, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return iterator(table_.emplace_hint(get(hint), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
)); \
|
||||
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
iterator emplace( \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return iterator( \
|
||||
table_.emplace(BOOST_UNORDERED_CALL_PARAMS(z, n))); \
|
||||
} \
|
||||
\
|
||||
template < \
|
||||
BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \
|
||||
> \
|
||||
iterator emplace_hint(const_iterator hint, \
|
||||
BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \
|
||||
) \
|
||||
{ \
|
||||
return iterator(table_.emplace_hint(get(hint), \
|
||||
BOOST_UNORDERED_CALL_PARAMS(z, n) \
|
||||
)); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
|
||||
@ -755,8 +789,8 @@ namespace boost
|
||||
return iterator(table_.emplace_hint(get(hint), obj));
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
void insert(InputIterator first, InputIterator last)
|
||||
template <class InputIt>
|
||||
void insert(InputIt first, InputIt last)
|
||||
{
|
||||
table_.insert_range(first, last);
|
||||
}
|
||||
@ -813,7 +847,8 @@ namespace boost
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const key_type& k) const
|
||||
{
|
||||
return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
|
||||
return boost::unordered_detail::pair_cast<
|
||||
const_iterator, const_iterator>(
|
||||
table_.equal_range(k));
|
||||
}
|
||||
|
||||
@ -821,7 +856,7 @@ namespace boost
|
||||
|
||||
size_type bucket_count() const
|
||||
{
|
||||
return table_.bucket_count();
|
||||
return table_.bucket_count_;
|
||||
}
|
||||
|
||||
size_type max_bucket_count() const
|
||||
@ -849,14 +884,14 @@ namespace boost
|
||||
return const_local_iterator(table_.bucket_begin(n));
|
||||
}
|
||||
|
||||
local_iterator end(size_type n)
|
||||
local_iterator end(size_type)
|
||||
{
|
||||
return local_iterator(table_.bucket_end(n));
|
||||
return local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator end(size_type n) const
|
||||
const_local_iterator end(size_type) const
|
||||
{
|
||||
return const_local_iterator(table_.bucket_end(n));
|
||||
return const_local_iterator();
|
||||
}
|
||||
|
||||
const_local_iterator cbegin(size_type n) const
|
||||
@ -864,9 +899,9 @@ namespace boost
|
||||
return const_local_iterator(table_.bucket_begin(n));
|
||||
}
|
||||
|
||||
const_local_iterator cend(size_type n) const
|
||||
const_local_iterator cend(size_type) const
|
||||
{
|
||||
return const_local_iterator(table_.bucket_end(n));
|
||||
return const_local_iterator();
|
||||
}
|
||||
|
||||
// hash policy
|
||||
@ -892,8 +927,10 @@ namespace boost
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
|
||||
friend bool operator==<Value, Hash, Pred, Alloc>(unordered_multiset const&, unordered_multiset const&);
|
||||
friend bool operator!=<Value, Hash, Pred, Alloc>(unordered_multiset const&, unordered_multiset const&);
|
||||
friend bool operator==<Value, Hash, Pred, Alloc>(
|
||||
unordered_multiset const&, unordered_multiset const&);
|
||||
friend bool operator!=<Value, Hash, Pred, Alloc>(
|
||||
unordered_multiset const&, unordered_multiset const&);
|
||||
#endif
|
||||
}; // class template unordered_multiset
|
||||
|
||||
|
@ -21,14 +21,17 @@ namespace test
|
||||
|
||||
namespace test_detail
|
||||
{
|
||||
template <typename T> struct list_node;
|
||||
template <typename T> class list_node;
|
||||
template <typename T> class list_data;
|
||||
template <typename T> class list_iterator;
|
||||
template <typename T> class list_const_iterator;
|
||||
|
||||
template <typename T>
|
||||
struct list_node
|
||||
class list_node
|
||||
{
|
||||
list_node(list_node const&);
|
||||
list_node& operator=(list_node const&);
|
||||
public:
|
||||
T value_;
|
||||
list_node* next_;
|
||||
|
||||
@ -243,8 +246,8 @@ namespace test
|
||||
node** merge_adjacent_ranges(node** first, node** second,
|
||||
node** third, Less less)
|
||||
{
|
||||
while(true) {
|
||||
while(true) {
|
||||
for(;;) {
|
||||
for(;;) {
|
||||
if(first == second) return third;
|
||||
if(less((*second)->value_, (*first)->value_)) break;
|
||||
first = &(*first)->next_;
|
||||
@ -256,7 +259,7 @@ namespace test
|
||||
// Since the two ranges we just swapped, the order is now:
|
||||
// first...third...second
|
||||
|
||||
while(true) {
|
||||
for(;;) {
|
||||
if(first == third) return second;
|
||||
if(!less((*first)->value_, (*third)->value_)) break;
|
||||
first = &(*first)->next_;
|
||||
|
@ -116,7 +116,7 @@ bool compare(Range1 const& x, Range2 const& y)
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
bool general_erase_range_test(Container& x, int start, int end)
|
||||
bool general_erase_range_test(Container& x, std::size_t start, std::size_t end)
|
||||
{
|
||||
collide_list l(x.begin(), x.end());
|
||||
l.erase(boost::next(l.begin(), start), boost::next(l.begin(), end));
|
||||
|
@ -10,7 +10,7 @@ struct foo {
|
||||
|
||||
template <class T>
|
||||
template <class U>
|
||||
bool foo<T>::bar(U x) { return x; }
|
||||
bool foo<T>::bar(U x) { return x ? true : false; }
|
||||
|
||||
int main() {
|
||||
foo<int> x;
|
||||
|
Loading…
x
Reference in New Issue
Block a user