[llvm] [LLVM][ADT] Add helper class for working with caches (PR #171008)
Victor Chernyakin via llvm-commits
llvm-commits at lists.llvm.org
Sat Dec 6 20:00:14 PST 2025
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/171008
>From d48726524e0d6a36bfa1cfc4a4669dcaeb8d0f6c Mon Sep 17 00:00:00 2001
From: Victor Chernyakin <chernyakin.victor.j at outlook.com>
Date: Sat, 6 Dec 2025 19:43:31 -0800
Subject: [PATCH] [LLVM] Add helper class for working with caches
---
llvm/include/llvm/ADT/STLExtras.h | 24 ++++++++++++++++++++++++
llvm/unittests/ADT/STLExtrasTest.cpp | 9 +++++++++
2 files changed, 33 insertions(+)
diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h
index af0e4a36be1b1..96b0967317547 100644
--- a/llvm/include/llvm/ADT/STLExtras.h
+++ b/llvm/include/llvm/ADT/STLExtras.h
@@ -2610,6 +2610,30 @@ template <typename T> using has_sizeof = decltype(sizeof(T));
template <typename T>
constexpr bool is_incomplete_v = !is_detected<detail::has_sizeof, T>::value;
+/// A utility for working with maps that allows concisely expressing "perform
+/// and cache this expensive computation only if it isn't already cached".
+/// Use it like so:
+///
+/// ```cpp
+/// std::unordered_map<K, V> Cache;
+/// auto& Value = Cache.try_emplace(
+/// Key, llvm::defer {[] { /* heavy work */ }}).first->second;
+/// ```
+template <typename FnT> class defer {
+public:
+ constexpr defer(FnT &&F LLVM_LIFETIME_BOUND) : Fn(std::forward<FnT>(F)) {}
+
+ template <typename T> constexpr operator T() {
+ return std::forward<FnT>(Fn)();
+ }
+
+private:
+ FnT &&Fn;
+};
+
+// Silence -Wctad-maybe-unsupported.
+template <typename FnT> defer(FnT &&) -> defer<FnT>;
+
} // end namespace llvm
namespace std {
diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp
index 85567775e4ebd..18a78e625022c 100644
--- a/llvm/unittests/ADT/STLExtrasTest.cpp
+++ b/llvm/unittests/ADT/STLExtrasTest.cpp
@@ -1699,4 +1699,13 @@ struct Bar {};
static_assert(is_incomplete_v<Foo>, "Foo is incomplete");
static_assert(!is_incomplete_v<Bar>, "Bar is defined");
+TEST(STLExtrasTest, Defer) {
+ std::unordered_map<int, int> Cache;
+ const auto [It, Inserted]{Cache.try_emplace(1, defer{[] { return 10; }})};
+ ASSERT_TRUE(Inserted);
+ ASSERT_EQ(It->second, 10);
+ Cache.try_emplace(
+ 1, defer{[] { ASSERT_TRUE(false && "this should never be executed"); }});
+}
+
} // namespace
More information about the llvm-commits
mailing list