From df72c4886f7d267a0308e2996e97c45c0b2926cb Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 20 Nov 2009 08:03:26 +0000 Subject: [PATCH] Support incomplete template parameters to unordered containers. [SVN r57798] --- include/boost/unordered/detail/equivalent.hpp | 46 ++-- .../boost/unordered/detail/extract_key.hpp | 214 +++++++++--------- include/boost/unordered/detail/fwd.hpp | 193 ++++++++++------ include/boost/unordered/detail/table.hpp | 182 +++++++-------- include/boost/unordered/detail/unique.hpp | 92 ++++---- include/boost/unordered/unordered_map.hpp | 20 +- include/boost/unordered/unordered_set.hpp | 21 +- test/helpers/allocator.hpp | 4 +- test/unordered/Jamfile.v2 | 1 + test/unordered/incomplete_test.cpp | 39 ++++ 10 files changed, 458 insertions(+), 354 deletions(-) create mode 100644 test/unordered/incomplete_test.cpp diff --git a/include/boost/unordered/detail/equivalent.hpp b/include/boost/unordered/detail/equivalent.hpp index 097dd60f..639dd5ef 100644 --- a/include/boost/unordered/detail/equivalent.hpp +++ b/include/boost/unordered/detail/equivalent.hpp @@ -15,9 +15,9 @@ namespace boost { namespace unordered_detail { //////////////////////////////////////////////////////////////////////////// // Equality - template - bool hash_equivalent_table - ::equals(hash_equivalent_table const& other) const + template + bool hash_equivalent_table + ::equals(hash_equivalent_table const& other) const { if(this->size_ != other.size_) return false; if(!this->size_) return true; @@ -51,9 +51,9 @@ namespace boost { namespace unordered_detail { //////////////////////////////////////////////////////////////////////////// // A convenience method for adding nodes. - template - inline BOOST_DEDUCED_TYPENAME hash_equivalent_table::node_ptr - hash_equivalent_table + template + inline BOOST_DEDUCED_TYPENAME hash_equivalent_table::node_ptr + hash_equivalent_table ::add_node(node_constructor& a, bucket_ptr bucket, node_ptr pos) { node_ptr n = a.release(); @@ -72,10 +72,10 @@ namespace boost { namespace unordered_detail { //////////////////////////////////////////////////////////////////////////// // Insert methods - template + template inline BOOST_DEDUCED_TYPENAME - hash_equivalent_table::iterator_base - hash_equivalent_table::emplace_impl(node_constructor& a) + hash_equivalent_table::iterator_base + hash_equivalent_table::emplace_impl(node_constructor& a) { key_type const& k = this->get_key(a.value()); std::size_t hash_value = this->hash_function()(k); @@ -96,8 +96,8 @@ namespace boost { namespace unordered_detail { } } - template - inline void hash_equivalent_table + template + inline void hash_equivalent_table ::emplace_impl_no_rehash(node_constructor& a) { key_type const& k = this->get_key(a.value()); @@ -112,10 +112,10 @@ namespace boost { namespace unordered_detail { // if hash function throws, basic exception safety // strong otherwise - template + template template - BOOST_DEDUCED_TYPENAME hash_equivalent_table::iterator_base - hash_equivalent_table + BOOST_DEDUCED_TYPENAME hash_equivalent_table::iterator_base + hash_equivalent_table ::emplace(Args&&... args) { // Create the node before rehashing in case it throws an @@ -129,10 +129,10 @@ namespace boost { namespace unordered_detail { #else #define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \ - template \ + template \ template \ - BOOST_DEDUCED_TYPENAME hash_equivalent_table::iterator_base \ - hash_equivalent_table \ + BOOST_DEDUCED_TYPENAME hash_equivalent_table::iterator_base \ + hash_equivalent_table \ ::emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \ { \ node_constructor a(*this); \ @@ -151,9 +151,9 @@ namespace boost { namespace unordered_detail { // if hash function throws, or inserting > 1 element, basic exception safety // strong otherwise - template + template template - inline void hash_equivalent_table + inline void hash_equivalent_table ::insert_for_range(I i, I j, forward_traversal_tag) { if(i == j) return; @@ -182,9 +182,9 @@ namespace boost { namespace unordered_detail { // if hash function throws, or inserting > 1 element, basic exception safety // strong otherwise - template + template template - inline void hash_equivalent_table + inline void hash_equivalent_table ::insert_for_range(I i, I j, boost::incrementable_traversal_tag) { node_constructor a(*this); @@ -196,9 +196,9 @@ namespace boost { namespace unordered_detail { // if hash function throws, or inserting > 1 element, basic exception safety // strong otherwise - template + template template - void hash_equivalent_table::insert_range(I i, I j) + void hash_equivalent_table::insert_range(I i, I j) { BOOST_DEDUCED_TYPENAME boost::iterator_traversal::type iterator_traversal_tag; diff --git a/include/boost/unordered/detail/extract_key.hpp b/include/boost/unordered/detail/extract_key.hpp index d415d935..184600d2 100644 --- a/include/boost/unordered/detail/extract_key.hpp +++ b/include/boost/unordered/detail/extract_key.hpp @@ -28,128 +28,120 @@ namespace unordered_detail { template no_key(T const&) {} }; + template struct set_extractor { - template - struct apply + typedef ValueType value_type; + typedef ValueType key_type; + + static key_type const& extract(key_type const& v) { - typedef ValueType value_type; - typedef ValueType key_type; + return v; + } - static key_type const& extract(key_type const& v) - { - return v; - } - - static no_key extract() - { - return no_key(); - } - - #if defined(BOOST_UNORDERED_STD_FORWARD) - template - static no_key extract(Args const&...) - { - return no_key(); - } - - #else - template - static no_key extract(Arg const&) - { - return no_key(); - } - - template - static no_key extract(Arg const&, Arg const&) - { - return no_key(); - } - #endif - - static bool compare_mapped(value_type const&, value_type const&) - { - return true; - } - }; - }; - - struct map_extractor - { - template - struct apply + static no_key extract() { - typedef ValueType value_type; - typedef BOOST_DEDUCED_TYPENAME - remove_const::type - key_type; - - static key_type const& extract(value_type const& v) - { - return v.first; - } - - static key_type const& extract(key_type const& v) - { - return v; - } - - template - static key_type const& extract(std::pair const& v) - { - return v.first; - } - - template - static key_type const& extract( - std::pair const& v) - { - return v.first; - } - + return no_key(); + } + #if defined(BOOST_UNORDERED_STD_FORWARD) - template - static key_type const& extract(key_type const& k, - Arg1 const&, Args const&...) - { - return k; - } + template + static no_key extract(Args const&...) + { + return no_key(); + } - template - static no_key extract(Args const&...) - { - return no_key(); - } #else - template - static key_type const& extract(key_type const& k, Arg1 const&) - { - return k; - } + template + static no_key extract(Arg const&) + { + return no_key(); + } - static no_key extract() - { - return no_key(); - } - - template - static no_key extract(Arg const&) - { - return no_key(); - } - - template - static no_key extract(Arg const&, Arg1 const&) - { - return no_key(); - } + template + static no_key extract(Arg const&, Arg const&) + { + return no_key(); + } #endif - static bool compare_mapped(value_type const& x, value_type const& y) - { - return x.second == y.second; - } - }; + static bool compare_mapped(value_type const&, value_type const&) + { + return true; + } + }; + + template + struct map_extractor + { + typedef ValueType value_type; + typedef Key key_type; + + static key_type const& extract(value_type const& v) + { + return v.first; + } + + static key_type const& extract(key_type const& v) + { + return v; + } + + template + static key_type const& extract(std::pair const& v) + { + return v.first; + } + + template + static key_type const& extract( + std::pair const& v) + { + return v.first; + } + +#if defined(BOOST_UNORDERED_STD_FORWARD) + template + static key_type const& extract(key_type const& k, + Arg1 const&, Args const&...) + { + return k; + } + + template + static no_key extract(Args const&...) + { + return no_key(); + } +#else + template + static key_type const& extract(key_type const& k, Arg1 const&) + { + return k; + } + + static no_key extract() + { + return no_key(); + } + + template + static no_key extract(Arg const&) + { + return no_key(); + } + + template + static no_key extract(Arg const&, Arg1 const&) + { + return no_key(); + } +#endif + + static bool compare_mapped(value_type const& x, value_type const& y) + { + return x.second == y.second; + } }; }} diff --git a/include/boost/unordered/detail/fwd.hpp b/include/boost/unordered/detail/fwd.hpp index f925dbc6..ff3d63e9 100644 --- a/include/boost/unordered/detail/fwd.hpp +++ b/include/boost/unordered/detail/fwd.hpp @@ -66,7 +66,9 @@ namespace boost { namespace unordered_detail { template class hash_node_constructor; + template struct set_extractor; + template struct map_extractor; struct no_key; @@ -208,9 +210,9 @@ namespace boost { namespace unordered_detail { typedef A value_allocator; typedef hash_bucket bucket; typedef hash_node 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; + typedef BOOST_DEDUCED_TYPENAME A::value_type value_type; + typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr; + typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr; bucket_ptr bucket_; node_ptr node_; @@ -268,9 +270,9 @@ namespace boost { namespace unordered_detail { 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 bucket::bucket_allocator bucket_allocator; + typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr; + typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr; typedef BOOST_DEDUCED_TYPENAME rebind_wrap::type node_allocator; @@ -424,33 +426,28 @@ namespace boost { namespace unordered_detail { } }; - template - class hash_table : - public hash_buckets, - public hash_buffered_functions + template + class hash_table : public T::buckets, public T::buffered_functions { hash_table(hash_table const&); public: - typedef H hasher; - typedef P key_equal; - typedef A value_allocator; - typedef E key_extractor; - typedef hash_buffered_functions base; - typedef hash_buckets buckets; - - typedef BOOST_DEDUCED_TYPENAME value_allocator::value_type value_type; - typedef BOOST_DEDUCED_TYPENAME key_extractor::BOOST_NESTED_TEMPLATE - apply extractor; - typedef BOOST_DEDUCED_TYPENAME extractor::key_type key_type; + typedef BOOST_DEDUCED_TYPENAME T::hasher hasher; + typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal; + typedef BOOST_DEDUCED_TYPENAME T::value_allocator value_allocator; + typedef BOOST_DEDUCED_TYPENAME T::key_type key_type; + typedef BOOST_DEDUCED_TYPENAME T::value_type value_type; + typedef BOOST_DEDUCED_TYPENAME T::buffered_functions base; + typedef BOOST_DEDUCED_TYPENAME T::buckets buckets; + typedef BOOST_DEDUCED_TYPENAME T::extractor extractor; + typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor; - 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; - typedef BOOST_DEDUCED_TYPENAME buckets::node_allocator node_allocator; - typedef hash_node_constructor node_constructor; - typedef std::pair iterator_pair; + typedef BOOST_DEDUCED_TYPENAME T::node node; + typedef BOOST_DEDUCED_TYPENAME T::bucket bucket; + typedef BOOST_DEDUCED_TYPENAME T::node_ptr node_ptr; + typedef BOOST_DEDUCED_TYPENAME T::bucket_ptr bucket_ptr; + typedef BOOST_DEDUCED_TYPENAME T::iterator_base iterator_base; + typedef BOOST_DEDUCED_TYPENAME T::node_allocator node_allocator; + typedef BOOST_DEDUCED_TYPENAME T::iterator_pair iterator_pair; // Members @@ -563,27 +560,23 @@ namespace boost { namespace unordered_detail { node_constructor&, std::size_t); }; - template - class hash_unique_table : - public hash_table - + template + class hash_unique_table : public T::table { public: - typedef H hasher; - typedef P key_equal; - typedef A value_allocator; - typedef E key_extractor; + typedef BOOST_DEDUCED_TYPENAME T::hasher hasher; + typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal; + typedef BOOST_DEDUCED_TYPENAME T::value_allocator value_allocator; + typedef BOOST_DEDUCED_TYPENAME T::key_type key_type; + typedef BOOST_DEDUCED_TYPENAME T::value_type value_type; + typedef BOOST_DEDUCED_TYPENAME T::table table; + typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor; - typedef hash_table table; - typedef hash_node_constructor 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 BOOST_DEDUCED_TYPENAME T::node node; + typedef BOOST_DEDUCED_TYPENAME T::node_ptr node_ptr; + typedef BOOST_DEDUCED_TYPENAME T::bucket_ptr bucket_ptr; + typedef BOOST_DEDUCED_TYPENAME T::iterator_base iterator_base; + typedef BOOST_DEDUCED_TYPENAME T::extractor extractor; typedef std::pair emplace_return; @@ -657,27 +650,23 @@ namespace boost { namespace unordered_detail { void insert_range_impl(no_key, InputIt i, InputIt j); }; - template - class hash_equivalent_table : - public hash_table - + template + class hash_equivalent_table : public T::table { public: - typedef H hasher; - typedef P key_equal; - typedef A value_allocator; - typedef E key_extractor; + typedef BOOST_DEDUCED_TYPENAME T::hasher hasher; + typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal; + typedef BOOST_DEDUCED_TYPENAME T::value_allocator value_allocator; + typedef BOOST_DEDUCED_TYPENAME T::key_type key_type; + typedef BOOST_DEDUCED_TYPENAME T::value_type value_type; + typedef BOOST_DEDUCED_TYPENAME T::table table; + typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor; - typedef hash_table table; - typedef hash_node_constructor node_constructor; - typedef hash_iterator_base 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; + typedef BOOST_DEDUCED_TYPENAME T::node node; + typedef BOOST_DEDUCED_TYPENAME T::node_ptr node_ptr; + typedef BOOST_DEDUCED_TYPENAME T::bucket_ptr bucket_ptr; + typedef BOOST_DEDUCED_TYPENAME T::iterator_base iterator_base; + typedef BOOST_DEDUCED_TYPENAME T::extractor extractor; // Constructors @@ -963,6 +952,80 @@ namespace boost { namespace unordered_detail { return base_ != x.base_; } }; + + // types + + template + struct types + { + public: + typedef K key_type; + typedef V value_type; + typedef H hasher; + typedef P key_equal; + typedef A value_allocator; + typedef E extractor; + typedef G group_type; + + typedef hash_node_constructor node_constructor; + typedef hash_buckets buckets; + typedef hash_buffered_functions buffered_functions; + + 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; + typedef BOOST_DEDUCED_TYPENAME buckets::node_allocator node_allocator; + + typedef std::pair iterator_pair; + }; + + template + struct set : public types< + BOOST_DEDUCED_TYPENAME A::value_type, + BOOST_DEDUCED_TYPENAME A::value_type, + H, P, A, + set_extractor, + ungrouped> + { + typedef hash_unique_table > impl; + typedef hash_table > table; + }; + + template + struct multiset : public types< + BOOST_DEDUCED_TYPENAME A::value_type, + BOOST_DEDUCED_TYPENAME A::value_type, + H, P, A, + set_extractor, + grouped> + { + typedef hash_equivalent_table > impl; + typedef hash_table > table; + }; + + template + struct map : public types< + K, BOOST_DEDUCED_TYPENAME A::value_type, + H, P, A, + map_extractor, + ungrouped> + { + typedef hash_unique_table > impl; + typedef hash_table > table; + }; + + template + struct multimap : public types< + K, BOOST_DEDUCED_TYPENAME A::value_type, + H, P, A, + map_extractor, + grouped> + { + typedef hash_equivalent_table > impl; + typedef hash_table > table; + }; }} #endif diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp index 4fe86b88..2f4e5ebd 100644 --- a/include/boost/unordered/detail/table.hpp +++ b/include/boost/unordered/detail/table.hpp @@ -21,17 +21,17 @@ namespace boost { namespace unordered_detail { // Helper methods // strong exception safety, no side effects - template - inline bool hash_table::equal( + template + inline bool hash_table::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 - inline BOOST_DEDUCED_TYPENAME hash_table::node_ptr - hash_table::find_iterator( + template + inline BOOST_DEDUCED_TYPENAME T::node_ptr + hash_table::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 - inline BOOST_DEDUCED_TYPENAME hash_table::node_ptr - hash_table::find_iterator(key_type const& k) const + template + inline BOOST_DEDUCED_TYPENAME T::node_ptr + hash_table::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 - inline BOOST_DEDUCED_TYPENAME hash_table::node_ptr* - hash_table::find_for_erase( + template + inline BOOST_DEDUCED_TYPENAME T::node_ptr* + hash_table::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 - std::size_t hash_table::max_size() const + template + std::size_t hash_table::max_size() const { using namespace std; @@ -84,8 +84,8 @@ namespace boost { namespace unordered_detail { } // strong safety - template - inline std::size_t hash_table::bucket_index( + template + inline std::size_t hash_table::bucket_index( key_type const& k) const { // hash_function can throw: @@ -94,8 +94,8 @@ namespace boost { namespace unordered_detail { // no throw - template - inline std::size_t hash_table::calculate_max_load() + template + inline std::size_t hash_table::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 - void hash_table::max_load_factor(float z) + template + void hash_table::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 - inline std::size_t hash_table::min_buckets_for_size( + template + inline std::size_t hash_table::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 - inline void hash_table::init_buckets() + template + inline void hash_table::init_buckets() { if (this->size_) { this->cached_begin_bucket_ = this->buckets_; @@ -153,8 +153,8 @@ namespace boost { namespace unordered_detail { // // no throw - template - inline void hash_table::recompute_begin_bucket(bucket_ptr b) + template + inline void hash_table::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 - inline void hash_table::recompute_begin_bucket( + template + inline void hash_table::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 - inline float hash_table::load_factor() const + template + inline float hash_table::load_factor() const { BOOST_ASSERT(this->bucket_count_ != 0); return static_cast(this->size_) @@ -197,8 +197,8 @@ namespace boost { namespace unordered_detail { //////////////////////////////////////////////////////////////////////////// // Constructors - template - hash_table::hash_table(std::size_t num_buckets, + template + hash_table::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 - hash_table::hash_table(hash_table const& x, + template + hash_table::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 - hash_table::hash_table(hash_table& x, move_tag) + template + hash_table::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 - hash_table::hash_table(hash_table& x, + template + hash_table::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 - hash_table& hash_table::operator=( + template + hash_table& hash_table::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 - inline void hash_table::partial_swap(hash_table& x) + template + inline void hash_table::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 - inline void hash_table::fast_swap(hash_table& x) + template + inline void hash_table::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 op1(*this, x); - set_hash_functions op2(x, *this); + set_hash_functions op1(*this, x); + set_hash_functions 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 - inline void hash_table::slow_swap(hash_table& x) + template + inline void hash_table::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 op1(*this, x); - set_hash_functions op2(x, *this); + set_hash_functions op1(*this, x); + set_hash_functions 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 - void hash_table::swap(hash_table& x) + template + void hash_table::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 - void hash_table::move(hash_table& x) + template + void hash_table::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 new_func_this(*this, x); + set_hash_functions 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 - inline void hash_table::create_for_insert(std::size_t size) + template + inline void hash_table::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 - inline bool hash_table::reserve_for_insert(std::size_t size) + template + inline bool hash_table::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 - inline void hash_table::rehash(std::size_t min_buckets) + template + inline void hash_table::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 - void hash_table + template + void hash_table ::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 - void hash_table + template + void hash_table ::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(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 - std::size_t hash_table::count(key_type const& k) const + template + std::size_t hash_table::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 - BOOST_DEDUCED_TYPENAME hash_table::iterator_base - hash_table::find(key_type const& k) const + template + BOOST_DEDUCED_TYPENAME T::iterator_base + hash_table::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 - BOOST_DEDUCED_TYPENAME A::value_type& - hash_table::at(key_type const& k) const + template + BOOST_DEDUCED_TYPENAME T::value_type& + hash_table::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 - BOOST_DEDUCED_TYPENAME hash_table::iterator_pair - hash_table::equal_range(key_type const& k) const + template + BOOST_DEDUCED_TYPENAME T::iterator_pair + hash_table::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 - void hash_table::clear() + template + void hash_table::clear() { if(!this->size_) return; @@ -626,8 +626,8 @@ namespace boost { namespace unordered_detail { this->cached_begin_bucket_ = end; } - template - inline std::size_t hash_table::erase_group( + template + inline std::size_t hash_table::erase_group( node_ptr* it, bucket_ptr bucket) { node_ptr pos = *it; @@ -639,8 +639,8 @@ namespace boost { namespace unordered_detail { return count; } - template - std::size_t hash_table::erase_key(key_type const& k) + template + std::size_t hash_table::erase_key(key_type const& k) { if(!this->size_) return 0; @@ -653,9 +653,9 @@ namespace boost { namespace unordered_detail { } - template - BOOST_DEDUCED_TYPENAME hash_table::iterator_base - hash_table::erase(iterator_base r) + template + BOOST_DEDUCED_TYPENAME T::iterator_base + hash_table::erase(iterator_base r) { BOOST_ASSERT(r.node_); iterator_base next = r; @@ -668,9 +668,9 @@ namespace boost { namespace unordered_detail { return next; } - template - BOOST_DEDUCED_TYPENAME hash_table::iterator_base - hash_table::erase_range( + template + BOOST_DEDUCED_TYPENAME T::iterator_base + hash_table::erase_range( iterator_base r1, iterator_base r2) { if(r1 != r2) @@ -713,9 +713,9 @@ namespace boost { namespace unordered_detail { return r2; } - template - BOOST_DEDUCED_TYPENAME hash_table::iterator_base - hash_table::emplace_empty_impl_with_node( + template + BOOST_DEDUCED_TYPENAME hash_table::iterator_base + hash_table::emplace_empty_impl_with_node( node_constructor& a, std::size_t size) { key_type const& k = get_key(a.value()); diff --git a/include/boost/unordered/detail/unique.hpp b/include/boost/unordered/detail/unique.hpp index 3d89d7db..79ba28e6 100644 --- a/include/boost/unordered/detail/unique.hpp +++ b/include/boost/unordered/detail/unique.hpp @@ -15,9 +15,9 @@ namespace boost { namespace unordered_detail { //////////////////////////////////////////////////////////////////////////// // Equality - template - bool hash_unique_table - ::equals(hash_unique_table const& other) const + template + bool hash_unique_table + ::equals(hash_unique_table const& other) const { if(this->size_ != other.size_) return false; if(!this->size_) return true; @@ -43,9 +43,9 @@ namespace boost { namespace unordered_detail { //////////////////////////////////////////////////////////////////////////// // A convenience method for adding nodes. - template - inline BOOST_DEDUCED_TYPENAME hash_unique_table::node_ptr - hash_unique_table::add_node(node_constructor& a, + template + inline BOOST_DEDUCED_TYPENAME hash_unique_table::node_ptr + hash_unique_table::add_node(node_constructor& a, bucket_ptr bucket) { node_ptr n = a.release(); @@ -61,9 +61,9 @@ namespace boost { namespace unordered_detail { // if hash function throws, basic exception safety // strong otherwise - template - BOOST_DEDUCED_TYPENAME hash_unique_table::value_type& - hash_unique_table::operator[](key_type const& k) + template + BOOST_DEDUCED_TYPENAME hash_unique_table::value_type& + hash_unique_table::operator[](key_type const& k) { typedef BOOST_DEDUCED_TYPENAME value_type::second_type mapped_type; @@ -100,9 +100,9 @@ namespace boost { namespace unordered_detail { } } - template - inline BOOST_DEDUCED_TYPENAME hash_unique_table::emplace_return - hash_unique_table::emplace_impl_with_node(node_constructor& a) + template + inline BOOST_DEDUCED_TYPENAME hash_unique_table::emplace_return + hash_unique_table::emplace_impl_with_node(node_constructor& a) { // No side effects in this initial code key_type const& k = this->get_key(a.value()); @@ -129,10 +129,10 @@ namespace boost { namespace unordered_detail { #if defined(BOOST_UNORDERED_STD_FORWARD) - template + template template - inline BOOST_DEDUCED_TYPENAME hash_unique_table::emplace_return - hash_unique_table::emplace_impl(key_type const& k, + inline BOOST_DEDUCED_TYPENAME hash_unique_table::emplace_return + hash_unique_table::emplace_impl(key_type const& k, Args&&... args) { // No side effects in this initial code @@ -166,10 +166,10 @@ namespace boost { namespace unordered_detail { } } - template + template template - inline BOOST_DEDUCED_TYPENAME hash_unique_table::emplace_return - hash_unique_table::emplace_impl(no_key, Args&&... args) + inline BOOST_DEDUCED_TYPENAME hash_unique_table::emplace_return + hash_unique_table::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 @@ -178,10 +178,10 @@ namespace boost { namespace unordered_detail { return emplace_impl_with_node(a); } - template + template template - inline BOOST_DEDUCED_TYPENAME hash_unique_table::emplace_return - hash_unique_table::emplace_empty_impl(Args&&... args) + inline BOOST_DEDUCED_TYPENAME hash_unique_table::emplace_return + hash_unique_table::emplace_empty_impl(Args&&... args) { node_constructor a(*this); a.construct(std::forward(args)...); @@ -191,11 +191,11 @@ namespace boost { namespace unordered_detail { #else #define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \ - template \ + template \ template \ inline BOOST_DEDUCED_TYPENAME \ - hash_unique_table::emplace_return \ - hash_unique_table::emplace_impl( \ + hash_unique_table::emplace_return \ + hash_unique_table::emplace_impl( \ key_type const& k, \ BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \ { \ @@ -218,11 +218,11 @@ namespace boost { namespace unordered_detail { } \ } \ \ - template \ + template \ template \ inline BOOST_DEDUCED_TYPENAME \ - hash_unique_table::emplace_return \ - hash_unique_table:: \ + hash_unique_table::emplace_return \ + hash_unique_table:: \ emplace_impl(no_key, \ BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \ { \ @@ -231,17 +231,17 @@ namespace boost { namespace unordered_detail { return emplace_impl_with_node(a); \ } \ \ - template \ + template \ template \ inline BOOST_DEDUCED_TYPENAME \ - hash_unique_table::emplace_return \ - hash_unique_table:: \ + hash_unique_table::emplace_return \ + hash_unique_table:: \ emplace_empty_impl( \ BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \ { \ node_constructor a(*this); \ a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \ - return emplace_return(this->emplace_empty_impl_with_node(a, 1), true); \ + return emplace_return(this->emplace_empty_impl_with_node(a, 1), true); \ } BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, @@ -259,10 +259,10 @@ namespace boost { namespace unordered_detail { // if hash function throws, basic exception safety // strong otherwise - template + template template - BOOST_DEDUCED_TYPENAME hash_unique_table::emplace_return - hash_unique_table::emplace(Args&&... args) + BOOST_DEDUCED_TYPENAME hash_unique_table::emplace_return + hash_unique_table::emplace(Args&&... args) { return this->size_ ? emplace_impl( @@ -273,10 +273,10 @@ namespace boost { namespace unordered_detail { #else - template + template template - BOOST_DEDUCED_TYPENAME hash_unique_table::emplace_return - hash_unique_table::emplace(Arg0 const& arg0) + BOOST_DEDUCED_TYPENAME hash_unique_table::emplace_return + hash_unique_table::emplace(Arg0 const& arg0) { return this->size_ ? emplace_impl(extractor::extract(arg0), arg0) : @@ -284,10 +284,10 @@ namespace boost { namespace unordered_detail { } #define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \ - template \ + template \ template \ - BOOST_DEDUCED_TYPENAME hash_unique_table::emplace_return \ - hash_unique_table::emplace( \ + BOOST_DEDUCED_TYPENAME hash_unique_table::emplace_return \ + hash_unique_table::emplace( \ BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \ { \ return this->size_ ? \ @@ -307,9 +307,9 @@ namespace boost { namespace unordered_detail { //////////////////////////////////////////////////////////////////////////// // Insert range methods - template + template template - inline void hash_unique_table::insert_range_impl( + inline void hash_unique_table::insert_range_impl( key_type const&, InputIt i, InputIt j) { node_constructor a(*this); @@ -352,9 +352,9 @@ namespace boost { namespace unordered_detail { } while(++i != j); } - template + template template - inline void hash_unique_table::insert_range_impl( + inline void hash_unique_table::insert_range_impl( no_key, InputIt i, InputIt j) { node_constructor a(*this); @@ -375,9 +375,9 @@ namespace boost { namespace unordered_detail { // if hash function throws, or inserting > 1 element, basic exception safety // strong otherwise - template + template template - void hash_unique_table::insert_range(InputIt i, InputIt j) + void hash_unique_table::insert_range(InputIt i, InputIt j) { if(i != j) return insert_range_impl(extractor::extract(*i), i, j); diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index 8fab6e65..b0034116 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -58,10 +58,11 @@ namespace boost allocator_type, value_type>::type value_allocator; - typedef boost::unordered_detail::hash_unique_table table; + typedef boost::unordered_detail::map types; + typedef BOOST_DEDUCED_TYPENAME types::impl table; - typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base; + typedef BOOST_DEDUCED_TYPENAME types::iterator_base iterator_base; public: @@ -96,7 +97,7 @@ namespace boost table table_; - BOOST_DEDUCED_TYPENAME table::iterator_base const& + BOOST_DEDUCED_TYPENAME types::iterator_base const& get(const_iterator const& it) { return boost::unordered_detail::iterator_access::get(it); @@ -553,14 +554,17 @@ namespace boost #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582) private: #endif + typedef BOOST_DEDUCED_TYPENAME boost::unordered_detail::rebind_wrap< allocator_type, value_type>::type value_allocator; - typedef boost::unordered_detail::hash_equivalent_table table; - typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base; + typedef boost::unordered_detail::multimap types; + typedef BOOST_DEDUCED_TYPENAME types::impl table; + + typedef BOOST_DEDUCED_TYPENAME types::iterator_base iterator_base; public: @@ -595,7 +599,7 @@ namespace boost table table_; - BOOST_DEDUCED_TYPENAME table::iterator_base const& + BOOST_DEDUCED_TYPENAME types::iterator_base const& get(const_iterator const& it) { return boost::unordered_detail::iterator_access::get(it); diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index 16418c11..26c5090a 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -58,9 +58,11 @@ namespace boost allocator_type, value_type>::type value_allocator; - typedef boost::unordered_detail::hash_unique_table table; - typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base; + typedef boost::unordered_detail::set types; + typedef BOOST_DEDUCED_TYPENAME types::impl table; + + typedef BOOST_DEDUCED_TYPENAME types::iterator_base iterator_base; public: @@ -91,7 +93,7 @@ namespace boost table table_; - BOOST_DEDUCED_TYPENAME table::iterator_base const& + BOOST_DEDUCED_TYPENAME types::iterator_base const& get(const_iterator const& it) { return boost::unordered_detail::iterator_access::get(it); @@ -518,14 +520,17 @@ namespace boost #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582) private: #endif + typedef BOOST_DEDUCED_TYPENAME boost::unordered_detail::rebind_wrap< allocator_type, value_type>::type value_allocator; - typedef boost::unordered_detail::hash_equivalent_table table; - typedef BOOST_DEDUCED_TYPENAME table::iterator_base iterator_base; + typedef boost::unordered_detail::multiset types; + typedef BOOST_DEDUCED_TYPENAME types::impl table; + + typedef BOOST_DEDUCED_TYPENAME types::iterator_base iterator_base; public: @@ -556,7 +561,7 @@ namespace boost table table_; - BOOST_DEDUCED_TYPENAME table::iterator_base const& + BOOST_DEDUCED_TYPENAME types::iterator_base const& get(const_iterator const& it) { return boost::unordered_detail::iterator_access::get(it); diff --git a/test/helpers/allocator.hpp b/test/helpers/allocator.hpp index e41259b0..5482baa0 100644 --- a/test/helpers/allocator.hpp +++ b/test/helpers/allocator.hpp @@ -58,8 +58,8 @@ namespace test return (std::numeric_limits::max)(); } - bool operator==(malloc_allocator const& x) const { return true; } - bool operator!=(malloc_allocator const& x) const { return false; } + bool operator==(malloc_allocator const&) const { return true; } + bool operator!=(malloc_allocator const&) const { return false; } #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) template void deallocate(T* p, size_type) { diff --git a/test/unordered/Jamfile.v2 b/test/unordered/Jamfile.v2 index 5cae0605..2fdfd357 100644 --- a/test/unordered/Jamfile.v2 +++ b/test/unordered/Jamfile.v2 @@ -25,6 +25,7 @@ test-suite unordered [ run compile_set.cpp ] [ run compile_map.cpp ] [ run link_test_1.cpp link_test_2.cpp ] + [ run incomplete_test.cpp ] [ run simple_tests.cpp ] [ run equivalent_keys_tests.cpp ] [ run constructor_tests.cpp ] diff --git a/test/unordered/incomplete_test.cpp b/test/unordered/incomplete_test.cpp new file mode 100644 index 00000000..01f4c530 --- /dev/null +++ b/test/unordered/incomplete_test.cpp @@ -0,0 +1,39 @@ + +// Copyright 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) + +#include +#include + +namespace test +{ + struct value; + struct hash; + struct equals; + template + struct malloc_allocator; + + typedef boost::unordered_map > > map; + typedef boost::unordered_multimap > > multimap; + typedef boost::unordered_set > set; + typedef boost::unordered_multiset > multiset; + + struct value {}; + struct hash { std::size_t operator()(value const&) const { return 0; } }; + struct equals { bool operator()(value const&, value const&) const { return true; } }; +} + +#include "../helpers/allocator.hpp" + +int main() { + test::map m1; + test::multimap m2; + test::set s1; + test::multiset s2; + + m1[test::value()] = test::value(); + m2.insert(std::make_pair(test::value(), test::value())); + s1.insert(test::value()); + s2.insert(test::value()); +} \ No newline at end of file