#pragma once #include #include #include namespace gj { class iAllocator { public: template struct Deleter { Deleter() = default; Deleter(Deleter&&) = default; Deleter(const Deleter&) = delete; Deleter& operator=(Deleter&&) = default; Deleter& operator=(const Deleter&) = delete; Deleter(iAllocator* alloc) : alloc_(alloc) { } void operator()(T* ptr) { assert(alloc_); ptr->~T(); alloc_->Free(ptr); } iAllocator* alloc_; }; template using UniqPtr = std::unique_ptr>; iAllocator(iAllocator&&) = default; iAllocator(const iAllocator&) = default; iAllocator& operator=(iAllocator&&) = default; iAllocator& operator=(const iAllocator&) = default; iAllocator() = default; virtual ~iAllocator() = default; virtual void* Alloc(const size_t size) = 0; virtual void Free(void* ptr) = 0; template T* Alloc(size_t n = 1) { return reinterpret_cast(Alloc(sizeof(T) * n)); } template UniqPtr MakeUniq(Args&&... args) { T* ptr = Alloc(); return std::unique_ptr>(new(ptr) T(std::forward(args)...), Deleter(this)); } template UniqPtr MakeUniq(Args&&... args) { T* ptr = Alloc(); return std::unique_ptr>(new(ptr) T(std::forward(args)...), Deleter(this)); } template UniqPtr MakeUniqArray(size_t n) { T* ptr = Alloc(n); return std::unique_ptr>(ptr, Deleter(this)); } }; template using UniqPtr = iAllocator::UniqPtr; }