File tree Expand file tree Collapse file tree 2 files changed +33
-0
lines changed
Expand file tree Collapse file tree 2 files changed +33
-0
lines changed Original file line number Diff line number Diff line change @@ -2610,6 +2610,30 @@ template <typename T> using has_sizeof = decltype(sizeof(T));
26102610template <typename T>
26112611constexpr bool is_incomplete_v = !is_detected<detail::has_sizeof, T>::value;
26122612
2613+ // / A utility for working with maps that allows concisely expressing "perform
2614+ // / and cache this expensive computation only if it isn't already cached".
2615+ // / Use it like so:
2616+ // /
2617+ // / ```cpp
2618+ // / std::unordered_map<K, V> Cache;
2619+ // / auto& Value = Cache.try_emplace(
2620+ // / Key, llvm::defer {[] { /* heavy work */ }}).first->second;
2621+ // / ```
2622+ template <typename FnT> class defer {
2623+ public:
2624+ constexpr defer (FnT &&F LLVM_LIFETIME_BOUND) : Fn(std::forward<FnT>(F)) {}
2625+
2626+ template <typename T> constexpr operator T () {
2627+ return std::forward<FnT>(Fn)();
2628+ }
2629+
2630+ private:
2631+ FnT &&Fn;
2632+ };
2633+
2634+ // Silence -Wctad-maybe-unsupported.
2635+ template <typename FnT> defer (FnT &&) -> defer<FnT>;
2636+
26132637} // end namespace llvm
26142638
26152639namespace std {
Original file line number Diff line number Diff line change @@ -1699,4 +1699,13 @@ struct Bar {};
16991699static_assert (is_incomplete_v<Foo>, " Foo is incomplete" );
17001700static_assert (!is_incomplete_v<Bar>, " Bar is defined" );
17011701
1702+ TEST (STLExtrasTest, Defer) {
1703+ std::unordered_map<int , int > Cache;
1704+ const auto [It, Inserted]{Cache.try_emplace (1 , defer{[] { return 10 ; }})};
1705+ ASSERT_TRUE (Inserted);
1706+ ASSERT_EQ (It->second , 10 );
1707+ Cache.try_emplace (
1708+ 1 , defer{[] { ASSERT_TRUE (false && " this should never be executed" ); }});
1709+ }
1710+
17021711} // namespace
You can’t perform that action at this time.
0 commit comments