Support incomplete template parameters to unordered containers.

[SVN r57798]
This commit is contained in:
Daniel James committed 2009-11-20 08:03:26 +00:00
1 parent 26c72f9860
commit df72c4886f
10 files changed
+458 -354

No files matched your search

+91 -91
View File
@@ -21,17 +21,17 @@ namespace boost { namespace unordered_detail {
// Helper methods
// strong exception safety, no side effects
template <class H, class P, class A, class G, class E>
inline bool hash_table<H, P, A, G, E>::equal(
template <class T>
inline bool hash_table<T>::equal(
key_type const& k, value_type const& v) const
{
return this->key_eq()(k, get_key(v));
}
// strong exception safety, no side effects
template <class H, class P, class A, class G, class E>
inline BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, E>::node_ptr
hash_table<H, P, A, G, E>::find_iterator(
template <class T>
inline BOOST_DEDUCED_TYPENAME T::node_ptr
hash_table<T>::find_iterator(
bucket_ptr bucket, key_type const& k) const
{
node_ptr it = bucket->next_;
@@ -46,17 +46,17 @@ namespace boost { namespace unordered_detail {
// strong exception safety, no side effects
// pre: this->buckets_
template <class H, class P, class A, class G, class E>
inline BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, E>::node_ptr
hash_table<H, P, A, G, E>::find_iterator(key_type const& k) const
template <class T>
inline BOOST_DEDUCED_TYPENAME T::node_ptr
hash_table<T>::find_iterator(key_type const& k) const
{
return find_iterator(this->get_bucket(this->bucket_index(k)), k);
}
// strong exception safety, no side effects
template <class H, class P, class A, class G, class E>
inline BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, E>::node_ptr*
hash_table<H, P, A, G, E>::find_for_erase(
template <class T>
inline BOOST_DEDUCED_TYPENAME T::node_ptr*
hash_table<T>::find_for_erase(
bucket_ptr bucket, key_type const& k) const
{
node_ptr* it = &bucket->next_;
@@ -73,8 +73,8 @@ namespace boost { namespace unordered_detail {
// Load methods
// no throw
template <class H, class P, class A, class G, class E>
std::size_t hash_table<H, P, A, G, E>::max_size() const
template <class T>
std::size_t hash_table<T>::max_size() const
{
using namespace std;
@@ -84,8 +84,8 @@ namespace boost { namespace unordered_detail {
}
// strong safety
template <class H, class P, class A, class G, class E>
inline std::size_t hash_table<H, P, A, G, E>::bucket_index(
template <class T>
inline std::size_t hash_table<T>::bucket_index(
key_type const& k) const
{
// hash_function can throw:
@@ -94,8 +94,8 @@ namespace boost { namespace unordered_detail {
// no throw
template <class H, class P, class A, class G, class E>
inline std::size_t hash_table<H, P, A, G, E>::calculate_max_load()
template <class T>
inline std::size_t hash_table<T>::calculate_max_load()
{
using namespace std;
@@ -104,8 +104,8 @@ namespace boost { namespace unordered_detail {
return double_to_size_t(ceil((double) mlf_ * this->bucket_count_));
}
template <class H, class P, class A, class G, class E>
void hash_table<H, P, A, G, E>::max_load_factor(float z)
template <class T>
void hash_table<T>::max_load_factor(float z)
{
BOOST_ASSERT(z > 0);
mlf_ = (std::max)(z, minimum_max_load_factor);
@@ -113,8 +113,8 @@ namespace boost { namespace unordered_detail {
}
// no throw
template <class H, class P, class A, class G, class E>
inline std::size_t hash_table<H, P, A, G, E>::min_buckets_for_size(
template <class T>
inline std::size_t hash_table<T>::min_buckets_for_size(
std::size_t size) const
{
BOOST_ASSERT(this->mlf_ != 0);
@@ -135,8 +135,8 @@ namespace boost { namespace unordered_detail {
// init_buckets
template <class H, class P, class A, class G, class E>
inline void hash_table<H, P, A, G, E>::init_buckets()
template <class T>
inline void hash_table<T>::init_buckets()
{
if (this->size_) {
this->cached_begin_bucket_ = this->buckets_;
@@ -153,8 +153,8 @@ namespace boost { namespace unordered_detail {
//
// no throw
template <class H, class P, class A, class G, class E>
inline void hash_table<H, P, A, G, E>::recompute_begin_bucket(bucket_ptr b)
template <class T>
inline void hash_table<T>::recompute_begin_bucket(bucket_ptr b)
{
BOOST_ASSERT(!(b < this->cached_begin_bucket_));
@@ -174,8 +174,8 @@ namespace boost { namespace unordered_detail {
//
// no throw
template <class H, class P, class A, class G, class E>
inline void hash_table<H, P, A, G, E>::recompute_begin_bucket(
template <class T>
inline void hash_table<T>::recompute_begin_bucket(
bucket_ptr b1, bucket_ptr b2)
{
BOOST_ASSERT(!(b1 < this->cached_begin_bucket_) && !(b2 < b1));
@@ -186,8 +186,8 @@ namespace boost { namespace unordered_detail {
}
// no throw
template <class H, class P, class A, class G, class E>
inline float hash_table<H, P, A, G, E>::load_factor() const
template <class T>
inline float hash_table<T>::load_factor() const
{
BOOST_ASSERT(this->bucket_count_ != 0);
return static_cast<float>(this->size_)
@@ -197,8 +197,8 @@ namespace boost { namespace unordered_detail {
////////////////////////////////////////////////////////////////////////////
// Constructors
template <class H, class P, class A, class G, class E>
hash_table<H, P, A, G, E>::hash_table(std::size_t num_buckets,
template <class T>
hash_table<T>::hash_table(std::size_t num_buckets,
hasher const& hf, key_equal const& eq, node_allocator const& a)
: buckets(a, next_prime(num_buckets)),
base(hf, eq),
@@ -211,8 +211,8 @@ namespace boost { namespace unordered_detail {
// Copy Construct with allocator
template <class H, class P, class A, class G, class E>
hash_table<H, P, A, G, E>::hash_table(hash_table const& x,
template <class T>
hash_table<T>::hash_table(hash_table const& x,
node_allocator const& a)
: buckets(a, x.min_buckets_for_size(x.size_)),
base(x),
@@ -229,8 +229,8 @@ namespace boost { namespace unordered_detail {
// Move Construct
template <class H, class P, class A, class G, class E>
hash_table<H, P, A, G, E>::hash_table(hash_table& x, move_tag)
template <class T>
hash_table<T>::hash_table(hash_table& x, move_tag)
: buckets(x.node_alloc(), x.bucket_count_),
base(x),
size_(0),
@@ -241,8 +241,8 @@ namespace boost { namespace unordered_detail {
this->partial_swap(x);
}
template <class H, class P, class A, class G, class E>
hash_table<H, P, A, G, E>::hash_table(hash_table& x,
template <class T>
hash_table<T>::hash_table(hash_table& x,
node_allocator const& a, move_tag)
: buckets(a, x.bucket_count_),
base(x),
@@ -261,8 +261,8 @@ namespace boost { namespace unordered_detail {
}
}
template <class H, class P, class A, class G, class E>
hash_table<H, P, A, G, E>& hash_table<H, P, A, G, K>::operator=(
template <class T>
hash_table<T>& hash_table<T>::operator=(
hash_table const& x)
{
hash_table tmp(x, this->node_alloc());
@@ -280,8 +280,8 @@ namespace boost { namespace unordered_detail {
// Can throw if hash or predicate object's copy constructor throws
// or if allocators are unequal.
template <class H, class P, class A, class G, class E>
inline void hash_table<H, P, A, G, E>::partial_swap(hash_table& x)
template <class T>
inline void hash_table<T>::partial_swap(hash_table& x)
{
this->buckets::swap(x); // No throw
std::swap(this->size_, x.size_);
@@ -290,15 +290,15 @@ namespace boost { namespace unordered_detail {
std::swap(this->max_load_, x.max_load_);
}
template <class H, class P, class A, class G, class E>
inline void hash_table<H, P, A, G, E>::fast_swap(hash_table& x)
template <class T>
inline void hash_table<T>::fast_swap(hash_table& x)
{
// These can throw, but they only affect the function objects
// that aren't in use so it is strongly exception safe, via.
// double buffering.
{
set_hash_functions<H, P> op1(*this, x);
set_hash_functions<H, P> op2(x, *this);
set_hash_functions<hasher, key_equal> op1(*this, x);
set_hash_functions<hasher, key_equal> op2(x, *this);
op1.commit();
op2.commit();
}
@@ -309,8 +309,8 @@ namespace boost { namespace unordered_detail {
std::swap(this->max_load_, x.max_load_);
}
template <class H, class P, class A, class G, class E>
inline void hash_table<H, P, A, G, E>::slow_swap(hash_table& x)
template <class T>
inline void hash_table<T>::slow_swap(hash_table& x)
{
if(this == &x) return;
@@ -318,8 +318,8 @@ namespace boost { namespace unordered_detail {
// These can throw, but they only affect the function objects
// that aren't in use so it is strongly exception safe, via.
// double buffering.
set_hash_functions<H, P> op1(*this, x);
set_hash_functions<H, P> op2(x, *this);
set_hash_functions<hasher, key_equal> op1(*this, x);
set_hash_functions<hasher, key_equal> op2(x, *this);
// Create new buckets in separate hash_buckets objects
// which will clean up if anything throws an exception.
@@ -345,8 +345,8 @@ namespace boost { namespace unordered_detail {
if(x.buckets_) x.init_buckets();
}
template <class H, class P, class A, class G, class E>
void hash_table<H, P, A, G, E>::swap(hash_table& x)
template <class T>
void hash_table<T>::swap(hash_table& x)
{
if(this->node_alloc() == x.node_alloc()) {
if(this != &x) this->fast_swap(x);
@@ -364,13 +364,13 @@ namespace boost { namespace unordered_detail {
// Can throw if hash or predicate object's copy constructor throws
// or if allocators are unequal.
template <class H, class P, class A, class G, class E>
void hash_table<H, P, A, G, E>::move(hash_table& x)
template <class T>
void hash_table<T>::move(hash_table& x)
{
// This can throw, but it only affects the function objects
// that aren't in use so it is strongly exception safe, via.
// double buffering.
set_hash_functions<H, P> new_func_this(*this, x);
set_hash_functions<hasher, key_equal> new_func_this(*this, x);
if(this->node_alloc() == x.node_alloc()) {
this->buckets::move(x); // no throw
@@ -402,8 +402,8 @@ namespace boost { namespace unordered_detail {
// Reserve & Rehash
// basic exception safety
template <class H, class P, class A, class G, class E>
inline void hash_table<H, P, A, G, E>::create_for_insert(std::size_t size)
template <class T>
inline void hash_table<T>::create_for_insert(std::size_t size)
{
this->bucket_count_ = (std::max)(this->bucket_count_,
this->min_buckets_for_size(size));
@@ -412,8 +412,8 @@ namespace boost { namespace unordered_detail {
}
// basic exception safety
template <class H, class P, class A, class G, class E>
inline bool hash_table<H, P, A, G, E>::reserve_for_insert(std::size_t size)
template <class T>
inline bool hash_table<T>::reserve_for_insert(std::size_t size)
{
if(size >= max_load_) {
std::size_t num_buckets
@@ -431,8 +431,8 @@ namespace boost { namespace unordered_detail {
// if hash function throws, basic exception safety
// strong otherwise.
template <class H, class P, class A, class G, class E>
inline void hash_table<H, P, A, G, E>::rehash(std::size_t min_buckets)
template <class T>
inline void hash_table<T>::rehash(std::size_t min_buckets)
{
using namespace std;
@@ -451,8 +451,8 @@ namespace boost { namespace unordered_detail {
// if hash function throws, basic exception safety
// strong otherwise
template <class H, class P, class A, class G, class E>
void hash_table<H, P, A, G, E>
template <class T>
void hash_table<T>
::rehash_impl(std::size_t num_buckets)
{
hasher const& hf = this->hash_function();
@@ -500,8 +500,8 @@ namespace boost { namespace unordered_detail {
// basic excpetion safety. If an exception is thrown this will
// leave dst partially filled.
template <class H, class P, class A, class G, class E>
void hash_table<H, P, A, G, E>
template <class T>
void hash_table<T>
::copy_buckets_to(buckets& dst) const
{
BOOST_ASSERT(this->buckets_ && !dst.buckets_);
@@ -509,7 +509,7 @@ namespace boost { namespace unordered_detail {
hasher const& hf = this->hash_function();
bucket_ptr end = this->get_bucket(this->bucket_count_);
hash_node_constructor<A, G> a(dst);
node_constructor a(dst);
dst.create_buckets();
// no throw:
@@ -544,8 +544,8 @@ namespace boost { namespace unordered_detail {
//
// strong exception safety, no side effects
template <class H, class P, class A, class G, class E>
std::size_t hash_table<H, P, A, G, E>::count(key_type const& k) const
template <class T>
std::size_t hash_table<T>::count(key_type const& k) const
{
if(!this->size_) return 0;
node_ptr it = find_iterator(k); // throws, strong
@@ -555,9 +555,9 @@ namespace boost { namespace unordered_detail {
// find
//
// strong exception safety, no side effects
template <class H, class P, class A, class G, class E>
BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, E>::iterator_base
hash_table<H, P, A, G, E>::find(key_type const& k) const
template <class T>
BOOST_DEDUCED_TYPENAME T::iterator_base
hash_table<T>::find(key_type const& k) const
{
if(!this->size_) return this->end();
@@ -570,9 +570,9 @@ namespace boost { namespace unordered_detail {
return this->end();
}
template <class H, class P, class A, class G, class E>
BOOST_DEDUCED_TYPENAME A::value_type&
hash_table<H, P, A, G, E>::at(key_type const& k) const
template <class T>
BOOST_DEDUCED_TYPENAME T::value_type&
hash_table<T>::at(key_type const& k) const
{
if(!this->size_)
throw std::out_of_range("Unable to find key in unordered_map.");
@@ -589,9 +589,9 @@ namespace boost { namespace unordered_detail {
// equal_range
//
// strong exception safety, no side effects
template <class H, class P, class A, class G, class E>
BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, E>::iterator_pair
hash_table<H, P, A, G, E>::equal_range(key_type const& k) const
template <class T>
BOOST_DEDUCED_TYPENAME T::iterator_pair
hash_table<T>::equal_range(key_type const& k) const
{
if(!this->size_)
return iterator_pair(this->end(), this->end());
@@ -612,8 +612,8 @@ namespace boost { namespace unordered_detail {
////////////////////////////////////////////////////////////////////////////
// Erase methods
template <class H, class P, class A, class G, class E>
void hash_table<H, P, A, G, E>::clear()
template <class T>
void hash_table<T>::clear()
{
if(!this->size_) return;
@@ -626,8 +626,8 @@ namespace boost { namespace unordered_detail {
this->cached_begin_bucket_ = end;
}
template <class H, class P, class A, class G, class E>
inline std::size_t hash_table<H, P, A, G, E>::erase_group(
template <class T>
inline std::size_t hash_table<T>::erase_group(
node_ptr* it, bucket_ptr bucket)
{
node_ptr pos = *it;
@@ -639,8 +639,8 @@ namespace boost { namespace unordered_detail {
return count;
}
template <class H, class P, class A, class G, class E>
std::size_t hash_table<H, P, A, G, E>::erase_key(key_type const& k)
template <class T>
std::size_t hash_table<T>::erase_key(key_type const& k)
{
if(!this->size_) return 0;
@@ -653,9 +653,9 @@ namespace boost { namespace unordered_detail {
}
template <class H, class P, class A, class G, class E>
BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, E>::iterator_base
hash_table<H, P, A, G, E>::erase(iterator_base r)
template <class T>
BOOST_DEDUCED_TYPENAME T::iterator_base
hash_table<T>::erase(iterator_base r)
{
BOOST_ASSERT(r.node_);
iterator_base next = r;
@@ -668,9 +668,9 @@ namespace boost { namespace unordered_detail {
return next;
}
template <class H, class P, class A, class G, class E>
BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, E>::iterator_base
hash_table<H, P, A, G, E>::erase_range(
template <class T>
BOOST_DEDUCED_TYPENAME T::iterator_base
hash_table<T>::erase_range(
iterator_base r1, iterator_base r2)
{
if(r1 != r2)
@@ -713,9 +713,9 @@ namespace boost { namespace unordered_detail {
return r2;
}
template <class H, class P, class A, class G, class E>
BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, E>::iterator_base
hash_table<H, P, A, G, E>::emplace_empty_impl_with_node(
template <class T>
BOOST_DEDUCED_TYPENAME hash_table<T>::iterator_base
hash_table<T>::emplace_empty_impl_with_node(
node_constructor& a, std::size_t size)
{
key_type const& k = get_key(a.value());