#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");
|
|
}
|
|
}
|
|
};
|