[llvm] [ADT] Add C++17-style insert_or_assign for DenseMap (PR #94151)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 3 01:08:34 PDT 2024
https://github.com/c8ef updated https://github.com/llvm/llvm-project/pull/94151
>From 1724a23fbf4bc4caa526d6b323abbe5c7607c19c Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Sun, 2 Jun 2024 08:11:27 +0000
Subject: [PATCH 1/3] implement insert_or_assign
---
llvm/include/llvm/ADT/DenseMap.h | 16 ++++++++++++++++
llvm/unittests/ADT/DenseMapTest.cpp | 28 ++++++++++++++++++++++++++++
2 files changed, 44 insertions(+)
diff --git a/llvm/include/llvm/ADT/DenseMap.h b/llvm/include/llvm/ADT/DenseMap.h
index 3ef6a7cd1b4b5..7ccc9445c0a7b 100644
--- a/llvm/include/llvm/ADT/DenseMap.h
+++ b/llvm/include/llvm/ADT/DenseMap.h
@@ -312,6 +312,22 @@ class DenseMapBase : public DebugEpochBase {
insert(*I);
}
+ template <typename V>
+ std::pair<iterator, bool> insert_or_assign(const KeyT &Key, V &&Val) {
+ auto Ret = try_emplace(Key, std::forward<V>(Val));
+ if (!Ret.second)
+ Ret.first->second = std::forward<V>(Val);
+ return Ret;
+ }
+
+ template <typename V>
+ std::pair<iterator, bool> insert_or_assign(KeyT &&Key, V &&Val) {
+ auto Ret = try_emplace(std::move(Key), std::forward<V>(Val));
+ if (!Ret.second)
+ Ret.first->second = std::forward<V>(Val);
+ return Ret;
+ }
+
/// Returns the value associated to the key in the map if it exists. If it
/// does not exist, emplace a default value for the key and returns a
/// reference to the newly created value.
diff --git a/llvm/unittests/ADT/DenseMapTest.cpp b/llvm/unittests/ADT/DenseMapTest.cpp
index cc3244528f27e..3fa20ef62ccea 100644
--- a/llvm/unittests/ADT/DenseMapTest.cpp
+++ b/llvm/unittests/ADT/DenseMapTest.cpp
@@ -499,6 +499,34 @@ TEST(DenseMapCustomTest, ReserveTest) {
}
}
+TEST(DenseMapCustomTest, InsertOrAssignTest) {
+ DenseMap<int, CountCopyAndMove> Map;
+ CountCopyAndMove::Copy = 0;
+ CountCopyAndMove::Move = 0;
+
+ CountCopyAndMove val1;
+ auto try0 = Map.insert_or_assign(0, val1);
+ EXPECT_TRUE(try0.second);
+ EXPECT_EQ(0, CountCopyAndMove::Move);
+ EXPECT_EQ(1, CountCopyAndMove::Copy);
+
+ auto try1 = Map.insert_or_assign(0, val1);
+ EXPECT_FALSE(try1.second);
+ EXPECT_EQ(0, CountCopyAndMove::Move);
+ EXPECT_EQ(2, CountCopyAndMove::Copy);
+
+ CountCopyAndMove val2;
+ auto try2 = Map.insert_or_assign(2, val2);
+ EXPECT_TRUE(try2.second);
+ EXPECT_EQ(0, CountCopyAndMove::Move);
+ EXPECT_EQ(3, CountCopyAndMove::Copy);
+
+ auto try3 = Map.insert_or_assign(2, std::move(val2));
+ EXPECT_FALSE(try3.second);
+ EXPECT_EQ(1, CountCopyAndMove::Move);
+ EXPECT_EQ(3, CountCopyAndMove::Copy);
+}
+
// Make sure DenseMap works with StringRef keys.
TEST(DenseMapCustomTest, StringRefTest) {
DenseMap<StringRef, int> M;
>From a13126c56a4323fa61b7bc6ed4df9af56dac90a0 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Mon, 3 Jun 2024 00:42:50 +0000
Subject: [PATCH 2/3] test the const ref api
---
llvm/unittests/ADT/DenseMapTest.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/llvm/unittests/ADT/DenseMapTest.cpp b/llvm/unittests/ADT/DenseMapTest.cpp
index 3fa20ef62ccea..da473280c8100 100644
--- a/llvm/unittests/ADT/DenseMapTest.cpp
+++ b/llvm/unittests/ADT/DenseMapTest.cpp
@@ -515,13 +515,14 @@ TEST(DenseMapCustomTest, InsertOrAssignTest) {
EXPECT_EQ(0, CountCopyAndMove::Move);
EXPECT_EQ(2, CountCopyAndMove::Copy);
+ int key2 = 2;
CountCopyAndMove val2;
- auto try2 = Map.insert_or_assign(2, val2);
+ auto try2 = Map.insert_or_assign(key2, val2);
EXPECT_TRUE(try2.second);
EXPECT_EQ(0, CountCopyAndMove::Move);
EXPECT_EQ(3, CountCopyAndMove::Copy);
- auto try3 = Map.insert_or_assign(2, std::move(val2));
+ auto try3 = Map.insert_or_assign(key2, std::move(val2));
EXPECT_FALSE(try3.second);
EXPECT_EQ(1, CountCopyAndMove::Move);
EXPECT_EQ(3, CountCopyAndMove::Copy);
>From 91423247140729cf3bfa38098e1b54be2f273a37 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Mon, 3 Jun 2024 08:08:22 +0000
Subject: [PATCH 3/3] add a subclass to avoid default construct
---
llvm/unittests/ADT/DenseMapTest.cpp | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/llvm/unittests/ADT/DenseMapTest.cpp b/llvm/unittests/ADT/DenseMapTest.cpp
index da473280c8100..4c8773df55217 100644
--- a/llvm/unittests/ADT/DenseMapTest.cpp
+++ b/llvm/unittests/ADT/DenseMapTest.cpp
@@ -359,15 +359,15 @@ struct CountCopyAndMove {
return *this;
}
CountCopyAndMove(CountCopyAndMove &&) { Move++; }
- CountCopyAndMove &operator=(const CountCopyAndMove &&) {
+ CountCopyAndMove &operator=(CountCopyAndMove &&) {
Move++;
return *this;
}
};
+
int CountCopyAndMove::Copy = 0;
int CountCopyAndMove::Move = 0;
-
-} // anonymous namespace
+} // namespace
// Test initializer list construction.
TEST(DenseMapCustomTest, InitializerList) {
@@ -500,11 +500,16 @@ TEST(DenseMapCustomTest, ReserveTest) {
}
TEST(DenseMapCustomTest, InsertOrAssignTest) {
- DenseMap<int, CountCopyAndMove> Map;
+ struct C : CountCopyAndMove {
+ C(int v) : v(v) {}
+ int v;
+ };
+
+ DenseMap<int, C> Map;
CountCopyAndMove::Copy = 0;
CountCopyAndMove::Move = 0;
- CountCopyAndMove val1;
+ C val1(1);
auto try0 = Map.insert_or_assign(0, val1);
EXPECT_TRUE(try0.second);
EXPECT_EQ(0, CountCopyAndMove::Move);
@@ -516,7 +521,7 @@ TEST(DenseMapCustomTest, InsertOrAssignTest) {
EXPECT_EQ(2, CountCopyAndMove::Copy);
int key2 = 2;
- CountCopyAndMove val2;
+ C val2(2);
auto try2 = Map.insert_or_assign(key2, val2);
EXPECT_TRUE(try2.second);
EXPECT_EQ(0, CountCopyAndMove::Move);
More information about the llvm-commits
mailing list