// ===================================================================================================================== // fennec, a free and open source game engine // Copyright (C) 2025 Medusa Slockbower // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. //2 // You should have received a copy of the GNU General Public License // along with this program. If not, see . // ===================================================================================================================== #ifndef FENNEC_MEMORY_POINTERS_H #define FENNEC_MEMORY_POINTERS_H #include namespace fennec { /// /// \brief Struct for wrapping C++ `delete` /// \tparam TypeT The type of the buffer to be deleted template struct default_delete { /// /// \brief Default constructor constexpr default_delete() noexcept = default; /// /// \brief Conversion Constructor /// \tparam ConvT of other deleter template requires requires { is_convertible{}.value == true; } constexpr default_delete(const default_delete&) noexcept {} /// /// \brief Function Call Operator, calls `delete` on `ptr` /// \param ptr Memory resource to delete constexpr void operator()(TypeT* ptr) const noexcept { static_assert(not is_void_v, "cannot delete a pointer to an incomplete type"); static_assert(not sizeof(TypeT) > 0, "cannot delete a pointer to an incomplete type"); delete ptr; } }; // Overload for Arrays template struct default_delete { /// /// \brief Default constructor constexpr default_delete() noexcept = default; /// /// \brief Conversion Constructor /// \tparam ConvT of other deleter template requires requires { is_convertible_v == true; } constexpr default_delete(const default_delete&) noexcept {} /// /// \brief Function Call Operator, calls `delete` on `ptr` /// \param ptr Memory resource to delete template requires requires { is_convertible_v == true; } constexpr void operator()(TypeT* ptr) const noexcept { static_assert(not is_void_v, "cannot delete a pointer to an incomplete type"); static_assert(not sizeof(TypeT) > 0, "cannot delete a pointer to an incomplete type"); delete[] ptr; } }; /// /// \brief /// \tparam TypeT /// \tparam DeleteT template> class unique_ptr { public: /// \brief the element type using element_t = TypeT; /// \brief pointer to element type using pointer_t = element_t*; /// \brief the deleter using delete_t = DeleteT; /// /// \brief Default Constructor, creates a unique_ptr that owns nothing. constexpr unique_ptr() : unique_ptr(nullptr) {} /// /// \brief Nullptr Constructor, creates a unique_ptr that owns nothing. constexpr unique_ptr(nullptr_t) noexcept : unique_ptr(nullptr) {} /// /// \brief Pointer Constructor, creates a unique_ptr that owns `ptr` with deleter `del` /// \param ptr The resource to own /// \param del The deleter explicit constexpr unique_ptr(pointer_t ptr, const delete_t& del) : _delete(del), _handle(ptr) { } /// /// \brief Pointer Constructor, creates a unique_ptr that owns `ptr` with deleter `del` /// \param ptr The resource to own /// \param del The deleter explicit constexpr unique_ptr(pointer_t ptr, delete_t&& del) : _delete(del), _handle(ptr) { } /// /// \brief Move Constructor, transfers ownership from `other` /// \param other The unique_ptr to take ownership from constexpr unique_ptr(unique_ptr&& other) : _handle(other._handle) { other._handle = nullptr; } // Delete copy constructor constexpr unique_ptr(const unique_ptr&) = delete; /// /// \brief Default Constructor, if it owns a resource, it deletes it using `delete_t` constexpr ~unique_ptr() { if(_handle) _delete(_handle); } constexpr unique_ptr& operator=(const unique_ptr&) = delete; constexpr unique_ptr& operator=(unique_ptr&& r) noexcept { _delete = r._delete; _handle = r._handle; r._handle = nullptr; return *this; } pointer_t release() { pointer_t retval = _handle; _handle = nullptr; return retval; } private: delete_t _delete; pointer_t _handle; }; } #endif // FENNEC_MEMORY_POINTERS_H