libstdc++: [_Hashtable] Consider all initializer_list elements are inserted
When instantiated using an initializer_list the container is pre-sized
based on
initializer_list size.
libstdc++-v3/ChangeLog:
* include/bits/hashtable_policy.h
(_Insert_base<>::insert(initializer_list<>)):
Use assignment operator if container is empty and has default
bucket count.
* include/bits/hashtable.h (_Hashtable<>(initializer_list<>)): Use
initializer_list
size as bucket count hint if user did not provide any value that is
to say if it is
the default 0 value.
* testsuite/23_containers/unordered_set/init-list.cc (test02): New
test case.
Tested under Linux x86_64.
François
diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index e53cbaf0644..b0d1bc1f08a 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -575,7 +575,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const _Hash& __hf = _Hash(),
const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type())
- : _Hashtable(__l.begin(), __l.end(), __bkt_count_hint,
+ : _Hashtable(__l.begin(), __l.end(),
+ __bkt_count_hint == 0 ? __l.size() : __bkt_count_hint,
__hf, __eql, __a, __unique_keys{})
{ }
diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h
index e848ba1d3f7..139d0ec27df 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -969,7 +969,16 @@ namespace __detail
void
insert(initializer_list<value_type> __l)
- { this->insert(__l.begin(), __l.end()); }
+ {
+ __hashtable& __h = _M_conjure_hashtable();
+ if (__h.empty() && __h.bucket_count() == 1)
+ {
+ __h = __l;
+ return;
+ }
+
+ this->insert(__l.begin(), __l.end());
+ }
template<typename _InputIterator>
void
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/init-list.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/init-list.cc
index fc11498c718..70789d03e63 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_set/init-list.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/init-list.cc
@@ -48,8 +48,27 @@ void test01()
VERIFY(m.count(1) == 0);
}
+void test02()
+{
+ unordered_set<int> u({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 });
+ VERIFY( u.size() == 13 );
+ VERIFY( u.count(0) == 1 );
+ VERIFY( u.count(13) == 0 );
+
+ auto bkt_count = u.bucket_count();
+ u.insert({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 });
+ VERIFY( u.size() == 13 );
+ VERIFY( u.bucket_count() == bkt_count );
+
+ u.clear();
+ u.insert({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 });
+ VERIFY( u.size() == 13 );
+ VERIFY( u.bucket_count() == bkt_count );
+}
+
int main()
{
__gnu_test::set_memory_limits();
test01();
+ test02();
}