86 lines
2.8 KiB
C++
86 lines
2.8 KiB
C++
|
|
#pragma once
|
|
|
|
#if !defined(MIJIN_MEMORY_MEMUTIL_HPP_INCLUDED)
|
|
#define MIJIN_MEMORY_MEMUTIL_HPP_INCLUDED 1
|
|
|
|
#include <memory>
|
|
#include "../internal/common.hpp"
|
|
|
|
namespace mijin
|
|
{
|
|
template<typename TAllocator>
|
|
class AllocatorDeleter
|
|
{
|
|
public:
|
|
using value_type = std::allocator_traits<TAllocator>::value_type;
|
|
using pointer = std::allocator_traits<TAllocator>::pointer;
|
|
|
|
private:
|
|
[[no_unique_address]] TAllocator allocator_;
|
|
|
|
public:
|
|
explicit AllocatorDeleter(TAllocator allocator = {}) MIJIN_NOEXCEPT_IF(std::is_nothrow_move_constructible_v<TAllocator>)
|
|
: allocator_(std::move(allocator)) {}
|
|
|
|
template<typename TOtherAllocator> requires (std::is_constructible_v<TAllocator, const TOtherAllocator&>)
|
|
AllocatorDeleter(const AllocatorDeleter<TOtherAllocator>& other)
|
|
MIJIN_NOEXCEPT_IF((std::is_nothrow_constructible_v<TAllocator, TOtherAllocator>))
|
|
: allocator_(other.allocator_) {}
|
|
|
|
template<typename TOtherAllocator> requires (std::is_constructible_v<TAllocator, TOtherAllocator&&>)
|
|
AllocatorDeleter(AllocatorDeleter<TOtherAllocator>&& other)
|
|
MIJIN_NOEXCEPT_IF((std::is_nothrow_constructible_v<TAllocator, TOtherAllocator&&>))
|
|
: allocator_(std::move(other.allocator_)) {}
|
|
|
|
template<typename TOtherAllocator> requires (std::is_assignable_v<TAllocator&, const TOtherAllocator&>)
|
|
AllocatorDeleter& operator=(const AllocatorDeleter<TOtherAllocator>& other)
|
|
MIJIN_NOEXCEPT_IF((std::is_nothrow_assignable_v<TAllocator&, const TOtherAllocator&>))
|
|
{
|
|
if (this != static_cast<const void*>(&other))
|
|
{
|
|
allocator_ = other.allocator_;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template<typename TOtherAllocator> requires (std::is_assignable_v<TAllocator&, TOtherAllocator&&>)
|
|
AllocatorDeleter& operator=(AllocatorDeleter<TOtherAllocator>&& other)
|
|
MIJIN_NOEXCEPT_IF((std::is_nothrow_assignable_v<TAllocator&, TOtherAllocator&&>))
|
|
{
|
|
if (this != static_cast<const void*>(&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<typename TOtherAllocator>
|
|
friend class AllocatorDeleter;
|
|
};
|
|
|
|
template<typename T>
|
|
class AllocatorDeleter<std::allocator<T>>
|
|
{
|
|
public:
|
|
AllocatorDeleter() noexcept = default;
|
|
template<typename TOther>
|
|
AllocatorDeleter(const AllocatorDeleter<std::allocator<TOther>>&) noexcept {}
|
|
|
|
template<typename TOther>
|
|
AllocatorDeleter& operator=(const AllocatorDeleter<std::allocator<TOther>>&) noexcept { return *this; }
|
|
|
|
void operator()(T* ptr) const MIJIN_NOEXCEPT
|
|
{
|
|
delete ptr;
|
|
}
|
|
};
|
|
} // namespace mijin
|
|
|
|
#endif // !defined(MIJIN_MEMORY_MEMUTIL_HPP_INCLUDED)
|