diff mbox series

[01/12] libstdc++: Refactor _Hashtable::operator=(initializer_list<value_type>)

Message ID 20241108154548.813315-2-jwakely@redhat.com
State New
Headers show
Series libstdc++: Refactor _Hashtable class | expand

Commit Message

Jonathan Wakely Nov. 8, 2024, 3:30 p.m. UTC
This replaces a call to _M_insert_range with open coding the loop. This
will allow removing the node generator parameter from _M_insert_range in
a later commit.

libstdc++-v3/ChangeLog:

	* include/bits/hashtable.h (operator=(initializer_list)):
	Refactor to not use _M_insert_range.

Reviewed-by: François Dumont <fdumont@gcc.gnu.org>
---
 libstdc++-v3/include/bits/hashtable.h | 35 ++++++++++++++++++++++++---
 1 file changed, 32 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index b36142b358a..872fcac22d0 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -610,6 +610,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	return *this;
       }
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
       _Hashtable&
       operator=(initializer_list<value_type> __l)
       {
@@ -617,16 +619,43 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	_M_before_begin._M_nxt = nullptr;
 	clear();
 
-	// We consider that all elements of __l are going to be inserted.
+	// We assume that all elements of __l are likely to be inserted.
 	auto __l_bkt_count = _M_rehash_policy._M_bkt_for_elements(__l.size());
 
-	// Do not shrink to keep potential user reservation.
+	// Excess buckets might have been intentionally reserved by the user,
+	// so rehash if we need to grow, but don't shrink.
 	if (_M_bucket_count < __l_bkt_count)
 	  rehash(__l_bkt_count);
 
-	this->_M_insert_range(__l.begin(), __l.end(), __roan, __unique_keys{});
+	_ExtractKey __ex;
+	for (auto& __e : __l)
+	  {
+	    const key_type& __k = __ex(__e);
+
+	    if constexpr (__unique_keys::value)
+	      if (this->size() <= __small_size_threshold())
+		{
+		  auto __it = _M_begin();
+		  for (; __it; __it = __it->_M_next())
+		    if (this->_M_key_equals(__k, *__it))
+		      break;
+		  if (__it)
+		    continue; // Found existing element with equivalent key
+		}
+
+	    __hash_code __code = this->_M_hash_code(__k);
+	    size_type __bkt = _M_bucket_index(__code);
+
+	    if constexpr (__unique_keys::value)
+	      if (_M_find_node(__bkt, __k, __code))
+		continue; // Found existing element with equivalent key
+
+	    _M_insert_unique_node(__bkt, __code, __roan(__e));
+	  }
+
 	return *this;
       }
+#pragma GCC diagnostic pop
 
       ~_Hashtable() noexcept;