#pragma once #if !defined(MIJIN_MEMORY_MEMUTIL_HPP_INCLUDED) #define MIJIN_MEMORY_MEMUTIL_HPP_INCLUDED 1 #include #include "../internal/common.hpp" namespace mijin { template class AllocatorDeleter { public: using value_type = std::allocator_traits::value_type; using pointer = std::allocator_traits::pointer; private: [[no_unique_address]] TAllocator allocator_; public: AllocatorDeleter() = default; explicit AllocatorDeleter(TAllocator allocator) MIJIN_NOEXCEPT_IF(std::is_nothrow_move_constructible_v) : allocator_(std::move(allocator)) {} template requires (std::is_constructible_v) AllocatorDeleter(const AllocatorDeleter& other) MIJIN_NOEXCEPT_IF((std::is_nothrow_constructible_v)) : allocator_(other.allocator_) {} template requires (std::is_constructible_v) AllocatorDeleter(AllocatorDeleter&& other) MIJIN_NOEXCEPT_IF((std::is_nothrow_constructible_v)) : allocator_(std::move(other.allocator_)) {} template requires (std::is_assignable_v) AllocatorDeleter& operator=(const AllocatorDeleter& other) MIJIN_NOEXCEPT_IF((std::is_nothrow_assignable_v)) { if (this != static_cast(&other)) { allocator_ = other.allocator_; } return *this; } template requires (std::is_assignable_v) AllocatorDeleter& operator=(AllocatorDeleter&& other) MIJIN_NOEXCEPT_IF((std::is_nothrow_assignable_v)) { if (this != static_cast(&other)) { allocator_ = std::move(other.allocator_); } return *this; } void operator()(pointer ptr) MIJIN_NOEXCEPT_IF(noexcept(allocator_.deallocate(ptr, sizeof(value_type)))) { allocator_.deallocate(ptr, sizeof(value_type)); } template friend class AllocatorDeleter; }; template class AllocatorDeleter> { public: AllocatorDeleter() noexcept = default; template AllocatorDeleter(std::allocator) noexcept {} template AllocatorDeleter(const AllocatorDeleter>&) noexcept {} template AllocatorDeleter& operator=(const AllocatorDeleter>&) noexcept { return *this; } void operator()(T* ptr) const MIJIN_NOEXCEPT { delete ptr; } }; } // namespace mijin #endif // !defined(MIJIN_MEMORY_MEMUTIL_HPP_INCLUDED)