91 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			3.0 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:
 | 
						|
    AllocatorDeleter() = default;
 | 
						|
    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(std::allocator<TOther>) noexcept {}
 | 
						|
 | 
						|
    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)
 |