0.6.0
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
memoized.h
Go to the documentation of this file.
1/**
2 * src/util/memoized.h
3 *
4 * Copyright (c) 2021-2025 Bartek Kryza <bkryza@gmail.com>
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18#pragma once
19
20#include <map>
21#include <optional>
22#include <tuple>
23
24namespace clanguml::util {
25/**
26 * @brief Simple memoization implementation for expensive methods.
27 *
28 * @tparam T Tag type to allow multiple memoizations per class
29 * @tparam Ret Return type of the memoized method F
30 * @tparam Args Arguments the memoized method F
31 */
32template <typename T, typename Ret, typename... Args> class memoized {
33public:
34 using key_t = std::tuple<Args...>;
35 using value_t = Ret;
36
37 template <typename F>
38 auto memoize(bool is_complete, F &&f, Args... args) const
39 {
40 if (!is_complete)
41 return f(std::forward<Args>(args)...);
42
43 const auto key = key_t{std::forward<Args>(args)...};
44 if (cache_.find(key) == cache_.end())
45 cache_[key] = std::apply(f, key);
46
47 return cache_.at(key);
48 }
49
50 void invalidate(Args... args) const { cache_.erase(args...); }
51
52private:
53 mutable std::map<key_t, value_t> cache_;
54};
55
56template <typename T, typename Ret> class memoized<T, Ret> {
57public:
58 using key_t = bool;
59 using value_t = Ret;
60
61 template <typename F> auto memoize(bool is_complete, F f) const
62 {
63 if (!is_complete)
64 return f();
65
66 if (!value_) {
67 value_ = f();
68 }
69
70 return *value_; // NOLINT
71 }
72
73 void invalidate() const { value_.reset(); }
74
75private:
76 mutable std::optional<Ret> value_;
77};
78
79template <typename T, typename Ret> class memoized<T, Ret, bool> {
80public:
81 using key_t = bool;
82 using value_t = Ret;
83
84 template <typename F> auto memoize(bool is_complete, F f, bool arg) const
85 {
86 if (!is_complete)
87 return f(arg);
88
89 const auto key = arg;
90 if (key && !true_value_) {
91 true_value_ = f(arg);
92 }
93
94 if (!key && !false_value_) {
95 false_value_ = f(arg);
96 }
97
98 return key ? *true_value_ : *false_value_; // NOLINT
99 }
100
101 void invalidate(bool key) const
102 {
103 if (key)
104 true_value_.reset();
105 else
106 false_value_.reset();
107 }
108
109private:
110 mutable std::optional<Ret> true_value_;
111 mutable std::optional<Ret> false_value_;
112};
113} // namespace clanguml::util