General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

192 lines
2.9 KiB

#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");
}
}
};
class unique_array_ptr {
gp::buffer<char> data;
};