[llvm] [DenseMap] Introduce emplace_or_assign (PR #138886)
via llvm-commits
llvm-commits at lists.llvm.org
Wed May 7 07:50:50 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-adt
Author: Ramkumar Ramachandra (artagnon)
<details>
<summary>Changes</summary>
Introduce emplace_or_assign, a variant of insert_or_assign that has slightly better characteristics.
---
Full diff: https://github.com/llvm/llvm-project/pull/138886.diff
2 Files Affected:
- (modified) llvm/include/llvm/ADT/DenseMap.h (+16)
- (modified) llvm/unittests/ADT/DenseMapTest.cpp (+35)
``````````diff
diff --git a/llvm/include/llvm/ADT/DenseMap.h b/llvm/include/llvm/ADT/DenseMap.h
index bb99a41646b08..5f4442c777fad 100644
--- a/llvm/include/llvm/ADT/DenseMap.h
+++ b/llvm/include/llvm/ADT/DenseMap.h
@@ -324,6 +324,22 @@ class DenseMapBase : public DebugEpochBase {
return Ret;
}
+ template <typename... Ts>
+ std::pair<iterator, bool> emplace_or_assign(const KeyT &Key, Ts &&...Args) {
+ auto Ret = try_emplace(Key, std::forward<Ts>(Args)...);
+ if (!Ret.second)
+ Ret.first->second = ValueT(std::forward<Ts>(Args)...);
+ return Ret;
+ }
+
+ template <typename... Ts>
+ std::pair<iterator, bool> emplace_or_assign(KeyT &&Key, Ts &&...Args) {
+ auto Ret = try_emplace(std::move(Key), std::forward<Ts>(Args)...);
+ if (!Ret.second)
+ Ret.first->second = ValueT(std::forward<Ts>(Args)...);
+ return Ret;
+ }
+
bool erase(const KeyT &Val) {
BucketT *TheBucket = doFind(Val);
if (!TheBucket)
diff --git a/llvm/unittests/ADT/DenseMapTest.cpp b/llvm/unittests/ADT/DenseMapTest.cpp
index a4c045585fc28..c8a131b4f5f7e 100644
--- a/llvm/unittests/ADT/DenseMapTest.cpp
+++ b/llvm/unittests/ADT/DenseMapTest.cpp
@@ -545,6 +545,41 @@ TEST(DenseMapCustomTest, InsertOrAssignTest) {
EXPECT_EQ(1, CountCopyAndMove::MoveAssignments);
}
+TEST(DenseMapCustomTest, EmplaceOrAssign) {
+ DenseMap<int, CountCopyAndMove> Map;
+
+ CountCopyAndMove::ResetCounts();
+ auto Try0 = Map.emplace_or_assign(3, 3);
+ EXPECT_TRUE(Try0.second);
+ EXPECT_EQ(0, CountCopyAndMove::TotalCopies());
+ EXPECT_EQ(0, CountCopyAndMove::TotalMoves());
+ EXPECT_EQ(1, CountCopyAndMove::ValueConstructions);
+
+ CountCopyAndMove::ResetCounts();
+ auto Try1 = Map.emplace_or_assign(3, 4);
+ EXPECT_FALSE(Try1.second);
+ EXPECT_EQ(0, CountCopyAndMove::TotalCopies());
+ EXPECT_EQ(1, CountCopyAndMove::ValueConstructions);
+ EXPECT_EQ(0, CountCopyAndMove::MoveConstructions);
+ EXPECT_EQ(1, CountCopyAndMove::MoveAssignments);
+
+ int Key = 5;
+ CountCopyAndMove::ResetCounts();
+ auto Try2 = Map.emplace_or_assign(Key, 3);
+ EXPECT_TRUE(Try2.second);
+ EXPECT_EQ(0, CountCopyAndMove::TotalCopies());
+ EXPECT_EQ(0, CountCopyAndMove::TotalMoves());
+ EXPECT_EQ(1, CountCopyAndMove::ValueConstructions);
+
+ CountCopyAndMove::ResetCounts();
+ auto Try3 = Map.emplace_or_assign(Key, 4);
+ EXPECT_FALSE(Try3.second);
+ EXPECT_EQ(0, CountCopyAndMove::TotalCopies());
+ EXPECT_EQ(1, CountCopyAndMove::ValueConstructions);
+ EXPECT_EQ(0, CountCopyAndMove::MoveConstructions);
+ EXPECT_EQ(1, CountCopyAndMove::MoveAssignments);
+}
+
// Make sure DenseMap works with StringRef keys.
TEST(DenseMapCustomTest, StringRefTest) {
DenseMap<StringRef, int> M;
``````````
</details>
https://github.com/llvm/llvm-project/pull/138886
More information about the llvm-commits
mailing list