libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
uniqueptr.h
Go to the documentation of this file.
1
9#pragma once
10
11
12#include <promeki/config.h>
13#if PROMEKI_ENABLE_CORE
14#include <cassert>
15#include <cstddef>
16#include <type_traits>
17#include <utility>
18#include <promeki/namespace.h>
19
20PROMEKI_NAMESPACE_BEGIN
21
62template <typename T> class UniquePtr {
63 public:
64 // All UniquePtr instantiations are friends of each other so the
65 // upcast/downcast helpers can reach the private _ptr across
66 // type boundaries.
67 template <typename U> friend class UniquePtr;
68
70 UniquePtr() = default;
71
73 UniquePtr(std::nullptr_t) noexcept {}
74
76 UniquePtr(const UniquePtr &) = delete;
77
79 UniquePtr &operator=(const UniquePtr &) = delete;
80
82 UniquePtr(UniquePtr &&o) noexcept : _ptr(o._ptr) { o._ptr = nullptr; }
83
92 template <typename U, typename = std::enable_if_t<std::is_base_of_v<T, U> && !std::is_same_v<T, U>>>
93 UniquePtr(UniquePtr<U> &&o) noexcept : _ptr(o._ptr) {
94 o._ptr = nullptr;
95 }
96
97 ~UniquePtr() { clear(); }
98
100 UniquePtr &operator=(UniquePtr &&o) noexcept {
101 if (&o == this) return *this;
102 clear();
103 _ptr = o._ptr;
104 o._ptr = nullptr;
105 return *this;
106 }
107
114 template <typename U, typename = std::enable_if_t<std::is_base_of_v<T, U> && !std::is_same_v<T, U>>>
115 UniquePtr &operator=(UniquePtr<U> &&o) noexcept {
116 clear();
117 _ptr = o._ptr;
118 o._ptr = nullptr;
119 return *this;
120 }
121
126 template <typename... Args> static UniquePtr create(Args &&...args) {
127 UniquePtr up;
128 up._ptr = new T(std::forward<Args>(args)...);
129 return up;
130 }
131
140 static UniquePtr takeOwnership(T *obj) {
141 UniquePtr up;
142 up._ptr = obj;
143 return up;
144 }
145
147 void clear() {
148 if (_ptr == nullptr) return;
149 delete _ptr;
150 _ptr = nullptr;
151 return;
152 }
153
162 T *release() {
163 T *p = _ptr;
164 _ptr = nullptr;
165 return p;
166 }
167
180 void reset(T *obj = nullptr) {
181 delete _ptr;
182 _ptr = obj;
183 return;
184 }
185
187 void swap(UniquePtr &other) noexcept { std::swap(_ptr, other._ptr); }
188
190 bool isNull() const { return _ptr == nullptr; }
191
193 bool isValid() const { return _ptr != nullptr; }
194
196 explicit operator bool() const { return _ptr != nullptr; }
197
198 bool operator==(const UniquePtr &other) const { return _ptr == other._ptr; }
199 bool operator!=(const UniquePtr &other) const { return _ptr != other._ptr; }
200 bool operator==(std::nullptr_t) const { return _ptr == nullptr; }
201 bool operator!=(std::nullptr_t) const { return _ptr != nullptr; }
202
210 T *ptr() const {
211 assert(_ptr != nullptr);
212 return _ptr;
213 }
214
222 T *get() const { return _ptr; }
223
224 T *operator->() const { return ptr(); }
225 T &operator*() const { return *ptr(); }
226
227 private:
228 T *_ptr = nullptr;
229};
230
232template <typename T> void swap(UniquePtr<T> &a, UniquePtr<T> &b) noexcept {
233 a.swap(b);
234}
235
265template <typename T> class UniquePtr<T[]> {
266 public:
268 UniquePtr() = default;
269
271 UniquePtr(std::nullptr_t) noexcept {}
272
274 UniquePtr(const UniquePtr &) = delete;
275
277 UniquePtr &operator=(const UniquePtr &) = delete;
278
280 UniquePtr(UniquePtr &&o) noexcept : _ptr(o._ptr) { o._ptr = nullptr; }
281
282 ~UniquePtr() { clear(); }
283
285 UniquePtr &operator=(UniquePtr &&o) noexcept {
286 if (&o == this) return *this;
287 clear();
288 _ptr = o._ptr;
289 o._ptr = nullptr;
290 return *this;
291 }
292
302 static UniquePtr createArray(size_t n) {
303 UniquePtr up;
304 up._ptr = new T[n];
305 return up;
306 }
307
321 static UniquePtr createArrayValueInit(size_t n) {
322 UniquePtr up;
323 up._ptr = new T[n]();
324 return up;
325 }
326
335 static UniquePtr takeOwnership(T *obj) {
336 UniquePtr up;
337 up._ptr = obj;
338 return up;
339 }
340
342 void clear() {
343 if (_ptr == nullptr) return;
344 delete[] _ptr;
345 _ptr = nullptr;
346 return;
347 }
348
353 T *release() {
354 T *p = _ptr;
355 _ptr = nullptr;
356 return p;
357 }
358
370 void reset(T *obj = nullptr) {
371 delete[] _ptr;
372 _ptr = obj;
373 return;
374 }
375
377 void swap(UniquePtr &other) noexcept { std::swap(_ptr, other._ptr); }
378
380 bool isNull() const { return _ptr == nullptr; }
381
383 bool isValid() const { return _ptr != nullptr; }
384
386 explicit operator bool() const { return _ptr != nullptr; }
387
388 bool operator==(const UniquePtr &other) const { return _ptr == other._ptr; }
389 bool operator!=(const UniquePtr &other) const { return _ptr != other._ptr; }
390 bool operator==(std::nullptr_t) const { return _ptr == nullptr; }
391 bool operator!=(std::nullptr_t) const { return _ptr != nullptr; }
392
400 T *ptr() const {
401 assert(_ptr != nullptr);
402 return _ptr;
403 }
404
408 T *get() const { return _ptr; }
409
417 T &operator[](size_t i) const {
418 assert(_ptr != nullptr);
419 return _ptr[i];
420 }
421
422 private:
423 T *_ptr = nullptr;
424};
425
427template <typename T> void swap(UniquePtr<T[]> &a, UniquePtr<T[]> &b) noexcept {
428 a.swap(b);
429}
430
451template <typename Derived, typename Base> UniquePtr<Derived> uniquePointerCast(UniquePtr<Base> &&up) {
452 static_assert(std::is_base_of_v<Base, Derived>, "Derived must publicly derive from Base");
453 if (up.isNull()) return UniquePtr<Derived>();
454 Derived *d = dynamic_cast<Derived *>(up.ptr());
455 if (d == nullptr) return UniquePtr<Derived>();
456 up.release();
457 return UniquePtr<Derived>::takeOwnership(d);
458}
459
460PROMEKI_NAMESPACE_END
461
462#endif // PROMEKI_ENABLE_CORE