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 <type_traits>
16#include <utility>
17#include <promeki/namespace.h>
18
19PROMEKI_NAMESPACE_BEGIN
20
61template <typename T> class UniquePtr {
62 public:
63 // All UniquePtr instantiations are friends of each other so the
64 // upcast/downcast helpers can reach the private _ptr across
65 // type boundaries.
66 template <typename U> friend class UniquePtr;
67
69 UniquePtr() = default;
70
72 UniquePtr(std::nullptr_t) noexcept {}
73
75 UniquePtr(const UniquePtr &) = delete;
76
78 UniquePtr &operator=(const UniquePtr &) = delete;
79
81 UniquePtr(UniquePtr &&o) noexcept : _ptr(o._ptr) { o._ptr = nullptr; }
82
91 template <typename U, typename = std::enable_if_t<std::is_base_of_v<T, U> && !std::is_same_v<T, U>>>
92 UniquePtr(UniquePtr<U> &&o) noexcept : _ptr(o._ptr) {
93 o._ptr = nullptr;
94 }
95
96 ~UniquePtr() { clear(); }
97
99 UniquePtr &operator=(UniquePtr &&o) noexcept {
100 if (&o == this) return *this;
101 clear();
102 _ptr = o._ptr;
103 o._ptr = nullptr;
104 return *this;
105 }
106
113 template <typename U, typename = std::enable_if_t<std::is_base_of_v<T, U> && !std::is_same_v<T, U>>>
114 UniquePtr &operator=(UniquePtr<U> &&o) noexcept {
115 clear();
116 _ptr = o._ptr;
117 o._ptr = nullptr;
118 return *this;
119 }
120
125 template <typename... Args> static UniquePtr create(Args &&...args) {
126 UniquePtr up;
127 up._ptr = new T(std::forward<Args>(args)...);
128 return up;
129 }
130
139 static UniquePtr takeOwnership(T *obj) {
140 UniquePtr up;
141 up._ptr = obj;
142 return up;
143 }
144
146 void clear() {
147 if (_ptr == nullptr) return;
148 delete _ptr;
149 _ptr = nullptr;
150 return;
151 }
152
161 T *release() {
162 T *p = _ptr;
163 _ptr = nullptr;
164 return p;
165 }
166
179 void reset(T *obj = nullptr) {
180 delete _ptr;
181 _ptr = obj;
182 return;
183 }
184
186 void swap(UniquePtr &other) noexcept { std::swap(_ptr, other._ptr); }
187
189 bool isNull() const { return _ptr == nullptr; }
190
192 bool isValid() const { return _ptr != nullptr; }
193
195 explicit operator bool() const { return _ptr != nullptr; }
196
197 bool operator==(const UniquePtr &other) const { return _ptr == other._ptr; }
198 bool operator!=(const UniquePtr &other) const { return _ptr != other._ptr; }
199 bool operator==(std::nullptr_t) const { return _ptr == nullptr; }
200 bool operator!=(std::nullptr_t) const { return _ptr != nullptr; }
201
209 T *ptr() const {
210 assert(_ptr != nullptr);
211 return _ptr;
212 }
213
221 T *get() const { return _ptr; }
222
223 T *operator->() const { return ptr(); }
224 T &operator*() const { return *ptr(); }
225
226 private:
227 T *_ptr = nullptr;
228};
229
231template <typename T> void swap(UniquePtr<T> &a, UniquePtr<T> &b) noexcept {
232 a.swap(b);
233}
234
264template <typename T> class UniquePtr<T[]> {
265 public:
267 UniquePtr() = default;
268
270 UniquePtr(std::nullptr_t) noexcept {}
271
273 UniquePtr(const UniquePtr &) = delete;
274
276 UniquePtr &operator=(const UniquePtr &) = delete;
277
279 UniquePtr(UniquePtr &&o) noexcept : _ptr(o._ptr) { o._ptr = nullptr; }
280
281 ~UniquePtr() { clear(); }
282
284 UniquePtr &operator=(UniquePtr &&o) noexcept {
285 if (&o == this) return *this;
286 clear();
287 _ptr = o._ptr;
288 o._ptr = nullptr;
289 return *this;
290 }
291
301 static UniquePtr createArray(size_t n) {
302 UniquePtr up;
303 up._ptr = new T[n];
304 return up;
305 }
306
320 static UniquePtr createArrayValueInit(size_t n) {
321 UniquePtr up;
322 up._ptr = new T[n]();
323 return up;
324 }
325
334 static UniquePtr takeOwnership(T *obj) {
335 UniquePtr up;
336 up._ptr = obj;
337 return up;
338 }
339
341 void clear() {
342 if (_ptr == nullptr) return;
343 delete[] _ptr;
344 _ptr = nullptr;
345 return;
346 }
347
352 T *release() {
353 T *p = _ptr;
354 _ptr = nullptr;
355 return p;
356 }
357
369 void reset(T *obj = nullptr) {
370 delete[] _ptr;
371 _ptr = obj;
372 return;
373 }
374
376 void swap(UniquePtr &other) noexcept { std::swap(_ptr, other._ptr); }
377
379 bool isNull() const { return _ptr == nullptr; }
380
382 bool isValid() const { return _ptr != nullptr; }
383
385 explicit operator bool() const { return _ptr != nullptr; }
386
387 bool operator==(const UniquePtr &other) const { return _ptr == other._ptr; }
388 bool operator!=(const UniquePtr &other) const { return _ptr != other._ptr; }
389 bool operator==(std::nullptr_t) const { return _ptr == nullptr; }
390 bool operator!=(std::nullptr_t) const { return _ptr != nullptr; }
391
399 T *ptr() const {
400 assert(_ptr != nullptr);
401 return _ptr;
402 }
403
407 T *get() const { return _ptr; }
408
416 T &operator[](size_t i) const {
417 assert(_ptr != nullptr);
418 return _ptr[i];
419 }
420
421 private:
422 T *_ptr = nullptr;
423};
424
426template <typename T> void swap(UniquePtr<T[]> &a, UniquePtr<T[]> &b) noexcept {
427 a.swap(b);
428}
429
450template <typename Derived, typename Base> UniquePtr<Derived> uniquePointerCast(UniquePtr<Base> &&up) {
451 static_assert(std::is_base_of_v<Base, Derived>, "Derived must publicly derive from Base");
452 if (up.isNull()) return UniquePtr<Derived>();
453 Derived *d = dynamic_cast<Derived *>(up.ptr());
454 if (d == nullptr) return UniquePtr<Derived>();
455 up.release();
456 return UniquePtr<Derived>::takeOwnership(d);
457}
458
459PROMEKI_NAMESPACE_END
460
461#endif // PROMEKI_ENABLE_CORE