Zen C++ Libraries
Zero-dependency re-usable components for C++
Loading...
Searching...
No Matches
clone_ptr.hpp
1#ifndef ZEN_CLONE_PTR_HPP
2#define ZEN_CLONE_PTR_HPP
3
4#include <utility>
5
6#include "zen/config.hpp"
7
8ZEN_NAMESPACE_START
9
10template<typename T, typename Enabler = void>
12
13template<typename T>
14struct default_cloner<T, std::enable_if_t<std::is_fundamental_v<T>>> {
15
16 default_cloner();
17
18 template<typename T2>
19 default_cloner(default_cloner<T2>&& other) {}
20
21 template<typename T2>
22 default_cloner(const default_cloner<T2>& other) {}
23
24 T operator()(const T& value) {
25 return value;
26 }
27};
28
29template<typename T>
30struct default_cloner<T*> {
31
32 default_cloner() {}
33
34 template<typename T2>
35 default_cloner(default_cloner<T2>&& other) {}
36
37 template<typename T2>
38 default_cloner(const default_cloner<T2>& other) {}
39
40 T* operator()(const T* value) {
41 return value->clone();
42 }
43};
44
45template<typename T, typename ClonerT = default_cloner<T*>>
46class clone_ptr {
47
48 template<typename T2, typename ClonerT2>
49 friend class clone_ptr;
50
51 ClonerT cloner;
52 T* ptr;
53
54public:
55
56 clone_ptr(T* ptr, ClonerT cloner = default_cloner<T*> {}):
57 cloner(cloner), ptr(ptr) {}
58
59 clone_ptr(const clone_ptr& other):
60 cloner(other.cloner), ptr(cloner(other.ptr)) {}
61
62 clone_ptr(clone_ptr&& other):
63 cloner(std::move(other.cloner)), ptr(std::move(other.ptr)) {
64 other.ptr = nullptr;
65 };
66
67 clone_ptr& operator=(const clone_ptr& other) {
68 cloner = other.cloner;
69 ptr = cloner(other.ptr);
70 return *this;
71 }
72
73 clone_ptr& operator=(clone_ptr&& other) {
74 cloner = std::move(other.cloner);
75 ptr = std::move(other.ptr);
76 other.ptr = nullptr;
77 return *this;
78 }
79
80 template<typename T2, typename ClonerT2>
81 clone_ptr(const clone_ptr<T2, ClonerT2>& other):
82 cloner(other.cloner), ptr(cloner(other.ptr)) {}
83
84 template<typename T2, typename ClonerT2>
85 clone_ptr(clone_ptr<T2, ClonerT2>&& other):
86 cloner(std::move(other.cloner)), ptr(std::move(other.ptr)) {
87 other.ptr = nullptr;
88 };
89
90 template<typename T2, typename ClonerT2>
91 clone_ptr& operator=(const clone_ptr<T2, ClonerT2>& other) {
92 cloner = other.cloner;
93 ptr = cloner(other.ptr);
94 return *this;
95 }
96
97 template<typename T2, typename ClonerT2>
98 clone_ptr& operator=(clone_ptr<T2, ClonerT2>&& other) {
99 cloner = std::move(other.cloner);
100 ptr = std::move(other.ptr);
101 other.ptr = nullptr;
102 return *this;
103 }
104
105 T* get() {
106 return ptr;
107 }
108
109 const T* get() const {
110 return ptr;
111 }
112
113 T* release() {
114 auto keep = ptr;
115 ptr = nullptr;
116 return keep;
117 }
118
119 T& operator*() {
120 return *ptr;
121 }
122
123 const T& operator*() const {
124 return *ptr;
125 }
126
127 T* operator->() {
128 return ptr;
129 }
130
131 const T* operator->() const {
132 return ptr;
133 }
134
135 ~clone_ptr() {
136 if (ptr != nullptr) {
137 delete ptr;
138 }
139 }
140
141};
142
143template<typename T, typename ...ForwardArgs>
144clone_ptr<T> make_cloned(ForwardArgs&& ...args) {
145 return clone_ptr<T>(new T(std::forward<ForwardArgs>(args)...));
146}
147
148ZEN_NAMESPACE_END
149
150#endif // of #ifndef ZEN_CLONE_PTR_HPP
Definition clone_ptr.hpp:46
Definition value.hpp:34
Definition clone_ptr.hpp:11