#pragma once #include "gp/algorithm/modifiers.hpp" #include "gp/algorithm/move.hpp" #include "gp/buffer.hpp" #include "gp/function.hpp" template class unique_ptr; template class unique_ptr { T* ptr; gp::function deallocator; public: unique_ptr() : ptr{nullptr} {} template unique_ptr(T* _ptr, deal func) : ptr{_ptr} , deallocator{func} {} unique_ptr(unique_ptr&) = delete; unique_ptr(unique_ptr&& oth) : ptr{oth.ptr} , deallocator{oth.deallocator} { oth.ptr = nullptr; } void operator=(unique_ptr&) = delete; void operator=(unique_ptr&& oth) { ptr = oth.ptr; deallocator = oth.deallocator; oth.ptr = nullptr; } operator bool() { return ptr != nullptr; } T* operator->() { return ptr; } T* operator*() { return ptr; } ~unique_ptr() { if(ptr) { ptr->~T(); gp_config::assertion(deallocator(ptr), "freeing unique_ptr failed"); } } }; template class unique_ptr>{ T* ptr; gp::reference_wrapper ref; public: unique_ptr() : ptr{nullptr} {} template unique_ptr(Args ...args, allocator& _ref) : ref{_ref} { auto p = ref.get().allocate(sizeof(T)); if(p) { ptr = new(p) T(args...); } else { ptr = nullptr; } } unique_ptr(T* _ptr, allocator& _ref) : ptr{_ptr} , ref{_ref} {} unique_ptr(unique_ptr&) = delete; unique_ptr(unique_ptr&& oth) : ptr{oth.ptr} , ref{oth.ref} { oth.ptr = nullptr; } void operator=(unique_ptr&) = delete; void operator=(unique_ptr&& oth) { ptr = oth.ptr; ref = oth.ref; oth.ptr = nullptr; } operator bool() { return ptr != nullptr; } T* operator->() { return ptr; } T* operator*() { return ptr; } ~unique_ptr() { if(ptr) { ptr->~T(); gp_config::assertion(ref.get().deallocate(ptr), "freeing unique_ptr failed"); } } }; template class unique_ptr{ T* ptr; allocator alloc; public: unique_ptr() : ptr{nullptr} {} unique_ptr(T* _ptr, allocator _alloc = allocator{}) : ptr{_ptr} , alloc{_alloc} {} template unique_ptr(Args ...args, allocator _alloc = allocator{}) : alloc{_alloc} { auto p = alloc.allocate(sizeof(T)); if(p) { ptr = new(p) T(args...); } else { ptr = nullptr; } } unique_ptr(unique_ptr&) = delete; unique_ptr(unique_ptr&& oth) : ptr{oth.ptr} , alloc{oth.alloc} { oth.ptr = nullptr; } void operator=(unique_ptr&) = delete; void operator=(unique_ptr&& oth) { ptr = oth.ptr; alloc = oth.alloc; oth.ptr = nullptr; } operator bool() { return ptr != nullptr; } T* operator->() { return ptr; } T* operator*() { return ptr; } ~unique_ptr() { if(ptr) { ptr->~T(); gp_config::assertion(alloc.deallocate(ptr), "freeing unique_ptr failed"); } } }; class unique_array_ptr { gp::buffer data; };