[llvm] [ADT] add C++17-style try_emplace and insert_or_assign for DenseMap (PR #94151)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 2 01:14:24 PDT 2024


https://github.com/c8ef created https://github.com/llvm/llvm-project/pull/94151

add C++17-style try_emplace and insert_or_assign for DenseMap

close: #94115 

>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] 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;



More information about the llvm-commits mailing list