]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Refactor _Hashtable::operator=(initializer_list<value_type>)
authorJonathan Wakely <jwakely@redhat.com>
Fri, 1 Nov 2024 12:44:00 +0000 (12:44 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Wed, 13 Nov 2024 20:21:38 +0000 (20:21 +0000)
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

index b36142b358a701e2e007ce8acf2ccfc2c4885bb8..872fcac22d0953cc6690c296daaa23ea0466f028 100644 (file)
@@ -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;