IceShard 1
A personal game engine project, with development focused on 2D/2.5D games.
Loading...
Searching...
No Matches
mem_unique_ptr.hxx
Go to the documentation of this file.
1
3
4#pragma once
6
7namespace ice
8{
9
10 template<typename T>
11 struct UniquePtr;
12
13 template<typename T, typename... Args>
14 inline auto make_unique(ice::Allocator& alloc, Args&&... args) noexcept -> ice::UniquePtr<T>;
15
16 template<typename T>
17 using UniquePtrCustomDeleter = void(T*) noexcept;
18
19 template<typename T>
20 inline auto make_unique(ice::UniquePtrCustomDeleter<T>* fn_deleter, T* instanced_object) noexcept -> ice::UniquePtr<T>;
21
22
23 template<typename T>
24 struct UniquePtr
25 {
26 struct UserDeleterInfo;
27
28 inline UniquePtr() noexcept;
29 inline ~UniquePtr() noexcept;
30
31 inline explicit UniquePtr(ice::Allocator* alloc, T* ptr) noexcept;
32 inline explicit UniquePtr(ice::UniquePtrCustomDeleter<T>* deleter_fn, T* ptr) noexcept;
33
34 inline UniquePtr(UniquePtr&& other) noexcept;
35 template<typename U> requires std::is_base_of_v<T, U>
36 inline UniquePtr(UniquePtr<U>&& other) noexcept;
37
38 inline auto operator=(UniquePtr&& other) noexcept -> UniquePtr&;
39 template<typename U> requires std::is_base_of_v<T, U>
40 inline auto operator=(UniquePtr<U>&& other) noexcept -> UniquePtr&;
41 inline auto operator=(std::nullptr_t) noexcept -> UniquePtr&;
42
43 bool operator==(std::nullptr_t) const noexcept { return _ptr == nullptr; }
44
45 auto operator->() const noexcept -> T* { return _ptr; }
46 auto operator*() const noexcept -> T& { return *_ptr; }
47
48 inline auto get() const noexcept -> T* { return _ptr; }
49 inline void reset() noexcept;
50
52 T* _ptr;
53 void* _deleter;
54 };
55
56 template<typename T>
58 {
59 //ice::Allocator* alloc;
61 };
62
63 template<typename T>
64 inline UniquePtr<T>::UniquePtr() noexcept
65 : _alloc{ nullptr }
66 , _ptr{ nullptr }
67 { }
68
69 template<typename T>
70 inline UniquePtr<T>::~UniquePtr() noexcept
71 {
72 reset();
73 }
74
75 template<typename T>
77 : _alloc{ alloc }
78 , _ptr{ ptr }
79 , _deleter{ nullptr }
80 { }
81
82 template<typename T>
83 inline UniquePtr<T>::UniquePtr(ice::UniquePtrCustomDeleter<T>* deleter_fn, T* ptr) noexcept
84 : _alloc{ nullptr }
85 , _ptr{ ptr }
86 , _deleter{ reinterpret_cast<void*>(deleter_fn) }
87 { }
88
89 template<typename T>
90 inline UniquePtr<T>::UniquePtr(UniquePtr&& other) noexcept
91 : _alloc{ std::exchange(other._alloc, nullptr) }
92 , _ptr{ std::exchange(other._ptr, nullptr) }
93 , _deleter{ std::exchange(other._deleter, nullptr) }
94 {
95 }
96
97 template<typename T>
98 template<typename U> requires std::is_base_of_v<T, U>
99 inline UniquePtr<T>::UniquePtr(UniquePtr<U>&& other) noexcept
100 : _alloc{ std::exchange(other._alloc, nullptr) }
101 , _ptr{ std::exchange(other._ptr, nullptr) }
102 , _deleter{ std::exchange(other._deleter, nullptr) }
103 {
104 }
105
106 template<typename T>
107 inline auto UniquePtr<T>::operator=(UniquePtr&& other) noexcept -> UniquePtr&
108 {
109 if (this != &other)
110 {
111 reset();
112
113 _alloc = std::exchange(other._alloc, nullptr);
114 _ptr = std::exchange(other._ptr, nullptr);
115 _deleter = std::exchange(other._deleter, nullptr);
116 }
117 return *this;
118 }
119
120 template<typename T>
121 template<typename U> requires std::is_base_of_v<T, U>
122 inline auto UniquePtr<T>::operator=(UniquePtr<U>&& other) noexcept -> UniquePtr&
123 {
124 reset();
125
126 _alloc = std::exchange(other._alloc, nullptr);
127 _ptr = std::exchange(other._ptr, nullptr);
128 _deleter = std::exchange(other._deleter, nullptr);
129 return *this;
130 }
131
132 template<typename T>
133 inline auto UniquePtr<T>::operator=(std::nullptr_t) noexcept -> UniquePtr&
134 {
135 reset();
136 return *this;
137 }
138
139 template<typename T>
140 inline void UniquePtr<T>::reset() noexcept
141 {
142 if (_ptr == nullptr)
143 {
144 return;
145 }
146
147 // If we don't have a 'special' case
148 if (_alloc != nullptr)
149 {
150 if constexpr (ice::is_type_complete<T>)
151 {
152 ICE_ASSERT_CORE(_deleter == nullptr); // TODO: Implement various deleters
153 _alloc->destroy(_ptr);
154 }
155 else
156 {
157 //static_assert(ice::is_type_complete<T>);
158 ICE_ASSERT_CORE(_deleter != nullptr); // MEMORY LEAK INBOUND! Cannot delete object of incomplete type!
159 }
160 }
161 else
162 {
163 ICE_ASSERT_CORE(_deleter != nullptr); // TODO: Implement various deleters
164 ice::UniquePtrCustomDeleter<T>* fn_deleter = std::bit_cast<ice::UniquePtrCustomDeleter<T>*>(_deleter);
165 fn_deleter(_ptr);
166 }
167
168 _alloc = nullptr;
169 _ptr = nullptr;
170 _deleter = nullptr;
171 }
172
173 template<typename T, typename... Args>
174 concept MakeUniqueConstructorAvailable = requires(Args&&... args) {
175 { new T{ std::forward<Args>(args)... } } -> std::convertible_to<T*>;
176 };
177
178 template<typename T, typename... Args>
179 inline auto make_unique(ice::Allocator& alloc, Args&&... args) noexcept -> ice::UniquePtr<T>
180 {
181 static_assert(std::is_abstract_v<T> == false, "Can't instantiate an abstract type!");
182 static_assert(MakeUniqueConstructorAvailable<T, decltype(ice::forward<Args>(args))...>, "Can't call the constructor for the given type and arguments!");
183 return ice::UniquePtr<T>{ &alloc, alloc.create<T>(ice::forward<Args>(args)...) };
184 }
185
186 template<typename T>
187 inline auto make_unique(ice::UniquePtrCustomDeleter<T>* fn_deleter, T* instanced_object) noexcept -> ice::UniquePtr<T>
188 {
189 return ice::UniquePtr<T>{ fn_deleter, instanced_object };
190 }
191
192} // namespace ice
#define ICE_ASSERT_CORE(expression)
Definition assert_core.hxx:43
Definition mem_unique_ptr.hxx:174
SPDX-License-Identifier: MIT.
Definition array.hxx:12
constexpr bool is_type_complete
Definition base.hxx:76
auto alloc(ice::usize size) noexcept -> ice::AllocResult
auto make_unique(ice::Allocator &alloc, Args &&... args) noexcept -> ice::UniquePtr< T >
Definition mem_unique_ptr.hxx:179
void(T *) noexcept UniquePtrCustomDeleter
Definition mem_unique_ptr.hxx:17
ice::AllocatorBase< ice::build::is_debug||ice::build::is_develop > Allocator
Definition mem_types.hxx:25
Definition mem_unique_ptr.hxx:58
ice::UniquePtrCustomDeleter< T > * fn_deleter
Definition mem_unique_ptr.hxx:60
Definition mem_unique_ptr.hxx:25
Allocator * _alloc
Definition mem_unique_ptr.hxx:51
ParamsInternal * _ptr
Definition mem_unique_ptr.hxx:52
auto operator*() const noexcept -> T &
Definition mem_unique_ptr.hxx:46
~UniquePtr() noexcept
Definition mem_unique_ptr.hxx:70
auto get() const noexcept -> T *
Definition mem_unique_ptr.hxx:48
auto operator->() const noexcept -> T *
Definition mem_unique_ptr.hxx:45
void reset() noexcept
Definition mem_unique_ptr.hxx:140
void * _deleter
Definition mem_unique_ptr.hxx:53
auto operator=(UniquePtr &&other) noexcept -> UniquePtr &
Definition mem_unique_ptr.hxx:107
UniquePtr() noexcept
Definition mem_unique_ptr.hxx:64