|
|
- #pragma once
-
- #include "gp/algorithm/modifiers.hpp"
- #include "gp/algorithm/move.hpp"
- #include "gp/buffer.hpp"
- #include "gp/function.hpp"
-
- template<typename T, typename allocator_t = void>
- class unique_ptr;
-
- template<typename T>
- class unique_ptr<T, void> {
- T* ptr;
- gp::function<bool(T*)> deallocator;
- public:
- unique_ptr()
- : ptr{nullptr}
- {}
-
- template<typename deal>
- 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<typename T, typename allocator>
- class unique_ptr<T, gp::reference_wrapper<allocator>>{
- T* ptr;
- gp::reference_wrapper<allocator> ref;
- public:
- unique_ptr()
- : ptr{nullptr}
- {}
-
- template<typename ...Args>
- 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<typename T, typename allocator>
- class unique_ptr{
- T* ptr;
- allocator alloc;
- public:
- unique_ptr()
- : ptr{nullptr}
- {}
-
- unique_ptr(T* _ptr, allocator _alloc = allocator{})
- : ptr{_ptr}
- , alloc{_alloc}
- {}
-
- template<typename ...Args>
- 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");
- }
- }
- };
|