#pragma once #include #include #include "common.h" namespace mem { template struct aligned_ptr; template<> struct aligned_ptr; using aligned_ptr_util = aligned_ptr; template<> struct aligned_ptr final { template static inline T* alloc(T&& value) { u8* ptr = reinterpret_cast(_alloc(alignof(T), sizeof(T))); new(ptr) T(std::move(value)); return reinterpret_cast(ptr); } template static inline T* alloc() { return alloc(T()); } template static inline T* make(Args&&... init) { return alloc(T(std::forward(init)...)); } template static inline void dealloc(T* ptr) { ptr->~T(); _dealloc(reinterpret_cast(ptr)); } private: static void* _alloc(usize align, usize size); static void _dealloc(void* ptr); constexpr inline ~aligned_ptr(){} }; template struct aligned_ptr final { inline explicit aligned_ptr(T* raw) : ptr(raw){} inline aligned_ptr(aligned_ptr&& move) : ptr(move.ptr) { *const_cast(&move.ptr) = nullptr; } inline aligned_ptr(T&& box) : aligned_ptr(aligned_ptr_util::alloc(std::move(box))){} inline aligned_ptr() : aligned_ptr(T()){} inline ~aligned_ptr() { if(ptr) aligned_ptr::dealloc(ptr); } inline aligned_ptr clone() const { return aligned_ptr(*this); } inline const T & get() const { if(ptr) return *ptr; else throw "TODO: moved"; } inline T & get() { if(ptr) return *ptr; else throw "TODO: moved"; } inline const T * get_ptr() const { if(ptr) return ptr; else throw "TODO: moved"; } inline T * get_ptr() { if(ptr) return ptr; else throw "TODO: moved"; } inline const T * operator->() const { return get_ptr(); } inline T * operator->() { return get_ptr(); } inline const T & operator*() const { return get(); } inline T & operator*() { return get(); } inline operator const T*() const { return get_ptr(); } inline operator T*() { return get_ptr(); } inline aligned_ptr& operator=(aligned_ptr&& other) { if(ptr) aligned_ptr::dealloc(ptr); *const_cast(&ptr) = other.ptr; *const_cast(&other.ptr) = nullptr; return *this; } private: inline aligned_ptr& operator=(const aligned_ptr& other) { return (*this = other.clone()); } inline aligned_ptr(const aligned_ptr& copy) : ptr(aligned_ptr::make(copy.get())){} T* const ptr; }; template inline aligned_ptr make_aligned(Args&&... init) { return aligned_ptr(aligned_ptr_util::template make(std::forward(init)...)); } }