Skip to content

Commit 20169cb

Browse files
authored
[DenseMap] Introduce emplace_or_assign (#138886)
Introduce emplace_or_assign, a variant of insert_or_assign that has slightly better characteristics.
1 parent 4eebc8d commit 20169cb

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

llvm/include/llvm/ADT/DenseMap.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,22 @@ class DenseMapBase : public DebugEpochBase {
353353
return Ret;
354354
}
355355

356+
template <typename... Ts>
357+
std::pair<iterator, bool> emplace_or_assign(const KeyT &Key, Ts &&...Args) {
358+
auto Ret = try_emplace(Key, std::forward<Ts>(Args)...);
359+
if (!Ret.second)
360+
Ret.first->second = ValueT(std::forward<Ts>(Args)...);
361+
return Ret;
362+
}
363+
364+
template <typename... Ts>
365+
std::pair<iterator, bool> emplace_or_assign(KeyT &&Key, Ts &&...Args) {
366+
auto Ret = try_emplace(std::move(Key), std::forward<Ts>(Args)...);
367+
if (!Ret.second)
368+
Ret.first->second = ValueT(std::forward<Ts>(Args)...);
369+
return Ret;
370+
}
371+
356372
bool erase(const KeyT &Val) {
357373
BucketT *TheBucket = doFind(Val);
358374
if (!TheBucket)

llvm/unittests/ADT/DenseMapTest.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,41 @@ TEST(DenseMapCustomTest, InsertOrAssignTest) {
591591
EXPECT_EQ(1, CountCopyAndMove::MoveAssignments);
592592
}
593593

594+
TEST(DenseMapCustomTest, EmplaceOrAssign) {
595+
DenseMap<int, CountCopyAndMove> Map;
596+
597+
CountCopyAndMove::ResetCounts();
598+
auto Try0 = Map.emplace_or_assign(3, 3);
599+
EXPECT_TRUE(Try0.second);
600+
EXPECT_EQ(0, CountCopyAndMove::TotalCopies());
601+
EXPECT_EQ(0, CountCopyAndMove::TotalMoves());
602+
EXPECT_EQ(1, CountCopyAndMove::ValueConstructions);
603+
604+
CountCopyAndMove::ResetCounts();
605+
auto Try1 = Map.emplace_or_assign(3, 4);
606+
EXPECT_FALSE(Try1.second);
607+
EXPECT_EQ(0, CountCopyAndMove::TotalCopies());
608+
EXPECT_EQ(1, CountCopyAndMove::ValueConstructions);
609+
EXPECT_EQ(0, CountCopyAndMove::MoveConstructions);
610+
EXPECT_EQ(1, CountCopyAndMove::MoveAssignments);
611+
612+
int Key = 5;
613+
CountCopyAndMove::ResetCounts();
614+
auto Try2 = Map.emplace_or_assign(Key, 3);
615+
EXPECT_TRUE(Try2.second);
616+
EXPECT_EQ(0, CountCopyAndMove::TotalCopies());
617+
EXPECT_EQ(0, CountCopyAndMove::TotalMoves());
618+
EXPECT_EQ(1, CountCopyAndMove::ValueConstructions);
619+
620+
CountCopyAndMove::ResetCounts();
621+
auto Try3 = Map.emplace_or_assign(Key, 4);
622+
EXPECT_FALSE(Try3.second);
623+
EXPECT_EQ(0, CountCopyAndMove::TotalCopies());
624+
EXPECT_EQ(1, CountCopyAndMove::ValueConstructions);
625+
EXPECT_EQ(0, CountCopyAndMove::MoveConstructions);
626+
EXPECT_EQ(1, CountCopyAndMove::MoveAssignments);
627+
}
628+
594629
// Make sure DenseMap works with StringRef keys.
595630
TEST(DenseMapCustomTest, StringRefTest) {
596631
DenseMap<StringRef, int> M;

0 commit comments

Comments
 (0)