DiscordCoreAPI
A Discord bot library written in C++, with custom asynchronous coroutines.
Loading...
Searching...
No Matches
UniquePtr.hpp
Go to the documentation of this file.
1/*
2 MIT License
3
4 DiscordCoreAPI, A bot library for Discord, written in C++, and featuring explicit multithreading through the usage of custom, asynchronous C++ CoRoutines.
5
6 Copyright 2022, 2023 Chris M. (RealTimeChris)
7
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in all
16 copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 SOFTWARE.
25*/
26/// UniquePtr.hpp - Header for the "unique_ptr" related stuff.
27/// Dec 18, 2021
28/// https://discordcoreapi.com
29/// \file UniquePtr.hpp
30#pragma once
31
32#include <jsonifier/Index.hpp>
33
34namespace discord_core_api {
35
36 /**
37 * \addtogroup utilities
38 * @{
39 */
40
41 /// @brief A smart pointer class that provides unique ownership semantics.
42 /// @tparam value_type the type of the managed object.
43 /// @tparam deleter the type of the deleter used to destroy the object.
44 template<typename value_type, typename deleter = std::default_delete<value_type>> class unique_ptr : protected deleter {
45 public:
46 using element_type = std::remove_extent_t<value_type>;
47 using pointer = element_type*;
48 using deleter_type = deleter;
49 using reference = element_type&;
50
51 inline unique_ptr& operator=(const unique_ptr&) = delete;
52 inline unique_ptr(const unique_ptr&) = delete;
53
54 /// @brief Default constructor.
55 inline unique_ptr() : ptr{ nullptr } {};
56
57 /// @brief Move assignment operator for related pointers.
58 /// @param other the other unique_ptr to move from.
59 /// @return unique_ptr the new managed object inside a unique_ptr.
60 template<jsonifier::concepts::unique_ptr_t value_type_new> inline unique_ptr& operator=(value_type_new&& other) {
61 if (this != static_cast<void*>(&other)) {
62 reset();
63 try {
64 commit(other.release());
65 } catch (...) {
66 reset();
67 throw;
68 }
69 }
70 return *this;
71 }
72
73 /// @brief Move constructor for related pointers.
74 /// @param other the other unique_ptr to move from.
75 template<jsonifier::concepts::unique_ptr_t value_type_new> inline unique_ptr(value_type_new&& other) {
76 *this = std::move(other);
77 }
78
79 /// @brief Move assignment operator for raw pointer.
80 /// @param newPtr the new ptr to manage.
81 /// @return unique_ptr the new managed object inside a unique_ptr.
82 template<jsonifier::concepts::pointer_t value_type_new> inline unique_ptr& operator=(value_type_new newPtr) {
83 reset();
84 try {
85 commit(newPtr);
86 } catch (...) {
87 reset();
88 throw;
89 }
90 return *this;
91 }
92
93 /// @brief Constructor from a raw pointer.
94 /// @param newPtr the new ptr to manage.
95 template<jsonifier::concepts::pointer_t value_type_new> inline unique_ptr(value_type_new newPtr) {
96 *this = newPtr;
97 }
98
99 /// @brief Gets the managed raw pointer.
100 /// @return the managed raw pointer.
101 inline pointer get() const {
102 return ptr;
103 }
104
105 /// @brief Conversion operator to check if the pointer is valid.
106 /// @return `true` if the pointer is valid, `false` otherwise.
107 inline operator bool() const {
108 return ptr != nullptr;
109 }
110
111 /// @brief Dereference operator.
112 /// @return a reference to the managed object.
113 inline reference operator*() const {
114 if (!ptr) {
115 throw dca_exception{ "Sorry, but you attempted to access a unique_ptr that is nullptr." };
116 }
117 return *ptr;
118 }
119
120 /// @brief Member access operator.
121 /// @return the managed raw pointer.
122 inline pointer operator->() const {
123 if (!ptr) {
124 throw dca_exception{ "Sorry, but you attempted to access a unique_ptr that is nullptr." };
125 }
126 return ptr;
127 }
128
129 /// @brief Releases the managed pointer.
130 /// @return the released raw pointer.
131 inline pointer release() {
132 pointer releasedPtr = ptr;
133 ptr = nullptr;
134 return releasedPtr;
135 }
136
137 /// @brief Resets the managed pointer and invokes the deleter.
138 /// @param newPtr the new raw pointer to manage.
139 inline void reset(pointer newPtr = nullptr) {
140 pointer oldPtr = std::exchange(ptr, newPtr);
141 if (oldPtr) {
142 getDeleter()(oldPtr);
143 }
144 }
145
146 /// @brief Swaps the contents of two unique_ptr objects.
147 /// @param other the other unique_ptr to swap with.
148 inline void swap(unique_ptr& other) {
149 std::swap(ptr, other.ptr);
150 }
151
152 /// @brief Destructor that releases the managed object.
153 inline ~unique_ptr() {
154 reset(nullptr);
155 }
156
157 protected:
158 pointer ptr{ nullptr };///< The stored object.
159
160 /// @brief Commits a new pointer value and resets the current one.
161 /// @param other the new pointer value to commit.
162 inline void commit(pointer other) {
163 pointer tempPtr = other;
164 reset(tempPtr);
165 }
166
167 /// @brief Gets the deleter associated with the managed object.
168 /// @return the associated deleter.
169 inline deleter_type& getDeleter() {
170 return *static_cast<deleter_type*>(this);
171 }
172 };
173
174 /// @brief Specialization of unique_ptr for arrays.
175 /// @tparam value_type the type of the managed object.
176 /// @tparam deleter the type of the deleter used to destroy the object.
177 template<typename value_type, typename deleter> class unique_ptr<value_type[], deleter> : public deleter {
178 public:
179 using element_type = std::remove_extent_t<value_type>;
180 using pointer = element_type*;
181 using deleter_type = deleter;
182 using reference = element_type&;
183
184 inline unique_ptr& operator=(const unique_ptr&) = delete;
185 inline unique_ptr(const unique_ptr&) = delete;
186
187 /// @brief Default constructor.
188 inline unique_ptr() : ptr{ nullptr } {};
189
190 /// @brief Move assignment operator for related pointers.
191 /// @param other the other unique_ptr to move from.
192 /// @return unique_ptr the new managed object inside a unique_ptr.
193 template<jsonifier::concepts::unique_ptr_t value_type_new> inline unique_ptr& operator=(value_type_new&& other) {
194 if (this != static_cast<void*>(&other)) {
195 reset();
196 try {
197 commit(other.release());
198 } catch (...) {
199 reset();
200 throw;
201 }
202 }
203 return *this;
204 }
205
206 /// @brief Move constructor for related pointers.
207 /// @param other the other unique_ptr to move from.
208 template<jsonifier::concepts::unique_ptr_t value_type_new> inline unique_ptr(value_type_new&& other) {
209 *this = std::move(other);
210 }
211
212 /// @brief Move assignment operator for raw pointer.
213 /// @param newPtr the new ptr to manage.
214 /// @return unique_ptr the new managed object inside a unique_ptr.
215 template<jsonifier::concepts::pointer_t value_type_new> inline unique_ptr& operator=(value_type_new newPtr) {
216 reset();
217 try {
218 commit(newPtr);
219 } catch (...) {
220 reset();
221 throw;
222 }
223 return *this;
224 }
225
226 /// @brief Constructor from a raw pointer.
227 /// @param newPtr the new ptr to manage.
228 template<jsonifier::concepts::pointer_t value_type_new> inline unique_ptr(value_type_new newPtr) {
229 *this = newPtr;
230 }
231
232 /// @brief Gets the managed raw pointer.
233 /// @return pointer the managed raw pointer.
234 inline pointer get() const {
235 return ptr;
236 }
237
238 /// @brief Square bracket operator for accessing elements of this array.
239 /// @param index the index which is to be accessed.
240 /// @return reference a reference to the object that was accessed.
241 inline reference operator[](std::ptrdiff_t index) const {
242 return ptr[index];
243 }
244
245 /// @brief Conversion operator to check if the pointer is valid.
246 /// @return `true` if the pointer is valid, `false` otherwise.
247 inline operator bool() const {
248 return ptr != nullptr;
249 }
250
251 /// @brief Dereference operator.
252 /// @return a reference to the managed object.
253 inline reference operator*() const {
254 if (!ptr) {
255 throw dca_exception{ "Sorry, but you attempted to access a unique_ptr that is nullptr." };
256 }
257 return *ptr;
258 }
259
260 /// @brief Member access operator.
261 /// @return the managed raw pointer.
262 inline pointer operator->() const {
263 if (!ptr) {
264 throw dca_exception{ "Sorry, but you attempted to access a unique_ptr that is nullptr." };
265 }
266 return ptr;
267 }
268
269 /// @brief Releases the managed pointer.
270 /// @return the released raw pointer.
271 inline pointer release() {
272 pointer releasedPtr = ptr;
273 ptr = nullptr;
274 return releasedPtr;
275 }
276
277 /// @brief Resets the managed pointer and invokes the deleter.
278 /// @param newPtr the new raw pointer to manage.
279 inline void reset(pointer newPtr = nullptr) {
280 pointer oldPtr = std::exchange(ptr, newPtr);
281 if (oldPtr) {
282 getDeleter()(oldPtr);
283 }
284 }
285
286 /// @brief Swaps the contents of two unique_ptr objects.
287 /// @param other the other unique_ptr to swap with.
288 inline void swap(unique_ptr& other) {
289 std::swap(ptr, other.ptr);
290 }
291
292 /// @brief Destructor that releases the managed object.
293 inline ~unique_ptr() {
294 reset();
295 }
296
297 protected:
298 pointer ptr{ nullptr };///< The stored object.
299
300 /// @brief Commits a new pointer value and resets the current one.
301 /// @param other the new pointer value to commit.
302 inline void commit(pointer other) {
303 pointer tempPtr = other;
304 reset(tempPtr);
305 }
306
307 /// @brief Gets the deleter associated with the managed object.
308 /// @return the associated deleter.
309 inline deleter_type& getDeleter() {
310 return *static_cast<deleter_type*>(this);
311 }
312 };
313
314 /// @brief Helper function to create a unique_ptr for a non-array object.
315 /// @param args the arguments to construct the new object from.
316 /// @tparam value_type the type of value to store in the unique_ptr.
317 /// @tparam deleter the type of deleter to use for the stored object.
318 /// @tparam arg_types the types of arguments for constructing the object.
319 /// @return unique_ptr<value_type, deleter> the managed object.
320 template<typename value_type, typename deleter = std::default_delete<value_type>, typename... arg_types, std::enable_if_t<!std::is_array_v<value_type>, int32_t> = 0>
321 inline unique_ptr<value_type, deleter> makeUnique(arg_types&&... args) {
322 return unique_ptr<value_type, deleter>(new value_type(std::forward<arg_types>(args)...));
323 }
324
325 /// @brief Helper function to create a unique_ptr for a dynamic array.
326 /// @param size the size to allocate for the array.
327 /// @tparam value_type the type of value to store in the unique_ptr.
328 /// @tparam deleter the type of deleter to use for the stored object.
329 /// @return unique_ptr<value_type, deleter> the managed object.
330 template<typename value_type, typename deleter = std::default_delete<value_type>, std::enable_if_t<std::is_array_v<value_type> && std::extent_v<value_type> == 0, int32_t> = 0>
331 inline unique_ptr<value_type, deleter> makeUnique(const uint64_t size) {
332 using element_type = std::remove_extent_t<value_type>;
333 return unique_ptr<value_type, deleter>(new element_type[size]());
334 }
335
336 /// @brief Deleted overload for creating unique_ptr for static arrays.
337 template<typename value_type, typename... arg_types, std::enable_if_t<std::extent_v<value_type> != 0, int32_t> = 0> inline void makeUnique(arg_types&&...) = delete;
338
339 /**@}*/
340
341}
void reset(pointer newPtr=nullptr)
Resets the managed pointer and invokes the deleter.
Definition: UniquePtr.hpp:279
void swap(unique_ptr &other)
Swaps the contents of two unique_ptr objects.
Definition: UniquePtr.hpp:288
reference operator*() const
Dereference operator.
Definition: UniquePtr.hpp:253
void commit(pointer other)
Commits a new pointer value and resets the current one.
Definition: UniquePtr.hpp:302
deleter_type & getDeleter()
Gets the deleter associated with the managed object.
Definition: UniquePtr.hpp:309
unique_ptr(value_type_new &&other)
Move constructor for related pointers.
Definition: UniquePtr.hpp:208
unique_ptr(value_type_new newPtr)
Constructor from a raw pointer.
Definition: UniquePtr.hpp:228
pointer release()
Releases the managed pointer.
Definition: UniquePtr.hpp:271
unique_ptr & operator=(value_type_new newPtr)
Move assignment operator for raw pointer.
Definition: UniquePtr.hpp:215
~unique_ptr()
Destructor that releases the managed object.
Definition: UniquePtr.hpp:293
pointer get() const
Gets the managed raw pointer.
Definition: UniquePtr.hpp:234
unique_ptr & operator=(value_type_new &&other)
Move assignment operator for related pointers.
Definition: UniquePtr.hpp:193
reference operator[](std::ptrdiff_t index) const
Square bracket operator for accessing elements of this array.
Definition: UniquePtr.hpp:241
pointer operator->() const
Member access operator.
Definition: UniquePtr.hpp:262
A smart pointer class that provides unique ownership semantics.
Definition: UniquePtr.hpp:44
pointer get() const
Gets the managed raw pointer.
Definition: UniquePtr.hpp:101
void swap(unique_ptr &other)
Swaps the contents of two unique_ptr objects.
Definition: UniquePtr.hpp:148
deleter_type & getDeleter()
Gets the deleter associated with the managed object.
Definition: UniquePtr.hpp:169
unique_ptr & operator=(value_type_new newPtr)
Move assignment operator for raw pointer.
Definition: UniquePtr.hpp:82
reference operator*() const
Dereference operator.
Definition: UniquePtr.hpp:113
unique_ptr(value_type_new &&other)
Move constructor for related pointers.
Definition: UniquePtr.hpp:75
~unique_ptr()
Destructor that releases the managed object.
Definition: UniquePtr.hpp:153
pointer release()
Releases the managed pointer.
Definition: UniquePtr.hpp:131
unique_ptr()
Default constructor.
Definition: UniquePtr.hpp:55
unique_ptr & operator=(value_type_new &&other)
Move assignment operator for related pointers.
Definition: UniquePtr.hpp:60
unique_ptr(value_type_new newPtr)
Constructor from a raw pointer.
Definition: UniquePtr.hpp:95
pointer operator->() const
Member access operator.
Definition: UniquePtr.hpp:122
void reset(pointer newPtr=nullptr)
Resets the managed pointer and invokes the deleter.
Definition: UniquePtr.hpp:139
pointer ptr
The stored object.
Definition: UniquePtr.hpp:158
void commit(pointer other)
Commits a new pointer value and resets the current one.
Definition: UniquePtr.hpp:162
unique_ptr< value_type, deleter > makeUnique(arg_types &&... args)
Helper function to create a unique_ptr for a non-array object.
Definition: UniquePtr.hpp:321
The main namespace for the forward-facing interfaces.
An exception class derived from std::runtime_error for dca-related exceptions.
Definition: Base.hpp:820