[PATCH] D16360: unordered_map: Avoid unnecessary mallocs when no insert occurs

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Sun Jan 24 19:25:54 PST 2016


EricWF added a comment.

Alright, so this is looking really good.  Once we land this would you be interested in applying the same optimization to `emplace` calls?


================
Comment at: include/__hash_table:863
@@ -862,2 +862,3 @@
     _LIBCPP_INLINE_VISIBILITY
-    pair<iterator, bool> __insert_unique_value(_ValueTp&& __x);
+    pair<iterator, bool> __insert_unique_value(_ValueTp&& __x)
+        {return __insert_unique_key_value(__x, std::forward<_ValueTp>(__x));}
----------------
Woops, I know this was my suggestion, but I don't see any reason to have this function.

Please remove `__insert_unique_value`. Callers can call `__insert_unique_key_value` directly.

================
Comment at: include/__hash_table:875
@@ -867,1 +874,3 @@
+    _LIBCPP_INLINE_VISIBILITY
+    pair<iterator, bool> __insert_unique_key_value(const _ValueTp& __key, const _ValueTp& __x);
 #endif
----------------
Please use the following signature for this overload:

```
template <class _KeyLike, class _ValueTp>
pair<iterator, bool> __insert_unique_key_value(const _KeyTp& __key, const _ValueTp& __x);
```
Using `_ValueTp` twice in C++03, but `_KeyTp` in C++11 is confusing.
I understand that in C++03 `_KeyTp` should always be `_ValueTp` but it took me 10 minutes to realize that.
 

================
Comment at: include/unordered_map:401
@@ -400,1 +400,3 @@
         {return static_cast<const _Hash&>(*this)(__x.__cc.first);}
+#if defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES)
+    _LIBCPP_INLINE_VISIBILITY
----------------
Is there a reason your hiding these overloads in C++11 and beyond?

I would prefer as few conditional compilation blocks as possible.



================
Comment at: include/unordered_map:1004
@@ +1003,3 @@
+    _LIBCPP_INLINE_VISIBILITY
+    pair<iterator, bool> __insert_extract_key_if_pair(pair<_FirstTp, _SecondTp>&& __x)
+        {return __insert_extract_key<_FirstTp>(_VSTD::move(__x));}
----------------
Overall the dispatch looks good, but it could be a lot simpler.  Instead of multi-level dispatch I would write a single trait to computer if "_Pp" is a keylike pair. Then `insert(_Pp&&)` just use that to call `__insert_extract_key_if_referenceable` directly using that trait. 

For example:
```
template <class _Key, class _Pair, class _RawPair = typename __uncvref<_RawPair>::type>
struct __is_keylike_pair : false_type {};

template <class _Key, class _Pair, class _First, class _Second>
struct __is_keylike_pair<_Key, _Pair, pair<_First, _Second> > : is_same<typename remove_const<_First>::type, _Key> {};
```

We also should handle `pair<...>&` which you previously didn't have. 


http://reviews.llvm.org/D16360





More information about the cfe-commits mailing list