Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
icloneable.h
1// SPDX-FileCopyrightText: © 2024-2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include <memory>
7#include <type_traits>
8#include <variant>
9#include <vector>
10
11#include "utils/qt.h"
12#include "utils/traits.h"
13#include "utils/variant_helpers.h"
14
15namespace zrythm::utils
16{
17
32
37template <typename T>
39 requires (T &obj, const T &other, ObjectCloneType clone_type) {
40 { init_from (obj, other, clone_type) } -> std::same_as<void>;
41 };
42
43template <CloneableObject Derived, typename... Args>
44std::unique_ptr<Derived>
45clone_unique (
46 const Derived &obj,
48 Args &&... args)
49{
50 std::unique_ptr<Derived> cloned;
51 cloned = std::make_unique<Derived> (std::forward<Args> (args)...);
52 init_from (*cloned, obj, clone_type);
53 return cloned;
54}
55
56template <CloneableObject Derived, typename... Args>
57std::shared_ptr<Derived>
58clone_shared (
59 const Derived &obj,
61 Args &&... args)
62{
63 std::shared_ptr<Derived> cloned;
64 cloned = std::make_shared<Derived> (std::forward<Args> (args)...);
65 init_from (*cloned, obj, clone_type);
66 return cloned;
67}
68
69template <CloneableObject Derived, typename... Args>
70Derived *
71clone_raw_ptr (
72 const Derived &obj,
74 Args &&... args)
75{
76 auto unique_ptr = clone_unique (obj, clone_type, std::forward<Args> (args)...);
77 return unique_ptr.release ();
78}
79
80template <CloneableObject Derived, typename... Args>
81Derived *
82clone_qobject (
83 const Derived &obj,
84 QObject * parent,
86 Args &&... args)
87 requires utils::QObjectDerived<Derived>
88{
89 auto * cloned = clone_raw_ptr (obj, clone_type, std::forward<Args> (args)...);
90 if (cloned)
91 {
92 cloned->setParent (parent);
93 }
94 return cloned;
95}
96
97template <CloneableObject Derived, typename... Args>
98utils::QObjectUniquePtr<Derived>
99clone_unique_qobject (
100 const Derived &obj,
101 QObject * parent,
103 Args &&... args)
104 requires utils::QObjectDerived<Derived>
105{
106 return utils::QObjectUniquePtr<Derived> (
107 clone_qobject (obj, parent, clone_type, std::forward<Args> (args)...));
108}
109
114template <typename T>
116 CloneableObject<T> && std::default_initializable<T>;
117
119template <typename T, typename Base>
120concept InheritsFromBase = std::is_base_of_v<Base, std::remove_pointer_t<T>>;
121
123template <typename Variant, typename Base>
124concept AllInheritFromBase = requires {
125 []<typename... Ts> (std::variant<Ts...> *) {
126 static_assert (
128 "All types in Variant must inherit from Base");
129 }(static_cast<Variant *> (nullptr));
130};
131
140template <typename T, std::size_t N>
141void
143 std::array<std::unique_ptr<T>, N> &dest,
144 const std::array<std::unique_ptr<T>, N> &src,
146{
147 for (size_t i = 0; i < N; ++i)
148 {
149 if (src[i])
150 {
152 {
153 dest[i] =
154 clone_unique (*src[i], clone_type = ObjectCloneType::Snapshot);
155 }
156 else
157 {
158 dest[i] = std::make_unique<T> (*src[i]);
159 }
160 }
161 else
162 {
163 dest[i] = nullptr;
164 }
165 }
166}
167
176template <typename T, template <typename...> class Ptr>
177void
179 std::vector<Ptr<T>> &dest,
180 const std::vector<Ptr<T>> &src,
182{
183 dest.clear ();
184 dest.reserve (src.size ());
185
186 for (const auto &ptr : src)
187 {
188 if (ptr)
189 {
191 {
192 if constexpr (std::is_same_v<Ptr<T>, std::unique_ptr<T>>)
193 {
194 dest.push_back (clone_unique (
195 *ptr, clone_type = ObjectCloneType::Snapshot));
196 }
197 else if constexpr (std::is_same_v<Ptr<T>, std::shared_ptr<T>>)
198 {
199 dest.push_back (clone_shared (
200 *ptr, clone_type = ObjectCloneType::Snapshot));
201 }
202 }
203 else
204 {
205 if constexpr (std::is_same_v<Ptr<T>, std::unique_ptr<T>>)
206 {
207 dest.push_back (std::make_unique<T> (*ptr));
208 }
209 else if constexpr (std::is_same_v<Ptr<T>, std::shared_ptr<T>>)
210 {
211 dest.push_back (std::make_shared<T> (*ptr));
212 }
213 }
214 }
215 else
216 {
217 dest.push_back (nullptr);
218 }
219 }
220}
221
229template <typename Container>
230void
232 Container &dest,
233 const Container &src,
235{
236 if constexpr (StdArray<Container>)
237 {
238 clone_unique_ptr_array (dest, src, clone_type = ObjectCloneType::Snapshot);
239 }
240 else
241 {
242 clone_ptr_vector (dest, src, clone_type = ObjectCloneType::Snapshot);
243 }
244}
245
246template <typename Container, typename Variant, typename Base>
247 requires AllInheritFromBase<Variant, Base>
248void
249clone_variant_container (
250 Container &dest,
251 const Container &src,
253{
254 if constexpr (StdArray<Container>)
255 {
256 for (size_t i = 0; i < src.size (); ++i)
257 {
258 if (src[i])
259 {
260 dest[i] = clone_unique_with_variant<Variant, Base> (
261 src[i].get (), clone_type = ObjectCloneType::Snapshot);
262 }
263 else
264 {
265 dest[i] = nullptr;
266 }
267 }
268 }
269 else
270 {
271 dest.clear ();
272 dest.reserve (src.size ());
273
274 for (const auto &ptr : src)
275 {
276 if (ptr)
277 {
278 dest.push_back (
279 clone_unique_with_variant<Variant, Base> (
280 ptr.get (), clone_type = ObjectCloneType::Snapshot));
281 }
282 else
283 {
284 dest.push_back (nullptr);
285 }
286 }
287 }
288}
289
295template <typename Variant, typename Container>
297void
298clone_variant_container (
299 Container &dest,
300 const Container &src,
302{
303 using Base = typename Container::value_type::element_type;
304
305 if constexpr (StdArray<Container>)
306 {
307 // Handle std::array
308 for (size_t i = 0; i < src.size (); ++i)
309 {
310 if (src[i])
311 {
312 dest[i] = clone_unique_with_variant<Variant, Base> (
313 src[i].get (), clone_type = ObjectCloneType::Snapshot);
314 }
315 else
316 {
317 dest[i] = nullptr;
318 }
319 }
320 }
321 else
322 {
323 // Handle std::vector or similar containers
324 dest.clear ();
325 dest.reserve (src.size ());
326
327 for (const auto &ptr : src)
328 {
329 if (ptr)
330 {
331 dest.push_back (
332 clone_unique_with_variant<Variant, Base> (
333 ptr.get (), clone_type = ObjectCloneType::Snapshot));
334 }
335 else
336 {
337 dest.push_back (nullptr);
338 }
339 }
340 }
341}
342
343} // namespace zrythm::utils
Concept to ensure all types in a variant inherit from a base class.
Definition icloneable.h:124
Concept that checks if a type is cloneable.
Definition icloneable.h:115
Concept that checks if a type is cloneable.
Definition icloneable.h:38
Concept to check if a type inherits from a base class.
Definition icloneable.h:120
String utilities.
Definition algorithms.h:12
void clone_unique_ptr_container(Container &dest, const Container &src, ObjectCloneType clone_type=ObjectCloneType::Snapshot)
Clones the elements of a container of std::unique_ptr into the destination container.
Definition icloneable.h:231
void clone_unique_ptr_array(std::array< std::unique_ptr< T >, N > &dest, const std::array< std::unique_ptr< T >, N > &src, ObjectCloneType clone_type=ObjectCloneType::Snapshot)
Clones the elements of a std::array of std::unique_ptr into the destination array.
Definition icloneable.h:142
@ NewIdentity
Creates a separately identified object.
Definition icloneable.h:30
@ Snapshot
Creates a snapshot of the object with the same identity.
Definition icloneable.h:23
void clone_ptr_vector(std::vector< Ptr< T > > &dest, const std::vector< Ptr< T > > &src, ObjectCloneType clone_type=ObjectCloneType::Snapshot)
Clones the elements of a std::vector of std::unique_ptr or std::shared_ptr into the destination vecto...
Definition icloneable.h:178