diff --git a/doc/changes.qbk b/doc/changes.qbk index fda6066e..c5cb963c 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -178,6 +178,8 @@ C++11 support has resulted in some breaking changes: [h2 Boost 1.50.0] * Fix equality for `unordered_multiset` and `unordered_multimap`. +* [@https://svn.boost.org/trac/boost/ticket/6857 Ticket 6857]: + Implement `reserve`. * [@https://svn.boost.org/trac/boost/ticket/6771 Ticket 6771]: Avoid gcc's `-Wfloat-equal` warning. * [@https://svn.boost.org/trac/boost/ticket/6784 Ticket 6784]: diff --git a/doc/ref.php b/doc/ref.php index cc871be5..e014555c 100644 --- a/doc/ref.php +++ b/doc/ref.php @@ -963,6 +963,18 @@ EOL; The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + + + size_type + + void + + Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated. + + + The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + + diff --git a/doc/ref.xml b/doc/ref.xml index aecfd0af..9e4e399e 100644 --- a/doc/ref.xml +++ b/doc/ref.xml @@ -846,6 +846,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + + + size_type + + void + + Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated. + + + The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + + @@ -1797,6 +1809,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + + + size_type + + void + + Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated. + + + The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + + @@ -2793,6 +2817,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + + + size_type + + void + + Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated. + + + The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + + @@ -3758,6 +3794,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + + + size_type + + void + + Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated. + + + The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + + diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp index 35515cc7..cbf62195 100644 --- a/include/boost/unordered/detail/table.hpp +++ b/include/boost/unordered/detail/table.hpp @@ -387,6 +387,7 @@ namespace boost { namespace unordered { namespace detail { void reserve_for_insert(std::size_t); void rehash(std::size_t); + void reserve(std::size_t); }; //////////////////////////////////////////////////////////////////////////// @@ -402,7 +403,9 @@ namespace boost { namespace unordered { namespace detail { this->create_buckets(); this->max_load_ = this->calculate_max_load(); } - else if(size >= max_load_) { + // According to the standard this should be 'size >= max_load_', + // but I think this is better, defect report filed. + else if(size > max_load_) { std::size_t num_buckets = this->min_buckets_for_size((std::max)(size, this->size_ + (this->size_ >> 1))); @@ -417,7 +420,7 @@ namespace boost { namespace unordered { namespace detail { // strong otherwise. template - void table::rehash(std::size_t min_buckets) + inline void table::rehash(std::size_t min_buckets) { using namespace std; @@ -437,6 +440,13 @@ namespace boost { namespace unordered { namespace detail { } } } + + template + inline void table::reserve(std::size_t num_elements) + { + rehash(static_cast( + std::ceil(static_cast(num_elements) / this->mlf_))); + } }}} #endif diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index 7378b913..8e6621d4 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -515,6 +515,7 @@ namespace unordered float load_factor() const; void max_load_factor(float); void rehash(size_type); + void reserve(size_type); #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582) friend bool operator==( @@ -997,6 +998,7 @@ namespace unordered float load_factor() const; void max_load_factor(float); void rehash(size_type); + void reserve(size_type); #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582) friend bool operator==( @@ -1300,6 +1302,12 @@ namespace unordered table_.rehash(n); } + template + void unordered_map::reserve(size_type n) + { + table_.reserve(n); + } + template inline bool operator==( unordered_map const& m1, @@ -1606,6 +1614,12 @@ namespace unordered table_.rehash(n); } + template + void unordered_multimap::reserve(size_type n) + { + table_.reserve(n); + } + template inline bool operator==( unordered_multimap const& m1, diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index 1d56c777..a85a1676 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -500,6 +500,7 @@ namespace unordered float load_factor() const; void max_load_factor(float); void rehash(size_type); + void reserve(size_type); #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582) friend bool operator==( @@ -972,6 +973,7 @@ namespace unordered float load_factor() const; void max_load_factor(float); void rehash(size_type); + void reserve(size_type); #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582) friend bool operator==( @@ -1226,6 +1228,12 @@ namespace unordered table_.rehash(n); } + template + void unordered_set::reserve(size_type n) + { + table_.reserve(n); + } + template inline bool operator==( unordered_set const& m1, @@ -1504,6 +1512,12 @@ namespace unordered table_.rehash(n); } + template + void unordered_multiset::reserve(size_type n) + { + table_.reserve(n); + } + template inline bool operator==( unordered_multiset const& m1, diff --git a/test/unordered/rehash_tests.cpp b/test/unordered/rehash_tests.cpp index 252c660e..06c6a844 100644 --- a/test/unordered/rehash_tests.cpp +++ b/test/unordered/rehash_tests.cpp @@ -100,6 +100,34 @@ void rehash_test1(X* = 0, tracker.compare(x); } +template +void reserve_test(X* = 0, + test::random_generator generator = test::default_generator) +{ + for (int random_mlf = 0; random_mlf < 2; ++random_mlf) + { + for (int i = 0; i < 2000; i += i < 50 ? 1 : 13) + { + test::random_values v(i, generator); + + test::ordered tracker; + tracker.insert_range(v.begin(), v.end()); + + X x; + x.max_load_factor(random_mlf ? + static_cast(std::rand() % 1000) / 500.0 + 0.5f : 1.0f); + // For the current standard this should reserve i+1, I've + // submitted a defect report and will assume it's a defect + // for now. + x.reserve(i); + std::size_t bucket_count = x.bucket_count(); + x.insert(v.begin(), v.end()); + BOOST_TEST(bucket_count == x.bucket_count()); + tracker.compare(x); + } + } +} + boost::unordered_set* int_set_ptr; boost::unordered_multiset* int_multiset_ptr; boost::unordered_map* int_map_ptr; @@ -117,6 +145,9 @@ UNORDERED_TEST(rehash_empty_test3, UNORDERED_TEST(rehash_test1, ((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr)) ) +UNORDERED_TEST(reserve_test, + ((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr)) +) }