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))
+)
}