From 5edc45349f07e4252cd3f5d92a7962ff050a73bb Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 21 May 2010 07:06:33 +0000 Subject: [PATCH] Revert changes for sun 5.9. Nobody seems to be running the tests now. [SVN r62117] --- include/boost/unordered/detail/equivalent.hpp | 304 ++++---- include/boost/unordered/detail/fwd.hpp | 24 +- include/boost/unordered/detail/node.hpp | 6 + include/boost/unordered/detail/table.hpp | 17 + include/boost/unordered/detail/unique.hpp | 663 ++++++++++-------- 5 files changed, 575 insertions(+), 439 deletions(-) diff --git a/include/boost/unordered/detail/equivalent.hpp b/include/boost/unordered/detail/equivalent.hpp index df7401f2..1c497c32 100644 --- a/include/boost/unordered/detail/equivalent.hpp +++ b/include/boost/unordered/detail/equivalent.hpp @@ -47,150 +47,41 @@ namespace boost { namespace unordered_detail { : table(x, a, m) {} ~hash_equivalent_table() {} + // Insert methods + + iterator_base emplace_impl(node_constructor& a); + void emplace_impl_no_rehash(node_constructor& a); + // equals bool equals(hash_equivalent_table const&) const; - //////////////////////////////////////////////////////////////////////// - // A convenience method for adding nodes. - - 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; - } - - //////////////////////////////////////////////////////////////////////// - // Insert methods - - inline iterator_base emplace_impl(node_constructor& a) - { - key_type const& k = this->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 = this->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)); - } - } - - inline void emplace_impl_no_rehash(node_constructor& a) - { - key_type const& k = this->get_key(a.value()); - bucket_ptr bucket = this->get_bucket(this->bucket_index(k)); - add_node(a, bucket, this->find_iterator(bucket, k)); - } + inline node_ptr add_node(node_constructor& a, + bucket_ptr bucket, node_ptr pos); #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 - 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)...); - - return emplace_impl(a); - } - + iterator_base emplace(Args&&... args); + #else - -#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \ - template \ - iterator_base emplace( \ - BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \ - { \ - node_constructor a(*this); \ - a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \ - return emplace_impl(a); \ - } - + +#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \ + template \ + iterator_base emplace(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 - - //////////////////////////////////////////////////////////////////////////// - // Insert range methods - // if hash function throws, or inserting > 1 element, basic exception safety - // strong otherwise template - inline void 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 + void insert_for_range(I i, I j, forward_traversal_tag); template - inline 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); - } - } - - // if hash function throws, or inserting > 1 element, basic exception - // safety strong otherwise + void insert_for_range(I i, I j, boost::incrementable_traversal_tag); template - void insert_range(I i, I j) - { - BOOST_DEDUCED_TYPENAME boost::iterator_traversal::type - iterator_traversal_tag; - insert_for_range(i, j, iterator_traversal_tag); - } + void insert_range(I i, I j); }; template @@ -251,6 +142,163 @@ namespace boost { namespace unordered_detail { return true; } + + //////////////////////////////////////////////////////////////////////////// + // A convenience method for adding nodes. + + 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(); + 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 + inline BOOST_DEDUCED_TYPENAME + 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); + + 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 = this->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 + inline void hash_equivalent_table + ::emplace_impl_no_rehash(node_constructor& a) + { + key_type const& k = this->get_key(a.value()); + bucket_ptr bucket = this->get_bucket(this->bucket_index(k)); + add_node(a, bucket, this->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 + template + BOOST_DEDUCED_TYPENAME hash_equivalent_table::iterator_base + hash_equivalent_table + ::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)...); + + return emplace_impl(a); + } + +#else + +#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \ + template \ + template \ + BOOST_DEDUCED_TYPENAME hash_equivalent_table::iterator_base \ + hash_equivalent_table \ + ::emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \ + { \ + node_constructor a(*this); \ + a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \ + return emplace_impl(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 + template + inline void hash_equivalent_table + ::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 + template + inline void hash_equivalent_table + ::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 + template + template + void hash_equivalent_table::insert_range(I i, I j) + { + BOOST_DEDUCED_TYPENAME boost::iterator_traversal::type + iterator_traversal_tag; + insert_for_range(i, j, iterator_traversal_tag); + } }} #endif diff --git a/include/boost/unordered/detail/fwd.hpp b/include/boost/unordered/detail/fwd.hpp index 4adeb592..be4d5e1a 100644 --- a/include/boost/unordered/detail/fwd.hpp +++ b/include/boost/unordered/detail/fwd.hpp @@ -58,12 +58,6 @@ #endif -#if BOOST_WORKAROUND(__BORLANDC__, <= 0X0582) -#define BOOST_UNORDERED_BORLAND_BOOL(x) (bool)(x) -#else -#define BOOST_UNORDERED_BORLAND_BOOL(x) x -#endif - namespace boost { namespace unordered_detail { static const float minimum_max_load_factor = 1e-3f; @@ -475,25 +469,13 @@ namespace boost { namespace unordered_detail { return extractor::extract(node::get_value(n)); } bool equal(key_type const& k, value_type const& v) const; - template - inline node_ptr find_iterator(bucket_ptr bucket, Key const& k, - Pred const& eq) const - { - node_ptr it = bucket->next_; - while (BOOST_UNORDERED_BORLAND_BOOL(it) && - !eq(k, get_key(node::get_value(it)))) - { - it = node::next_group(it); - } - - return it; - } - + node_ptr find_iterator(bucket_ptr bucket, Key const& k, + Pred const&) const; node_ptr find_iterator(bucket_ptr bucket, key_type const& k) const; node_ptr find_iterator(key_type const& k) const; node_ptr* find_for_erase(bucket_ptr bucket, key_type const& k) const; - + // Load methods std::size_t max_size() const; diff --git a/include/boost/unordered/detail/node.hpp b/include/boost/unordered/detail/node.hpp index c2553bef..85a31410 100644 --- a/include/boost/unordered/detail/node.hpp +++ b/include/boost/unordered/detail/node.hpp @@ -16,6 +16,12 @@ #include #include +#if BOOST_WORKAROUND(__BORLANDC__, <= 0X0582) +#define BOOST_UNORDERED_BORLAND_BOOL(x) (bool)(x) +#else +#define BOOST_UNORDERED_BORLAND_BOOL(x) x +#endif + namespace boost { namespace unordered_detail { //////////////////////////////////////////////////////////////////////////// diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp index fca6113d..d37c0155 100644 --- a/include/boost/unordered/detail/table.hpp +++ b/include/boost/unordered/detail/table.hpp @@ -29,6 +29,23 @@ namespace boost { namespace unordered_detail { return this->key_eq()(k, get_key(v)); } + // strong exception safety, no side effects + template + template + inline BOOST_DEDUCED_TYPENAME T::node_ptr + hash_table::find_iterator(bucket_ptr bucket, Key const& k, + Pred const& eq) const + { + node_ptr it = bucket->next_; + while (BOOST_UNORDERED_BORLAND_BOOL(it) && + !eq(k, get_key(node::get_value(it)))) + { + it = node::next_group(it); + } + + return it; + } + // strong exception safety, no side effects template inline BOOST_DEDUCED_TYPENAME T::node_ptr diff --git a/include/boost/unordered/detail/unique.hpp b/include/boost/unordered/detail/unique.hpp index 19fe7de8..7ad367fe 100644 --- a/include/boost/unordered/detail/unique.hpp +++ b/include/boost/unordered/detail/unique.hpp @@ -48,190 +48,43 @@ namespace boost { namespace unordered_detail { : 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; - //////////////////////////////////////////////////////////////////////// - // A convenience method for adding nodes. - - 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; - } + node_ptr add_node(node_constructor& a, bucket_ptr bucket); - //////////////////////////////////////////////////////////////////////// - // Insert methods - - // if hash function throws, basic exception safety - // strong otherwise - value_type& 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 = this->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)); - } - } - - inline emplace_return emplace_impl_with_node(node_constructor& a) - { - // No side effects in this initial code - key_type const& k = this->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 = this->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 - inline emplace_return 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 = this->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)...); - - // 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); - } - } - + emplace_return emplace(Args&&... args); template - inline emplace_return 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)...); - return emplace_impl_with_node(a); - } - + emplace_return emplace_impl(key_type const& k, Args&&... args); template - inline emplace_return emplace_empty_impl(Args&&... args) - { - node_constructor a(*this); - a.construct(std::forward(args)...); - return emplace_return(this->emplace_empty_impl_with_node(a, 1), - true); - } - + emplace_return emplace_impl(no_key, Args&&... args); + template + emplace_return emplace_empty_impl(Args&&... args); #else -#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \ - template \ - inline emplace_return emplace_impl( \ - key_type const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \ - { \ - std::size_t hash_value = this->hash_function()(k); \ - bucket_ptr bucket \ - = this->bucket_ptr_from_hash(hash_value); \ - node_ptr pos = this->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, num_params)); \ - \ - 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 \ - inline emplace_return emplace_impl( \ - no_key, BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \ - { \ - node_constructor a(*this); \ - a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \ - return emplace_impl_with_node(a); \ - } \ - \ - template \ - inline emplace_return 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); \ - } - +#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \ + template \ + emplace_return emplace( \ + BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \ + template \ + emplace_return emplace_impl(key_type const& k, \ + BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \ + template \ + emplace_return emplace_impl(no_key, \ + BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \ + template \ + emplace_return emplace_empty_impl( \ + BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); + BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_INSERT_IMPL, _) @@ -239,127 +92,14 @@ namespace boost { namespace unordered_detail { #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 - emplace_return emplace(Args&&... args) - { - return this->size_ ? - emplace_impl( - extractor::extract(std::forward(args)...), - std::forward(args)...) : - emplace_empty_impl(std::forward(args)...); - } - -#else - - template - emplace_return emplace(Arg0 const& arg0) - { - return this->size_ ? - emplace_impl(extractor::extract(arg0), arg0) : - emplace_empty_impl(arg0); - } - -#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \ - template \ - emplace_return emplace( \ - BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \ - { \ - return this->size_ ? \ - emplace_impl(extractor::extract(arg0, arg1), \ - BOOST_UNORDERED_CALL_PARAMS(z, num_params)) : \ - emplace_empty_impl( \ - BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \ - } - - BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT, - BOOST_UNORDERED_INSERT_IMPL, _) - -#undef BOOST_UNORDERED_INSERT_IMPL - -#endif - - //////////////////////////////////////////////////////////////////////// - // Insert range methods - - template - inline void 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 - it - // could be a pair with first_types as key_type without const or - // a different second_type. - 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 = this->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 - inline void 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 - void insert_range(InputIt i, InputIt j) - { - if(i != j) - return insert_range_impl(extractor::extract(*i), i, j); - } + void insert_range(InputIt i, InputIt j); + template + void insert_range_impl(key_type const&, InputIt i, InputIt j); + template + void insert_range_impl(no_key, InputIt i, InputIt j); }; template @@ -412,6 +152,349 @@ namespace boost { namespace unordered_detail { return true; } + + //////////////////////////////////////////////////////////////////////////// + // A convenience method for adding nodes. + + 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(); + 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 + 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; + + 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 = this->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 + 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()); + std::size_t hash_value = this->hash_function()(k); + bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value); + node_ptr pos = this->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 + template + 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 + std::size_t hash_value = this->hash_function()(k); + bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value); + node_ptr pos = this->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)...); + + // 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 + template + 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 + node_constructor a(*this); + a.construct(std::forward(args)...); + return emplace_impl_with_node(a); + } + + template + template + 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)...); + return emplace_return(this->emplace_empty_impl_with_node(a, 1), true); + } + +#else + +#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \ + template \ + template \ + inline BOOST_DEDUCED_TYPENAME \ + hash_unique_table::emplace_return \ + hash_unique_table::emplace_impl( \ + key_type const& k, \ + BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \ + { \ + std::size_t hash_value = this->hash_function()(k); \ + bucket_ptr bucket \ + = this->bucket_ptr_from_hash(hash_value); \ + node_ptr pos = this->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, num_params)); \ + \ + 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 \ + template \ + inline BOOST_DEDUCED_TYPENAME \ + hash_unique_table::emplace_return \ + hash_unique_table:: \ + emplace_impl(no_key, \ + BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \ + { \ + node_constructor a(*this); \ + a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \ + return emplace_impl_with_node(a); \ + } \ + \ + template \ + template \ + inline BOOST_DEDUCED_TYPENAME \ + 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); \ + } + + 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 + template + BOOST_DEDUCED_TYPENAME hash_unique_table::emplace_return + hash_unique_table::emplace(Args&&... args) + { + return this->size_ ? + emplace_impl( + extractor::extract(std::forward(args)...), + std::forward(args)...) : + emplace_empty_impl(std::forward(args)...); + } + +#else + + template + template + BOOST_DEDUCED_TYPENAME hash_unique_table::emplace_return + hash_unique_table::emplace(Arg0 const& arg0) + { + return this->size_ ? + emplace_impl(extractor::extract(arg0), arg0) : + emplace_empty_impl(arg0); + } + +#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \ + template \ + template \ + BOOST_DEDUCED_TYPENAME hash_unique_table::emplace_return \ + hash_unique_table::emplace( \ + BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \ + { \ + return this->size_ ? \ + emplace_impl(extractor::extract(arg0, arg1), \ + BOOST_UNORDERED_CALL_PARAMS(z, num_params)) : \ + emplace_empty_impl( \ + BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \ + } + + BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT, + BOOST_UNORDERED_INSERT_IMPL, _) + +#undef BOOST_UNORDERED_INSERT_IMPL + +#endif + + //////////////////////////////////////////////////////////////////////////// + // Insert range methods + + template + template + inline void hash_unique_table::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 - it + // could be a pair with first_types as key_type without const or a + // different second_type. + 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 = this->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 + template + inline void hash_unique_table::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 + template + void hash_unique_table::insert_range(InputIt i, InputIt j) + { + if(i != j) + return insert_range_impl(extractor::extract(*i), i, j); + } }} #endif