Skip to content

Commit 2e89627

Browse files
[ADT] Refactor DenseMap::insert, try_emplace, and operator[] (NFC) (llvm#155204)
try_emplace and operator[] contain nearly identical code, and the code is duplicated for l-value and r-value reference variants. This patch introduces a templated helper function, try_emplace_impl, and uses it in all of DenseMap::insert, try_emplace, and operator[]. The helper function uses perfect forwarding to preserve the exact key type.
1 parent 790a132 commit 2e89627

File tree

1 file changed

+18
-27
lines changed

1 file changed

+18
-27
lines changed

llvm/include/llvm/ADT/DenseMap.h

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -240,43 +240,30 @@ class DenseMapBase : public DebugEpochBase {
240240
// If the key is already in the map, it returns false and doesn't update the
241241
// value.
242242
std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
243-
return try_emplace(KV.first, KV.second);
243+
return try_emplace_impl(KV.first, KV.second);
244244
}
245245

246246
// Inserts key,value pair into the map if the key isn't already in the map.
247247
// If the key is already in the map, it returns false and doesn't update the
248248
// value.
249249
std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
250-
return try_emplace(std::move(KV.first), std::move(KV.second));
250+
return try_emplace_impl(std::move(KV.first), std::move(KV.second));
251251
}
252252

253253
// Inserts key,value pair into the map if the key isn't already in the map.
254254
// The value is constructed in-place if the key is not in the map, otherwise
255255
// it is not moved.
256256
template <typename... Ts>
257257
std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&...Args) {
258-
BucketT *TheBucket;
259-
if (LookupBucketFor(Key, TheBucket))
260-
return {makeInsertIterator(TheBucket), false}; // Already in map.
261-
262-
// Otherwise, insert the new element.
263-
TheBucket =
264-
InsertIntoBucket(TheBucket, std::move(Key), std::forward<Ts>(Args)...);
265-
return {makeInsertIterator(TheBucket), true};
258+
return try_emplace_impl(std::move(Key), std::forward<Ts>(Args)...);
266259
}
267260

268261
// Inserts key,value pair into the map if the key isn't already in the map.
269262
// The value is constructed in-place if the key is not in the map, otherwise
270263
// it is not moved.
271264
template <typename... Ts>
272265
std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&...Args) {
273-
BucketT *TheBucket;
274-
if (LookupBucketFor(Key, TheBucket))
275-
return {makeInsertIterator(TheBucket), false}; // Already in map.
276-
277-
// Otherwise, insert the new element.
278-
TheBucket = InsertIntoBucket(TheBucket, Key, std::forward<Ts>(Args)...);
279-
return {makeInsertIterator(TheBucket), true};
266+
return try_emplace_impl(Key, std::forward<Ts>(Args)...);
280267
}
281268

282269
/// Alternate version of insert() which allows a different, and possibly
@@ -360,19 +347,11 @@ class DenseMapBase : public DebugEpochBase {
360347
}
361348

362349
ValueT &operator[](const KeyT &Key) {
363-
BucketT *TheBucket;
364-
if (LookupBucketFor(Key, TheBucket))
365-
return TheBucket->second;
366-
367-
return InsertIntoBucket(TheBucket, Key)->second;
350+
return try_emplace_impl(Key).first->second;
368351
}
369352

370353
ValueT &operator[](KeyT &&Key) {
371-
BucketT *TheBucket;
372-
if (LookupBucketFor(Key, TheBucket))
373-
return TheBucket->second;
374-
375-
return InsertIntoBucket(TheBucket, std::move(Key))->second;
354+
return try_emplace_impl(std::move(Key)).first->second;
376355
}
377356

378357
/// isPointerIntoBucketsArray - Return true if the specified pointer points
@@ -496,6 +475,18 @@ class DenseMapBase : public DebugEpochBase {
496475
static const KeyT getTombstoneKey() { return KeyInfoT::getTombstoneKey(); }
497476

498477
private:
478+
template <typename KeyArgT, typename... Ts>
479+
std::pair<iterator, bool> try_emplace_impl(KeyArgT &&Key, Ts &&...Args) {
480+
BucketT *TheBucket = nullptr;
481+
if (LookupBucketFor(Key, TheBucket))
482+
return {makeInsertIterator(TheBucket), false}; // Already in the map.
483+
484+
// Otherwise, insert the new element.
485+
TheBucket = InsertIntoBucket(TheBucket, std::forward<KeyArgT>(Key),
486+
std::forward<Ts>(Args)...);
487+
return {makeInsertIterator(TheBucket), true};
488+
}
489+
499490
iterator makeIterator(BucketT *P, BucketT *E, DebugEpochBase &Epoch,
500491
bool NoAdvance = false) {
501492
if (shouldReverseIterate<KeyT>()) {

0 commit comments

Comments
 (0)