[llvm] [LLVM] Add helper class for working with caches (PR #171008)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Dec 6 19:57:03 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-adt
Author: Victor Chernyakin (localspook)
<details>
<summary>Changes</summary>
See the doc comment for what it does.
I'm planning to use this in an upcoming refactor of [this function](https://github.com/llvm/llvm-project/blob/315c904e3e1c00ea1ec7f0757e4c538ec2513624/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp#L65). Here's [another, completely unrelated function](https://github.com/llvm/llvm-project/blob/315c904e3e1c00ea1ec7f0757e4c538ec2513624/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp#L253) it could simplify; this seems like a generally useful feature.
---
Full diff: https://github.com/llvm/llvm-project/pull/171008.diff
2 Files Affected:
- (modified) llvm/include/llvm/ADT/STLExtras.h (+24)
- (modified) llvm/unittests/ADT/STLExtrasTest.cpp (+9)
``````````diff
diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h
index af0e4a36be1b1..4645b35b234fb 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 &&Fn LLVM_LIFETIME_BOUND) : Fn(Fn) {}
+
+ template <typename U> constexpr operator U() {
+ return std::forward<FnT>(Fn)();
+ }
+
+private:
+ FnT &Fn;
+};
+
+// Silence -Wctad-maybe-unsupported.
+template <typename FnT> defer(FnT &&Fn LLVM_LIFETIME_BOUND) -> 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
``````````
</details>
https://github.com/llvm/llvm-project/pull/171008
More information about the llvm-commits
mailing list