Skip to content

Commit 7368846

Browse files
committed
[DenseMap] Introduce emplace_or_assign
Introduce emplace_or_assign, a variant of insert_or_assign that has slightly better characteristics.
1 parent aec3929 commit 7368846

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
@@ -324,6 +324,22 @@ class DenseMapBase : public DebugEpochBase {
324324
return Ret;
325325
}
326326

327+
template <typename... Ts>
328+
std::pair<iterator, bool> emplace_or_assign(const KeyT &Key, Ts &&...Args) {
329+
auto Ret = try_emplace(Key, std::forward<Ts>(Args)...);
330+
if (!Ret.second)
331+
Ret.first->second = ValueT(std::forward<Ts>(Args)...);
332+
return Ret;
333+
}
334+
335+
template <typename... Ts>
336+
std::pair<iterator, bool> emplace_or_assign(KeyT &&Key, Ts &&...Args) {
337+
auto Ret = try_emplace(std::move(Key), std::forward<Ts>(Args)...);
338+
if (!Ret.second)
339+
Ret.first->second = ValueT(std::forward<Ts>(Args)...);
340+
return Ret;
341+
}
342+
327343
bool erase(const KeyT &Val) {
328344
BucketT *TheBucket = doFind(Val);
329345
if (!TheBucket)

llvm/unittests/ADT/DenseMapTest.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,41 @@ TEST(DenseMapCustomTest, InsertOrAssignTest) {
545545
EXPECT_EQ(1, CountCopyAndMove::MoveAssignments);
546546
}
547547

548+
TEST(DenseMapCustomTest, EmplaceOrAssign) {
549+
DenseMap<int, CountCopyAndMove> Map;
550+
551+
CountCopyAndMove::ResetCounts();
552+
auto Try0 = Map.emplace_or_assign(3, 3);
553+
EXPECT_TRUE(Try0.second);
554+
EXPECT_EQ(0, CountCopyAndMove::TotalCopies());
555+
EXPECT_EQ(0, CountCopyAndMove::TotalMoves());
556+
EXPECT_EQ(1, CountCopyAndMove::ValueConstructions);
557+
558+
CountCopyAndMove::ResetCounts();
559+
auto Try1 = Map.emplace_or_assign(3, 4);
560+
EXPECT_FALSE(Try1.second);
561+
EXPECT_EQ(0, CountCopyAndMove::TotalCopies());
562+
EXPECT_EQ(1, CountCopyAndMove::ValueConstructions);
563+
EXPECT_EQ(0, CountCopyAndMove::MoveConstructions);
564+
EXPECT_EQ(1, CountCopyAndMove::MoveAssignments);
565+
566+
int Key = 5;
567+
CountCopyAndMove::ResetCounts();
568+
auto Try2 = Map.emplace_or_assign(Key, 3);
569+
EXPECT_TRUE(Try2.second);
570+
EXPECT_EQ(0, CountCopyAndMove::TotalCopies());
571+
EXPECT_EQ(0, CountCopyAndMove::TotalMoves());
572+
EXPECT_EQ(1, CountCopyAndMove::ValueConstructions);
573+
574+
CountCopyAndMove::ResetCounts();
575+
auto Try3 = Map.emplace_or_assign(Key, 4);
576+
EXPECT_FALSE(Try3.second);
577+
EXPECT_EQ(0, CountCopyAndMove::TotalCopies());
578+
EXPECT_EQ(1, CountCopyAndMove::ValueConstructions);
579+
EXPECT_EQ(0, CountCopyAndMove::MoveConstructions);
580+
EXPECT_EQ(1, CountCopyAndMove::MoveAssignments);
581+
}
582+
548583
// Make sure DenseMap works with StringRef keys.
549584
TEST(DenseMapCustomTest, StringRefTest) {
550585
DenseMap<StringRef, int> M;

0 commit comments

Comments
 (0)