Grindstone Game Engine v0.2.0
An open source game engine and toolkit.
Loading...
Searching...
No Matches
UniquePtr.hpp
1#pragma once
2
3#include <functional>
4
5namespace Grindstone {
6 template<typename T>
7 class UniquePtr {
8 public:
9
10 UniquePtr() : ptr(nullptr), deleteFn() {}
11
12 explicit UniquePtr(T* ptr, std::function<void(void*)> newDeleteFn) : ptr(ptr), deleteFn(newDeleteFn) {}
13
14 UniquePtr(std::nullptr_t) : ptr(nullptr), deleteFn() {}
15
16 // Deleted Copy operations
17 UniquePtr(const UniquePtr<T>& other) = delete;
18 UniquePtr& operator=(const UniquePtr<T>& other) = delete;
19
20 UniquePtr& operator=(std::nullptr_t) {
21 Release();
22 return *this;
23 }
24
25 UniquePtr(UniquePtr&& other) noexcept
26 : ptr(other.ptr), deleteFn(std::move(other.deleteFn)) {
27 other.ptr = nullptr;
28 other.deleteFn = std::function<void(void*)>{};
29
30 }
31
32 UniquePtr& operator=(UniquePtr&& other) noexcept {
33 UniquePtr tmp(std::move(other));
34 Swap(tmp);
35 return *this;
36 }
37
38 template<typename U,
39 std::enable_if_t<std::is_convertible_v<U*, T*>, int> = 0>
40 UniquePtr(UniquePtr<U>&& other) noexcept
41 : ptr(other.Get()), deleteFn(std::move(other.GetDeleter())) {
42 other.Release();
43 }
44
45 template<typename U,
46 std::enable_if_t<std::is_convertible_v<U*, T*>, int> = 0>
47 UniquePtr& operator=(UniquePtr<U>&& other) noexcept {
48 if (this != reinterpret_cast<UniquePtr<T>*>(&other)) {
49 Reset();
50 ptr = other.Release();
51 deleteFn = std::move(other.GetDeleter());
52 }
53 return *this;
54 }
55
56 T* Release() noexcept {
57 T* emptyPtr = nullptr;
58 std::swap(emptyPtr, ptr);
59 deleteFn = std::function<void(void*)>{};
60
61 return emptyPtr;
62 }
63
64 void Reset() noexcept {
65 if (ptr != nullptr) {
66 std::destroy_at(ptr);
67
68 if (deleteFn) {
69 deleteFn(ptr);
70 }
71
72 ptr = nullptr;
73 }
74
75 deleteFn = std::function<void(void*)>{};
76 }
77
78 void Swap(UniquePtr& other) noexcept {
79 std::swap(ptr, other.ptr);
80 std::swap(deleteFn, other.deleteFn);
81 }
82
83 bool operator==(const Grindstone::UniquePtr<T>& other) const noexcept {
84 return ptr == other.ptr && deleteFn.target<void(void)>() == other.deleteFn.target<void(void)>();
85 }
86
87 bool operator==(const T* other) const noexcept {
88 return ptr == other;
89 }
90
91 bool operator==(std::nullptr_t) const noexcept {
92 return ptr == nullptr;
93 }
94
95 explicit operator T*() const {
96 return ptr;
97 }
98
99 explicit operator bool() const {
100 return ptr != nullptr;
101 }
102
103 T* operator->() {
104 return this->ptr;
105 }
106
107 const T* operator->() const {
108 return this->ptr;
109 }
110
111 T& operator*() {
112 return *(this->ptr);
113 }
114
115 const T& operator*() const {
116 return *(this->ptr);
117 }
118
119 T* Get() {
120 return this->ptr;
121 }
122
123 const T* Get() const {
124 return this->ptr;
125 }
126
127 const std::function<void(void*)>& GetDeleter() const {
128 return this->deleteFn;
129 }
130
131 ~UniquePtr() {
132 Reset();
133 }
134
135 template<typename U>
136 bool operator==(const UniquePtr<U>& other) const noexcept {
137 static_assert(std::is_convertible_v<U*, T*> || std::is_convertible_v<T*, U*>,
138 "UniquePtr comparison requires compatible pointer types.");
139 return ptr == other.ptr && deleteFn == other.deleteFn;
140 }
141
142 private:
143 T* ptr = nullptr;
144 std::function<void(void*)> deleteFn;
145 };
146}
Definition UniquePtr.hpp:7