|
10 | 10 |
|
11 | 11 | #include <cereal/cereal.hpp>
|
12 | 12 |
|
| 13 | +#include <boost/hana/functional/id.hpp> |
| 14 | + |
13 | 15 | namespace immer::archive::box {
|
14 | 16 |
|
15 | 17 | template <typename T, typename MemoryPolicy>
|
@@ -115,25 +117,48 @@ save_to_archive(immer::box<T, MemoryPolicy> box,
|
115 | 117 | return {std::move(archive), id};
|
116 | 118 | }
|
117 | 119 |
|
118 |
| -template <typename T, typename MemoryPolicy> |
| 120 | +template <typename T, |
| 121 | + typename MemoryPolicy, |
| 122 | + typename Archive = archive_load<T, MemoryPolicy>, |
| 123 | + typename TransformF = boost::hana::id_t> |
119 | 124 | class loader
|
120 | 125 | {
|
121 | 126 | public:
|
122 |
| - explicit loader(archive_load<T, MemoryPolicy> ar) |
| 127 | + explicit loader(Archive ar) |
| 128 | + requires std::is_same_v<TransformF, boost::hana::id_t> |
| 129 | + : ar_{std::move(ar)} |
| 130 | + { |
| 131 | + } |
| 132 | + |
| 133 | + explicit loader(Archive ar, TransformF transform) |
123 | 134 | : ar_{std::move(ar)}
|
| 135 | + , transform_{std::move(transform)} |
124 | 136 | {
|
125 | 137 | }
|
126 | 138 |
|
127 |
| - immer::box<T, MemoryPolicy> load(container_id id) const |
| 139 | + immer::box<T, MemoryPolicy> load(container_id id) |
128 | 140 | {
|
129 | 141 | if (id.value >= ar_.boxes.size()) {
|
130 | 142 | throw invalid_container_id{id};
|
131 | 143 | }
|
132 |
| - return ar_.boxes[id.value]; |
| 144 | + if constexpr (std::is_same_v<TransformF, boost::hana::id_t>) { |
| 145 | + return ar_.boxes[id.value]; |
| 146 | + } else { |
| 147 | + if (auto* b = boxes.find(id)) { |
| 148 | + return *b; |
| 149 | + } |
| 150 | + const auto& old_box = ar_.boxes[id.value]; |
| 151 | + auto new_box = |
| 152 | + immer::box<T, MemoryPolicy>{transform_(old_box.get())}; |
| 153 | + boxes = std::move(boxes).set(id, new_box); |
| 154 | + return new_box; |
| 155 | + } |
133 | 156 | }
|
134 | 157 |
|
135 | 158 | private:
|
136 |
| - const archive_load<T, MemoryPolicy> ar_; |
| 159 | + const Archive ar_; |
| 160 | + const TransformF transform_; |
| 161 | + immer::map<container_id, immer::box<T, MemoryPolicy>> boxes; |
137 | 162 | };
|
138 | 163 |
|
139 | 164 | template <typename T, typename MemoryPolicy>
|
@@ -166,8 +191,12 @@ struct container_traits<immer::box<T, MemoryPolicy>>
|
166 | 191 | {
|
167 | 192 | using save_archive_t = box::archive_save<T, MemoryPolicy>;
|
168 | 193 | using load_archive_t = box::archive_load<T, MemoryPolicy>;
|
169 |
| - using loader_t = box::loader<T, MemoryPolicy>; |
170 |
| - using container_id = immer::archive::container_id; |
| 194 | + |
| 195 | + template <typename Archive = load_archive_t, |
| 196 | + typename TransformF = boost::hana::id_t> |
| 197 | + using loader_t = box::loader<T, MemoryPolicy, Archive, TransformF>; |
| 198 | + |
| 199 | + using container_id = immer::archive::container_id; |
171 | 200 |
|
172 | 201 | template <class F>
|
173 | 202 | static auto transform(F&& func)
|
|
0 commit comments