Import my latest version of the unordered associative containers.

Several changes:

- Makes insert meet its exception specification (but needs some refactoring).
- Some Borland work arounds, but not all there yet, maybe never will be.
- Some extra doxygen comments, but not nearly enough.
- Possibly other things that I'm too lazy to look up.


[SVN r2642]
This commit is contained in:
Daniel James
2005-06-20 21:55:28 +00:00
parent f6a60033e3
commit f3b00bc938
3 changed files with 270 additions and 148 deletions

View File

@ -10,35 +10,58 @@
# pragma once
#endif
#include <boost/detail/allocator_utilities.hpp>
#include <boost/config.hpp>
#if (defined(BOOST_NO_STD_ALLOCATOR) || defined(BOOST_DINKUMWARE_STDLIB)) \
&& !defined(__BORLANDC__)
# define BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES
#endif
#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
# include <boost/detail/allocator_utilities.hpp>
#endif
#include <boost/mpl/aux_/config/eti.hpp>
namespace boost {
namespace unordered_detail {
#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
template <class Alloc, class T>
struct rebind_wrap : ::boost::detail::allocator::rebind_to<Alloc, T> {};
#else
template <class Alloc, class T>
struct rebind_wrap
{
typedef BOOST_DEDUCED_TYPENAME
Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
type;
};
#endif
// Work around for Microsoft's ETI bug.
template <class Allocator> struct get_value_type
template <class Allocator> struct allocator_value_type
{
typedef typename Allocator::value_type type;
};
template <class Allocator> struct get_pointer
template <class Allocator> struct allocator_pointer
{
typedef typename Allocator::pointer type;
};
template <class Allocator> struct get_const_pointer
template <class Allocator> struct allocator_const_pointer
{
typedef typename Allocator::const_pointer type;
};
template <class Allocator> struct get_reference
template <class Allocator> struct allocator_reference
{
typedef typename Allocator::reference type;
};
template <class Allocator> struct get_const_reference
template <class Allocator> struct allocator_const_reference
{
typedef typename Allocator::const_reference type;
};
@ -46,31 +69,31 @@ namespace boost {
#if defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
template <>
struct get_value_type<int>
struct allocator_value_type<int>
{
typedef int type;
};
template <>
struct get_pointer<int>
struct allocator_pointer<int>
{
typedef int type;
};
template <>
struct get_const_pointer<int>
struct allocator_const_pointer<int>
{
typedef int type;
};
template <>
struct get_reference<int>
struct allocator_reference<int>
{
typedef int type;
};
template <>
struct get_const_reference<int>
struct allocator_const_reference<int>
{
typedef int type;
};
@ -80,7 +103,7 @@ namespace boost {
template <class Allocator>
struct allocator_constructor
{
typedef typename get_pointer<Allocator>::type pointer;
typedef typename allocator_pointer<Allocator>::type pointer;
Allocator& alloc_;
pointer ptr_;
@ -100,12 +123,20 @@ namespace boost {
ptr_ = pointer();
return p;
}
// no throw
pointer release()
{
pointer p = ptr_;
ptr_ = pointer();
return p;
}
};
template <class Allocator>
struct allocator_array_constructor
{
typedef typename get_pointer<Allocator>::type pointer;
typedef typename allocator_pointer<Allocator>::type pointer;
Allocator& alloc_;
pointer ptr_;
@ -149,4 +180,8 @@ namespace boost {
}
}
#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
# undef BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES
#endif
#endif

View File

@ -13,6 +13,10 @@
#ifndef BOOST_UNORDERED_DETAIL_HASH_TABLE_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_HASH_TABLE_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#include <cstddef>
@ -102,12 +106,18 @@ namespace boost {
typedef std::size_t size_type;
typedef Alloc value_allocator;
typedef typename boost::detail::allocator::rebind_to<Alloc, node>::type node_allocator;
typedef typename boost::detail::allocator::rebind_to<Alloc, bucket>::type bucket_allocator;
typedef typename get_value_type<Alloc>::type value_type;
typedef typename get_pointer<node_allocator>::type node_ptr;
typedef typename get_pointer<bucket_allocator>::type bucket_ptr;
typedef typename get_reference<value_allocator>::type reference;
typedef BOOST_DEDUCED_TYPENAME
boost::unordered_detail::rebind_wrap<Alloc, node>::type
node_allocator;
typedef BOOST_DEDUCED_TYPENAME
boost::unordered_detail::rebind_wrap<Alloc, bucket>::type
bucket_allocator;
typedef BOOST_DEDUCED_TYPENAME allocator_value_type<Alloc>::type value_type;
typedef BOOST_DEDUCED_TYPENAME allocator_pointer<node_allocator>::type node_ptr;
typedef BOOST_DEDUCED_TYPENAME allocator_pointer<bucket_allocator>::type bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME allocator_reference<value_allocator>::type reference;
#if defined(BOOST_UNORDERED_PARANOID)
// If the allocator has the expected pointer types I take some liberties.
@ -117,7 +127,7 @@ namespace boost {
boost::is_same<bucket_ptr, bucket*>
>::value));
typedef typename boost::mpl::if_c<
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
is_pointer_allocator, bucket_ptr, node_ptr>::type link_ptr;
#else
typedef bucket_ptr link_ptr;
@ -195,7 +205,7 @@ namespace boost {
}
template <class V>
node_ptr construct(V const& v)
void construct(V const& v)
{
assert(!ptr_);
value_allocated_ = bucket_allocated_ = false;
@ -209,12 +219,24 @@ namespace boost {
value_alloc_.construct(value_alloc_.address(
ptr_->value_), v);
value_allocated_ = true;
}
// no throw
link_ptr release()
{
node_ptr p = ptr_;
ptr_ = node_ptr();
return p;
return bucket_alloc_.address(*p);
}
};
#else
class node_constructor
: public allocator_constructor<node_allocator>
{
public:
node_constructor(node_allocator& n, bucket_allocator&)
: allocator_constructor<node_allocator>(n);
};
#endif
class local_iterator_base
@ -228,6 +250,11 @@ namespace boost {
explicit local_iterator_base(link_ptr n)
: node_pointer_(n) {}
bool not_finished() const
{
return node_pointer_;
}
bool operator==(local_iterator_base const& x) const
{
return node_pointer_ == x.node_pointer_;
@ -253,11 +280,10 @@ namespace boost {
// Erase Iterator
//
// This is an internal 'iterator' (not an STL iterator) which stores a
// pointer to the pointer to the current node. This is needed to remove
// a node from a bucket.
// This is an internal 'iterator' (not an STL iterator) which is
// used to erase or move a node.
//
// all no throw.
// All no throw.
class erase_iterator
{
@ -273,7 +299,7 @@ namespace boost {
prev_ptr = &(*prev_ptr)->next_;
}
operator bool() const
bool not_finished() const
{
return *prev_ptr;
}
@ -381,8 +407,7 @@ namespace boost {
if(buckets_[bucket_count_].next_) remove_end_marker();
for(size_type i = 0; i < bucket_count_; ++i)
delete_nodes(erase_iterator(buckets_ + i),
end(buckets_ + i));
delete_nodes(erase_iterator(buckets_ + i));
for(size_type i2 = 0; i2 < bucket_count_ + 1; ++i2)
bucket_alloc_.destroy(buckets_ + i2);
@ -401,10 +426,10 @@ namespace boost {
buckets_[bucket_count_].next_ = buckets_ + bucket_count_;
}
else {
// This seems very wasteful, but I can't think of a better way
// to create an end node and work with all allocators. Although,
// I might change it to do something different when
// typename node_allocator::pointer == node*.
// This seems very wasteful, but I can't think of a better
// way to create an end node and work with all allocators.
// Although, I might change it to do something different
// when typename node_allocator::pointer == node*.
buckets_[bucket_count_].next_ = node_alloc_.allocate(1);
}
#endif
@ -488,7 +513,7 @@ namespace boost {
return local_iterator_base(buckets_[n].next_);
}
local_iterator_base end(size_type n) const
local_iterator_base end(size_type) const
{
return local_iterator_base();
}
@ -498,11 +523,6 @@ namespace boost {
return local_iterator_base(b->next_);
}
local_iterator_base end(bucket_ptr b) const
{
return local_iterator_base();
}
// Bucket Size
// no throw
@ -510,8 +530,7 @@ namespace boost {
{
std::size_t count = 0;
local_iterator_base it1 = begin(n);
local_iterator_base it2 = end(n);
while(it1 != it2) {
while(it1.not_finished()) {
++count;
it1.increment();
}
@ -527,8 +546,8 @@ namespace boost {
erase_iterator get_for_erase(iterator_base r) const
{
erase_iterator it(r.bucket_);
local_iterator_base end(r.local());
while(it != end) it.next();
local_iterator_base pos(r.local());
while(it != pos) it.next();
return it;
}
@ -571,13 +590,9 @@ namespace boost {
// throws, strong exception-safety:
link_ptr construct_node(value_type const& v)
{
#if defined(BOOST_UNORDERED_PARANOID)
allocator_constructor<node_allocator> a(node_alloc_);
return a.construct(v);
#else
node_constructor a(node_alloc_, bucket_alloc_);
return bucket_alloc_.address(*a.construct(v));
#endif
a.construct(v);
return a.release();
}
// Create Node
@ -613,7 +628,7 @@ namespace boost {
link_ptr node = construct_node(v);
// Rest is no throw
if(position != end(base))
if(position.not_finished())
link_node(node, position);
else
link_node(node, base);
@ -640,7 +655,15 @@ namespace boost {
void delete_nodes(erase_iterator begin, local_iterator_base end)
{
while(begin != end) delete_node(begin);
while(begin != end) {
BOOST_ASSERT(begin.not_finished());
delete_node(begin);
}
}
void delete_nodes(erase_iterator begin)
{
while(begin.not_finished()) delete_node(begin);
}
// Clear
@ -657,8 +680,7 @@ namespace boost {
{
bucket_ptr end = buckets_ + bucket_count_;
while(cached_begin_bucket_ != end) {
delete_nodes(erase_iterator(cached_begin_bucket_),
this->end(cached_begin_bucket_));
delete_nodes(erase_iterator(cached_begin_bucket_));
++cached_begin_bucket_;
}
BOOST_ASSERT(!size_);
@ -697,10 +719,12 @@ namespace boost {
BOOST_ASSERT(!r1.bucket_->empty());
}
else {
delete_nodes(get_for_erase(r1), end(r1.bucket_));
BOOST_ASSERT(r1.bucket_ < r2.bucket_);
delete_nodes(get_for_erase(r1));
for(bucket_ptr i = r1.bucket_ + 1; i != r2.bucket_; ++i)
delete_nodes(erase_iterator(i), end(i));
delete_nodes(erase_iterator(i));
delete_nodes(erase_iterator(r2.bucket_), r2.local());
@ -749,28 +773,33 @@ namespace boost {
}
};
template <class ValueType, class Alloc>
struct hash_table_data_type
#if defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
template <>
class hash_table_data<int>
{
typedef typename boost::detail::allocator::rebind_to<Alloc, ValueType>::type
value_allocator;
typedef hash_table_data<value_allocator> type;
public:
typedef int size_type;
typedef int iterator_base;
};
#endif
template <class ValueType, class KeyType,
class Hash, class Pred,
class Alloc, bool EquivalentKeys>
class hash_table
: public hash_table_data_type<ValueType, Alloc>::type
: public hash_table_data<Alloc>
{
typedef typename hash_table_data_type<ValueType, Alloc>::type data;
typedef hash_table_data<Alloc> data;
typedef typename data::node_constructor node_constructor;
typedef typename data::link_ptr link_ptr;
public:
typedef typename data::value_allocator value_allocator;
typedef typename data::node_allocator node_allocator;
typedef typename data::bucket_ptr bucket_ptr;
typedef typename data::erase_iterator erase_iterator;
typedef BOOST_DEDUCED_TYPENAME data::value_allocator value_allocator;
typedef BOOST_DEDUCED_TYPENAME data::node_allocator node_allocator;
typedef BOOST_DEDUCED_TYPENAME data::bucket_ptr bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME data::erase_iterator erase_iterator;
// Type definitions
@ -782,8 +811,8 @@ namespace boost {
// iterators
typedef typename data::local_iterator_base local_iterator_base;
typedef typename data::iterator_base iterator_base;
typedef BOOST_DEDUCED_TYPENAME data::local_iterator_base local_iterator_base;
typedef BOOST_DEDUCED_TYPENAME data::iterator_base iterator_base;
private:
@ -804,7 +833,7 @@ namespace boost {
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200
boost::compressed_pair<hasher, key_equal> functions_;
#else
typedef std::pair<hasher, key_equal> functions;
std::pair<hasher, key_equal> functions_;
#endif
public:
@ -890,9 +919,9 @@ namespace boost {
template <class I>
std::size_t initial_size(I i, I j, size_type x)
{
typedef typename boost::iterator_traversal<I>::type
BOOST_DEDUCED_TYPENAME boost::iterator_traversal<I>::type
iterator_traversal_tag;
return initial_size(i, j, x, iterator_traversal_tag());
return initial_size(i, j, x, iterator_traversal_tag);
};
template <class I>
@ -1259,10 +1288,11 @@ namespace boost {
BOOST_ASSERT(src.node_alloc_ == dst.node_alloc_);
bucket_ptr end = src.buckets_ + src.bucket_count_; // no throw
for(; src.cached_begin_bucket_ != end; // no throw
++src.cached_begin_bucket_) {
erase_iterator it(src.cached_begin_bucket_); // no throw
while(it) {
while(it.not_finished()) {
// This next line throws iff the hash function throws.
bucket_ptr dst_bucket = dst.buckets_ +
dst.index_from_hash(
@ -1292,7 +1322,7 @@ namespace boost {
for(bucket_ptr i = src.cached_begin_bucket_; i != end; ++i) {
// no throw:
for(local_iterator_base it = src.begin(i);
it != src.end(i); it.increment()) {
it.not_finished(); it.increment()) {
// hash function can throw.
bucket_ptr dst_bucket = dst.buckets_ +
dst.index_from_hash(hf(extract_key(*it)));
@ -1316,12 +1346,12 @@ namespace boost {
BOOST_STATIC_ASSERT(!EquivalentKeys);
BOOST_STATIC_ASSERT((
!boost::is_same<value_type, key_type>::value));
typedef typename value_type::second_type mapped_type;
typedef BOOST_DEDUCED_TYPENAME value_type::second_type mapped_type;
bucket_ptr bucket = get_bucket(k);
local_iterator_base node = find_iterator(bucket, k);
if (node != this->end(bucket))
if (node.not_finished())
return *node;
else
{
@ -1358,10 +1388,10 @@ namespace boost {
{
// Condition throws, no side effects.
if(it != this->end() && equal(extract_key(v), *it)) {
return this->create_node(v, it); // throws, strong
return this->create_node(v, it); // throws, strong
}
else {
return unchecked_insert_equivalent(v); // throws, strong
return unchecked_insert_equivalent(v); // throws, strong
}
}
@ -1371,8 +1401,33 @@ namespace boost {
// strong otherwise
iterator_base insert_equivalent(value_type const& v)
{
reserve(size() + 1); // basic/strong
return unchecked_insert_equivalent(v); // throws, strong
key_type const& k = extract_key(v);
size_type hash_value = hash_function()(k);
bucket_ptr bucket = this->buckets_
+ this->index_from_hash(hash_value);
local_iterator_base position = find_iterator(bucket, k);
// Create the node before rehashing in case it throws.
// throws, no side effects:
node_constructor a(this->node_alloc_, this->bucket_alloc_);
a.construct(v);
// strong/no throw:
if(reserve(size() + 1)) // basic/strong
bucket = this->buckets_ + this->index_from_hash(hash_value);
// No throw from here.
link_ptr node = a.release();
// I'm relying on local_iterator_base not being invalidated by
// the rehash here.
if(position.not_finished())
link_node(node, position);
else
link_node(node, bucket);
return iterator_base(bucket, node);
}
// if hash function throws, basic exception safety
@ -1380,16 +1435,20 @@ namespace boost {
iterator_base insert_equivalent(iterator_base const& it, value_type const& v)
{
if (it != this->end() && equal(extract_key(v), *it)) { // throws, no side effects
// Create new node immediately as rehashing will invalidate 'it'
iterator_base new_node = this->create_node(v, it); // throws, strong
// Create the node before rehashing in case it throws.
// throws, no side effects:
node_constructor a(this->node_alloc_, this->bucket_alloc_);
a.construct(v);
// If reserve rehashes, new_node is invalidated.
if (reserve(size() + 1)) // basic/strong
return iterator_base( // no throw
get_bucket(extract_key(v)), // throws, no effects
new_node.local());
else
return new_node;
// The hash function can throw in get_bucket, but that's okay
// because then only basic exception safety is required.
bucket_ptr base = reserve(size() + 1) ?
get_bucket(extract_key(v)) : it.bucket_;
link_ptr node = a.release();
link_node(node, it.local());
return iterator_base(base, node);
}
else {
return insert_equivalent(v); // basic/strong
@ -1406,10 +1465,12 @@ namespace boost {
{
// Throws, but no side effects in this initial code
key_type const& k = extract_key(v);
bucket_ptr bucket = get_bucket(k);
size_type hash_value = hash_function()(k);
bucket_ptr bucket = this->buckets_
+ this->index_from_hash(hash_value);
local_iterator_base pos = find_iterator(bucket, k);
if (pos != this->end(bucket)) { // no throw
if (pos.not_finished()) { // no throw
// Found existing key, return it.
return std::pair<iterator_base, bool>(
iterator_base(bucket, pos), false); // no throw
@ -1418,12 +1479,20 @@ namespace boost {
// Doesn't already exist, add to bucket.
// Data is only changed in this block.
// Create the node before rehashing in case it throws.
// throws, no side effects:
node_constructor a(this->node_alloc_, this->bucket_alloc_);
a.construct(v);
// If we resize, then need to recalculate bucket.
if(reserve(size() + 1)) // throws, basic/strong
bucket = get_bucket(k); // throws, strong
bucket = this->buckets_ + this->index_from_hash(hash_value);
link_ptr node = a.release();
link_node(node, bucket);
return std::pair<iterator_base, bool>(
this->create_node(v, bucket), true); // throws, strong
iterator_base(bucket, node), true); // throws, strong
}
}
@ -1488,9 +1557,9 @@ namespace boost {
template <class InputIterator>
void insert(InputIterator i, InputIterator j)
{
typedef typename boost::iterator_traversal<InputIterator>::type
BOOST_DEDUCED_TYPENAME boost::iterator_traversal<InputIterator>::type
iterator_traversal_tag;
insert_for_range(i, j, iterator_traversal_tag());
insert_for_range(i, j, iterator_traversal_tag);
}
public:
@ -1512,12 +1581,12 @@ namespace boost {
erase_iterator it(find_for_erase(bucket, k));
// Rest is no throw, side effects only after this point.
if (it) {
if (it.not_finished()) {
if (EquivalentKeys) {
do {
++count;
this->delete_node(it);
} while(it && equal(k, *it));
} while(it.not_finished() && equal(k, *it));
}
else {
count = 1;
@ -1542,15 +1611,14 @@ namespace boost {
size_type count(key_type const& k) const
{
local_iterator_base it = find_iterator(k); // throws, strong
local_iterator_base end;
size_type count = 0;
if(it != end) {
if(it.not_finished()) {
if(EquivalentKeys) {
do {
++count;
it.increment();
} while (it != end && equal(k, *it)); // throws, strong
} while (it.not_finished() && equal(k, *it)); // throws, strong
}
else {
count = 1;
@ -1568,7 +1636,7 @@ namespace boost {
bucket_ptr bucket = get_bucket(k);
local_iterator_base it = find_iterator(bucket, k);
if (it != this->end(bucket))
if (it.not_finished())
return iterator_base(bucket, it);
else
return this->end();
@ -1581,15 +1649,14 @@ namespace boost {
{
bucket_ptr bucket = get_bucket(k);
local_iterator_base it = find_iterator(bucket, k);
if (it != this->end(bucket)) {
if (it.not_finished()) {
local_iterator_base last = it;
if(EquivalentKeys) {
local_iterator_base end = this->end(bucket);
local_iterator_base next = last;
next.increment();
while(next != end && equal(k, *next)) {
while(next.not_finished() && equal(k, *next)) {
last = next;
next.increment();
}
@ -1625,8 +1692,7 @@ namespace boost {
key_type const& k) const
{
local_iterator_base it = this->begin(bucket);
local_iterator_base end = this->end(bucket);
while (it != end && !equal(k, *it))
while (it.not_finished() && !equal(k, *it))
it.increment();
return it;
@ -1637,7 +1703,7 @@ namespace boost {
const
{
erase_iterator it(bucket);
while(it && !equal(k, *it))
while(it.not_finished() && !equal(k, *it))
it.next();
return it;
@ -1660,18 +1726,16 @@ namespace boost {
class hash_local_iterator
: public boost::iterator <
std::forward_iterator_tag,
typename get_value_type<Alloc>::type,
BOOST_DEDUCED_TYPENAME allocator_value_type<Alloc>::type,
std::ptrdiff_t,
typename get_pointer<Alloc>::type,
typename get_reference<Alloc>::type >
BOOST_DEDUCED_TYPENAME allocator_pointer<Alloc>::type,
BOOST_DEDUCED_TYPENAME allocator_reference<Alloc>::type >
{
public:
typedef typename hash_local_iterator::pointer pointer;
typedef typename hash_local_iterator::reference reference;
typedef typename get_value_type<Alloc>::type value_type;
typedef BOOST_DEDUCED_TYPENAME allocator_value_type<Alloc>::type value_type;
private:
typedef typename hash_table_data<Alloc>::local_iterator_base base;
typedef BOOST_DEDUCED_TYPENAME hash_table_data<Alloc>::local_iterator_base base;
typedef hash_const_local_iterator<Alloc> const_local_iterator;
friend class hash_const_local_iterator<Alloc>;
@ -1680,7 +1744,8 @@ namespace boost {
public:
hash_local_iterator() : base_() {}
explicit hash_local_iterator(base x) : base_(x) {}
reference operator*() const { return *base_; }
BOOST_DEDUCED_TYPENAME allocator_reference<Alloc>::type operator*() const
{ return *base_; }
value_type* operator->() const { return &*base_; }
hash_local_iterator& operator++() { base_.increment(); return *this; }
hash_local_iterator operator++(int) { hash_local_iterator tmp(base_); base_.increment(); return tmp; }
@ -1694,18 +1759,16 @@ namespace boost {
class hash_const_local_iterator
: public boost::iterator <
std::forward_iterator_tag,
typename get_value_type<Alloc>::type,
BOOST_DEDUCED_TYPENAME allocator_value_type<Alloc>::type,
std::ptrdiff_t,
typename get_const_pointer<Alloc>::type,
typename get_const_reference<Alloc>::type >
BOOST_DEDUCED_TYPENAME allocator_const_pointer<Alloc>::type,
BOOST_DEDUCED_TYPENAME allocator_const_reference<Alloc>::type >
{
public:
typedef typename hash_const_local_iterator::pointer pointer;
typedef typename hash_const_local_iterator::reference reference;
typedef typename get_value_type<Alloc>::type value_type;
typedef BOOST_DEDUCED_TYPENAME allocator_value_type<Alloc>::type value_type;
private:
typedef typename hash_table_data<Alloc>::local_iterator_base base;
typedef BOOST_DEDUCED_TYPENAME hash_table_data<Alloc>::local_iterator_base base;
typedef hash_local_iterator<Alloc> local_iterator;
friend class hash_local_iterator<Alloc>;
base base_;
@ -1714,7 +1777,8 @@ namespace boost {
hash_const_local_iterator() : base_() {}
explicit hash_const_local_iterator(base x) : base_(x) {}
hash_const_local_iterator(local_iterator x) : base_(x.base_) {}
reference operator*() const { return *base_; }
BOOST_DEDUCED_TYPENAME allocator_const_reference<Alloc>::type
operator*() const { return *base_; }
value_type const* operator->() const { return &*base_; }
hash_const_local_iterator& operator++() { base_.increment(); return *this; }
hash_const_local_iterator operator++(int) { hash_const_local_iterator tmp(base_); base_.increment(); return tmp; }
@ -1733,18 +1797,16 @@ namespace boost {
class hash_iterator
: public boost::iterator <
std::forward_iterator_tag,
typename get_value_type<Alloc>::type,
BOOST_DEDUCED_TYPENAME allocator_value_type<Alloc>::type,
std::ptrdiff_t,
typename get_pointer<Alloc>::type,
typename get_reference<Alloc>::type >
BOOST_DEDUCED_TYPENAME allocator_pointer<Alloc>::type,
BOOST_DEDUCED_TYPENAME allocator_reference<Alloc>::type >
{
public:
typedef typename hash_iterator::pointer pointer;
typedef typename hash_iterator::reference reference;
typedef typename get_value_type<Alloc>::type value_type;
typedef BOOST_DEDUCED_TYPENAME allocator_value_type<Alloc>::type value_type;
private:
typedef typename hash_table_data<Alloc>::iterator_base base;
typedef BOOST_DEDUCED_TYPENAME hash_table_data<Alloc>::iterator_base base;
typedef hash_const_iterator<Alloc> const_iterator;
friend class hash_const_iterator<Alloc>;
base base_;
@ -1753,7 +1815,8 @@ namespace boost {
hash_iterator() : base_() {}
explicit hash_iterator(base const& x) : base_(x) {}
reference operator*() const { return *base_; }
BOOST_DEDUCED_TYPENAME allocator_reference<Alloc>::type
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; }
@ -1767,18 +1830,16 @@ namespace boost {
class hash_const_iterator
: public boost::iterator <
std::forward_iterator_tag,
typename get_value_type<Alloc>::type,
BOOST_DEDUCED_TYPENAME allocator_value_type<Alloc>::type,
std::ptrdiff_t,
typename get_const_pointer<Alloc>::type,
typename get_const_reference<Alloc>::type >
BOOST_DEDUCED_TYPENAME allocator_const_pointer<Alloc>::type,
BOOST_DEDUCED_TYPENAME allocator_const_reference<Alloc>::type >
{
public:
typedef typename hash_const_iterator::pointer pointer;
typedef typename hash_const_iterator::reference reference;
typedef typename get_value_type<Alloc>::type value_type;
typedef BOOST_DEDUCED_TYPENAME allocator_value_type<Alloc>::type value_type;
private:
typedef typename hash_table_data<Alloc>::iterator_base base;
typedef BOOST_DEDUCED_TYPENAME hash_table_data<Alloc>::iterator_base base;
typedef hash_iterator<Alloc> iterator;
friend class hash_iterator<Alloc>;
friend class iterator_access;
@ -1789,7 +1850,8 @@ namespace boost {
hash_const_iterator() : base_() {}
explicit hash_const_iterator(base const& x) : base_(x) {}
hash_const_iterator(iterator const& x) : base_(x.base_) {}
reference operator*() const { return *base_; }
BOOST_DEDUCED_TYPENAME allocator_const_reference<Alloc>::type
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; }
@ -1803,7 +1865,7 @@ namespace boost {
{
public:
template <class Iterator>
static typename Iterator::base const& get(Iterator const& it) {
static BOOST_DEDUCED_TYPENAME Iterator::base const& get(Iterator const& it) {
return it.base_;
}
};
@ -1814,18 +1876,21 @@ namespace boost {
class hash_types
{
public:
typedef hash_table<ValueType, KeyType, Hash, Pred, Alloc,
EquivalentKeys> hash_table;
typedef BOOST_DEDUCED_TYPENAME
boost::unordered_detail::rebind_wrap<Alloc, ValueType>::type
value_allocator;
typedef typename hash_table::value_allocator value_allocator;
typedef typename hash_table::iterator_base iterator_base;
typedef hash_table<ValueType, KeyType, Hash, Pred, value_allocator,
EquivalentKeys> hash_table;
typedef hash_table_data<value_allocator> data;
typedef BOOST_DEDUCED_TYPENAME data::iterator_base iterator_base;
typedef hash_const_local_iterator<value_allocator> const_local_iterator;
typedef hash_local_iterator<value_allocator> local_iterator;
typedef hash_const_iterator<value_allocator> const_iterator;
typedef hash_iterator<value_allocator> iterator;
typedef typename hash_table::size_type size_type;
typedef BOOST_DEDUCED_TYPENAME data::size_type size_type;
typedef std::ptrdiff_t difference_type;
};
} // namespace boost::unordered_detail

View File

@ -51,13 +51,20 @@ namespace boost
public:
// types
/*! Key must be Assignable and CopyConstructible.
*/
typedef Key key_type;
typedef std::pair<const Key, T> value_type;
typedef T mapped_type;
/*! Hash is a unary function object type such for hf of type hasher
* hf(x) has type std::size_t.
*/
typedef Hash hasher;
/*! Pred is a binary predicate that takes two arguments of type Key.
* Pred is an equivalence realtion
*/
typedef Pred key_equal;
// This version can be used when compiling against CVS.
typedef Alloc allocator_type;
typedef typename allocator_type::pointer pointer;
typedef typename allocator_type::const_pointer const_pointer;
@ -69,11 +76,24 @@ namespace boost
typedef typename implementation_defined::iterator iterator;
typedef typename implementation_defined::const_iterator const_iterator;
/*! A local_iterator object may be used to iterate through a single
* bucket, but may not be used to iterate across buckets.
*/
typedef typename implementation_defined::local_iterator local_iterator;
typedef typename implementation_defined::const_local_iterator const_local_iterator;
/*! A const_local_iterator object may be used to iterate through a single
* bucket, but may not be used to iterate across buckets.
*/
typedef typename implementation_defined::const_local_iterator
const_local_iterator;
// construct/destroy/copy
/*! Constructs an empty container with at least n buckets, using hf as
* the hash function and eq as the key equality predicate. a is used
* as the allocator.
*/
explicit unordered_map(
size_type n = boost::unordered_detail::default_initial_bucket_count,
const hasher &hf = hasher(),
@ -83,6 +103,10 @@ namespace boost
{
}
/*! Constructs an empty container with at least n buckets, using hf as
* the hash function and eq as the key equality predicate, and inserts
* elements from [i,j) into it. a is used as the allocator.
*/
template <class InputIterator>
unordered_map(InputIterator f, InputIterator l,
size_type n = boost::unordered_detail::default_initial_bucket_count,
@ -339,8 +363,6 @@ namespace boost
typedef Hash hasher;
typedef Pred key_equal;
// This version can be used when compiling against CVS.
typedef Alloc allocator_type;
typedef typename allocator_type::pointer pointer;
typedef typename allocator_type::const_pointer const_pointer;