From 584eaad67a2aefe277ac1a40dac8ef1077745656 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Tue, 20 Oct 2009 23:05:28 +0000 Subject: [PATCH] A couple of bug fixes for unordered containers. Merged revisions 57005-57006 via svnmerge from https://svn.boost.org/svn/boost/trunk ........ r57005 | danieljames | 2009-10-19 20:24:33 +0100 (Mon, 19 Oct 2009) | 6 lines Use normal emplace implementation for emplace_hint and insert with hint. There's a bug in the emplace_hint implementation for unordered containers with equivalent keys. Since my tests missed it, I'm just going to use the normal emplace implementation until I write better tests. ........ r57006 | danieljames | 2009-10-19 20:32:09 +0100 (Mon, 19 Oct 2009) | 1 line Fix allocator for construct from initializer list. ........ [SVN r57027] --- include/boost/unordered/detail/equivalent.hpp | 61 ------------------- include/boost/unordered/detail/fwd.hpp | 10 +-- include/boost/unordered/unordered_map.hpp | 25 ++++---- include/boost/unordered/unordered_set.hpp | 23 ++++--- test/unordered/constructor_tests.cpp | 53 ++++++++++++++++ 5 files changed, 77 insertions(+), 95 deletions(-) diff --git a/include/boost/unordered/detail/equivalent.hpp b/include/boost/unordered/detail/equivalent.hpp index 5f250d62..7e52a609 100644 --- a/include/boost/unordered/detail/equivalent.hpp +++ b/include/boost/unordered/detail/equivalent.hpp @@ -96,36 +96,6 @@ namespace boost { namespace unordered_detail { } } - template - inline BOOST_DEDUCED_TYPENAME - hash_equivalent_table::iterator_base - hash_equivalent_table - ::emplace_hint_impl(iterator_base const& it, node_constructor& a) - { - // equal can throw, but with no effects - if (!it.node_ || !equal(get_key(a.value()), *it)) { - // Use the standard emplace if the iterator doesn't point - // to a matching key. - return emplace_impl(a); - } - else { - // Find the first node in the group - so that the node - // will be added at the end of the group. - - node_ptr start = node::first_in_group(it.node_); - - // reserve has basic exception safety if the hash function - // throws, strong otherwise. - bucket_ptr bucket = this->reserve_for_insert(this->size_ + 1) ? - get_bucket(this->bucket_index(get_key(a.value()))) : - it.bucket_; - - // Nothing after this point can throw - - return iterator_base(bucket, add_node(a, bucket, start)); - } - } - template inline void hash_equivalent_table ::emplace_impl_no_rehash(node_constructor& a) @@ -156,25 +126,6 @@ namespace boost { namespace unordered_detail { return emplace_impl(a); } - // Emplace (equivalent key containers) - // (I'm using an overloaded emplace for both 'insert' and 'emplace') - - // if hash function throws, basic exception safety - // strong otherwise - template - template - BOOST_DEDUCED_TYPENAME hash_equivalent_table::iterator_base - hash_equivalent_table - ::emplace_hint(iterator_base const& it, Args&&... args) - { - // Create the node before rehashing in case it throws an - // exception (need strong safety in such a case). - node_constructor a(*this); - a.construct(std::forward(args)...); - - return emplace_hint_impl(it, a); - } - #else #define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \ @@ -187,18 +138,6 @@ namespace boost { namespace unordered_detail { node_constructor a(*this); \ a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \ return emplace_impl(a); \ - } \ - \ - template \ - template \ - BOOST_DEDUCED_TYPENAME hash_equivalent_table::iterator_base \ - hash_equivalent_table \ - ::emplace_hint(iterator_base const& it, \ - BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \ - { \ - node_constructor a(*this); \ - a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \ - return emplace_hint_impl(it, a); \ } BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, diff --git a/include/boost/unordered/detail/fwd.hpp b/include/boost/unordered/detail/fwd.hpp index 39f85427..3a5e3f73 100644 --- a/include/boost/unordered/detail/fwd.hpp +++ b/include/boost/unordered/detail/fwd.hpp @@ -710,8 +710,6 @@ namespace boost { namespace unordered_detail { // Insert methods iterator_base emplace_impl(node_constructor& a); - iterator_base emplace_hint_impl(iterator_base const& it, - node_constructor& a); void emplace_impl_no_rehash(node_constructor& a); // equals @@ -725,18 +723,12 @@ namespace boost { namespace unordered_detail { template iterator_base emplace(Args&&... args); - template - iterator_base emplace_hint(iterator_base const& it, Args&&... args); #else #define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \ template \ - iterator_base emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \ - \ - template \ - iterator_base emplace_hint(iterator_base const& it, \ - BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); + iterator_base emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_INSERT_IMPL, _) diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index 36b17f78..8fab6e65 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -199,7 +199,7 @@ namespace boost const allocator_type &a = allocator_type()) : table_(boost::unordered_detail::initial_size( list.begin(), list.end(), n), - hf, eql, allocator_type()) + hf, eql, a) { table_.insert_range(list.begin(), list.end()); } @@ -311,7 +311,7 @@ namespace boost template < \ BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \ > \ - iterator emplace_hint(const_iterator hint, \ + iterator emplace_hint(const_iterator, \ BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \ ) \ { \ @@ -332,7 +332,7 @@ namespace boost table_.emplace(obj)); } - iterator insert(const_iterator hint, const value_type& obj) + iterator insert(const_iterator, const value_type& obj) { return iterator(table_.emplace(obj).first); } @@ -699,7 +699,7 @@ namespace boost const allocator_type &a = allocator_type()) : table_(boost::unordered_detail::initial_size( list.begin(), list.end(), n), - hf, eql, allocator_type()) + hf, eql, a) { table_.insert_range(list.begin(), list.end()); } @@ -776,10 +776,9 @@ namespace boost } template - iterator emplace_hint(const_iterator hint, Args&&... args) + iterator emplace_hint(const_iterator, Args&&... args) { - return iterator(table_.emplace_hint(get(hint), - std::forward(args)...)); + return iterator(table_.emplace(std::forward(args)...)); } #else @@ -788,10 +787,10 @@ namespace boost return iterator(table_.emplace(v)); } - iterator emplace_hint(const_iterator hint, + iterator emplace_hint(const_iterator, value_type const& v = value_type()) { - return iterator(table_.emplace_hint(get(hint), v)); + return iterator(table_.emplace(v)); } @@ -812,11 +811,11 @@ namespace boost template < \ BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \ > \ - iterator emplace_hint(const_iterator hint, \ + iterator emplace_hint(const_iterator, \ BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \ ) \ { \ - return iterator(table_.emplace_hint(get(hint), \ + return iterator(table_.emplace( \ BOOST_UNORDERED_CALL_PARAMS(z, n) \ )); \ } @@ -833,9 +832,9 @@ namespace boost return iterator(table_.emplace(obj)); } - iterator insert(const_iterator hint, const value_type& obj) + iterator insert(const_iterator, const value_type& obj) { - return iterator(table_.emplace_hint(get(hint), obj)); + return iterator(table_.emplace(obj)); } template diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index 82446025..16418c11 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -192,7 +192,7 @@ namespace boost const allocator_type &a = allocator_type()) : table_(boost::unordered_detail::initial_size( list.begin(), list.end(), n), - hf, eql, allocator_type()) + hf, eql, a) { table_.insert_range(list.begin(), list.end()); } @@ -326,7 +326,7 @@ namespace boost table_.emplace(obj)); } - iterator insert(const_iterator hint, const value_type& obj) + iterator insert(const_iterator, const value_type& obj) { return iterator(table_.emplace(obj).first); } @@ -658,7 +658,7 @@ namespace boost const allocator_type &a = allocator_type()) : table_(boost::unordered_detail::initial_size( list.begin(), list.end(), n), - hf, eql, allocator_type()) + hf, eql, a) { table_.insert_range(list.begin(), list.end()); } @@ -735,10 +735,9 @@ namespace boost } template - iterator emplace_hint(const_iterator hint, Args&&... args) + iterator emplace_hint(const_iterator, Args&&... args) { - return iterator(table_.emplace_hint(get(hint), - std::forward(args)...)); + return iterator(table_.emplace(std::forward(args)...)); } #else @@ -747,10 +746,10 @@ namespace boost return iterator(table_.emplace(v)); } - iterator emplace_hint(const_iterator hint, + iterator emplace_hint(const_iterator, value_type const& v = value_type()) { - return iterator(table_.emplace_hint(get(hint), v)); + return iterator(table_.emplace(v)); } #define BOOST_UNORDERED_EMPLACE(z, n, _) \ @@ -768,11 +767,11 @@ namespace boost template < \ BOOST_UNORDERED_TEMPLATE_ARGS(z, n) \ > \ - iterator emplace_hint(const_iterator hint, \ + iterator emplace_hint(const_iterator, \ BOOST_UNORDERED_FUNCTION_PARAMS(z, n) \ ) \ { \ - return iterator(table_.emplace_hint(get(hint), \ + return iterator(table_.emplace( \ BOOST_UNORDERED_CALL_PARAMS(z, n) \ )); \ } @@ -789,9 +788,9 @@ namespace boost return iterator(table_.emplace(obj)); } - iterator insert(const_iterator hint, const value_type& obj) + iterator insert(const_iterator, const value_type& obj) { - return iterator(table_.emplace_hint(get(hint), obj)); + return iterator(table_.emplace(obj)); } template diff --git a/test/unordered/constructor_tests.cpp b/test/unordered/constructor_tests.cpp index 0702e4e6..8ddd005c 100644 --- a/test/unordered/constructor_tests.cpp +++ b/test/unordered/constructor_tests.cpp @@ -263,6 +263,59 @@ void constructor_tests2(T*, test::random_generator const& generator = test::defa test::check_container(x, v); test::check_equivalent_keys(x); } + +#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) + std::initializer_list list; + + std::cerr<<"Initializer list construct 1\n"; + { + T x(list); + BOOST_TEST(x.empty()); + BOOST_TEST(test::equivalent(x.hash_function(), hf)); + BOOST_TEST(test::equivalent(x.key_eq(), eq)); + BOOST_TEST(test::equivalent(x.get_allocator(), al)); + } + + std::cerr<<"Initializer list construct 2\n"; + { + T x(list, 1000); + BOOST_TEST(x.empty()); + BOOST_TEST(x.bucket_count() >= 1000); + BOOST_TEST(test::equivalent(x.hash_function(), hf)); + BOOST_TEST(test::equivalent(x.key_eq(), eq)); + BOOST_TEST(test::equivalent(x.get_allocator(), al)); + } + + std::cerr<<"Initializer list construct 3\n"; + { + T x(list, 10, hf1); + BOOST_TEST(x.empty()); + BOOST_TEST(x.bucket_count() >= 10); + BOOST_TEST(test::equivalent(x.hash_function(), hf1)); + BOOST_TEST(test::equivalent(x.key_eq(), eq)); + BOOST_TEST(test::equivalent(x.get_allocator(), al)); + } + + std::cerr<<"Initializer list construct 4\n"; + { + T x(list, 10, hf1, eq1); + BOOST_TEST(x.empty()); + BOOST_TEST(x.bucket_count() >= 10); + BOOST_TEST(test::equivalent(x.hash_function(), hf1)); + BOOST_TEST(test::equivalent(x.key_eq(), eq1)); + BOOST_TEST(test::equivalent(x.get_allocator(), al)); + } + + std::cerr<<"Initializer list construct 5\n"; + { + T x(list, 10, hf1, eq1, al1); + BOOST_TEST(x.empty()); + BOOST_TEST(x.bucket_count() >= 10); + BOOST_TEST(test::equivalent(x.hash_function(), hf1)); + BOOST_TEST(test::equivalent(x.key_eq(), eq1)); + BOOST_TEST(test::equivalent(x.get_allocator(), al1)); + } +#endif } template