mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
175 lines
6.0 KiB
C++
175 lines
6.0 KiB
C++
/*
|
|
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
* option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef TRINITY_MEMORY_H
|
|
#define TRINITY_MEMORY_H
|
|
|
|
#include "CompilerDefs.h"
|
|
#include <concepts>
|
|
#include <memory>
|
|
|
|
#if TRINITY_COMPILER == TRINITY_COMPILER_GNU
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wignored-attributes"
|
|
#endif
|
|
|
|
namespace Trinity
|
|
{
|
|
namespace Impl
|
|
{
|
|
template<typename T, typename Del>
|
|
struct stateful_unique_ptr_deleter
|
|
{
|
|
using pointer = T;
|
|
explicit(false) stateful_unique_ptr_deleter(Del deleter) : _deleter(std::move(deleter)) { }
|
|
void operator()(pointer ptr) const { (void)_deleter(ptr); }
|
|
|
|
private:
|
|
Del _deleter;
|
|
};
|
|
|
|
template<typename T, auto Del>
|
|
struct stateless_unique_ptr_deleter
|
|
{
|
|
using pointer = T;
|
|
void operator()(pointer ptr) const
|
|
{
|
|
if constexpr (std::is_member_function_pointer_v<decltype(Del)>)
|
|
(void)(ptr->*Del)();
|
|
else
|
|
(void)Del(ptr);
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Convenience function to construct type aliases for std::unique_ptr stateful deleters (such as lambda with captures)
|
|
* @tparam Ptr Type of the pointer
|
|
* @tparam Del Type of object freeing function (deduced from argument)
|
|
* @param deleter Object deleter
|
|
*
|
|
* Example use
|
|
* @code
|
|
* void FreeV1(Resource*);
|
|
* void FreeV2(Resource*);
|
|
*
|
|
* using ResourceDeleter = decltype(Trinity::unique_ptr_deleter<Resource*>(&FreeV1));
|
|
*
|
|
* std::unique_ptr<Resource, ResourceDeleter> resource = Trinity::make_unique_ptr_with_deleter(GetResourceV1(), &FreeV1);
|
|
* // do stuff ...
|
|
* // ... later get new resource
|
|
* resource = Trinity::make_unique_ptr_with_deleter(GetResourceV2(), &FreeV2);
|
|
* @endcode
|
|
*/
|
|
template <typename Ptr, typename Del> requires std::invocable<Del, Ptr> && std::is_pointer_v<Ptr>
|
|
Impl::stateful_unique_ptr_deleter<Ptr, Del> unique_ptr_deleter(Del deleter)
|
|
{
|
|
return Impl::stateful_unique_ptr_deleter<Ptr, Del>(std::move(deleter));
|
|
}
|
|
|
|
/**
|
|
* Convenience function to construct type aliases for std::unique_ptr stateful deleters (such as lambda with captures)
|
|
*
|
|
* Main use is for forming struct/class members without the call to make_unique_ptr_with_deleter
|
|
* @tparam Ptr Type of the pointer
|
|
* @tparam Del The freeing function. This can be either a free function pointer that accepts T* as argument, pointer to a member function of T that accepts no arguments or a lambda with no captures
|
|
*
|
|
* Example use
|
|
* @code
|
|
* using FileDeleter = decltype(Trinity::unique_ptr_deleter<FILE*, &::fclose>());
|
|
*
|
|
* class Resource
|
|
* {
|
|
* std::unique_ptr<FILE, FileDeleter> File;
|
|
* };
|
|
* @endcode
|
|
*/
|
|
template <typename Ptr, auto Del> requires std::invocable<decltype(Del), Ptr> && std::is_pointer_v<Ptr>
|
|
Impl::stateless_unique_ptr_deleter<Ptr, Del> unique_ptr_deleter()
|
|
{
|
|
return Impl::stateless_unique_ptr_deleter<Ptr, Del>();
|
|
}
|
|
|
|
/**
|
|
* Utility function to construct a std::unique_ptr object with custom stateful deleter (such as lambda with captures)
|
|
* @tparam Ptr Type of the pointer
|
|
* @tparam T Type of the pointed-to object (defaults to std::remove_pointer_t<Ptr>)
|
|
* @tparam Del Type of object freeing function (deduced from second argument)
|
|
* @param ptr Raw pointer to owned object
|
|
* @param deleter Object deleter
|
|
*
|
|
* Example use
|
|
* @code
|
|
* class Resource
|
|
* {
|
|
* };
|
|
* class ResourceService
|
|
* {
|
|
* Resource* Create();
|
|
* void Destroy(Resource*);
|
|
* };
|
|
*
|
|
* ResourceService* service = GetResourceService();
|
|
*
|
|
* // Lambda that captures all required variables for destruction
|
|
* auto resource = Trinity::make_unique_ptr_with_deleter(service->Create(), [service](Resource* res){ service->Destroy(res); });
|
|
* @endcode
|
|
*/
|
|
template<typename Ptr, typename T = std::remove_pointer_t<Ptr>, typename Del> requires std::invocable<Del, Ptr> && std::is_pointer_v<Ptr>
|
|
inline std::unique_ptr<T, Impl::stateful_unique_ptr_deleter<Ptr, Del>> make_unique_ptr_with_deleter(Ptr ptr, Del deleter)
|
|
{
|
|
return std::unique_ptr<T, Impl::stateful_unique_ptr_deleter<Ptr, Del>>(ptr, std::move(deleter));
|
|
}
|
|
|
|
/**
|
|
* Utility function to construct a std::unique_ptr object with custom stateless deleter (function pointer, captureless lambda)
|
|
* @tparam Del The freeing function. This can be either a free function pointer that accepts T* as argument, pointer to a member function of T that accepts no arguments or a lambda with no captures
|
|
* @tparam Ptr Type of the pointer
|
|
* @tparam T Type of the pointed-to object (defaults to std::remove_pointer_t<Ptr>)
|
|
* @param ptr Raw pointer to owned object
|
|
*
|
|
* Example uses
|
|
* @code
|
|
* void DestroyResource(Resource*);
|
|
* class Resource
|
|
* {
|
|
* void Destroy();
|
|
* };
|
|
*
|
|
* // Free function
|
|
* auto free = Trinity::make_unique_ptr_with_deleter<&DestroyResource>(new Resource());
|
|
*
|
|
* // Member function
|
|
* auto member = Trinity::make_unique_ptr_with_deleter<&Resource::Destroy>(new Resource());
|
|
*
|
|
* // Lambda
|
|
* auto lambda = Trinity::make_unique_ptr_with_deleter<[](Resource* res){ res->Destroy(); }>(new Resource());
|
|
* @endcode
|
|
*/
|
|
template<auto Del, typename Ptr, typename T = std::remove_pointer_t<Ptr>> requires std::invocable<decltype(Del), Ptr> && std::is_pointer_v<Ptr>
|
|
inline std::unique_ptr<T, Impl::stateless_unique_ptr_deleter<Ptr, Del>> make_unique_ptr_with_deleter(Ptr ptr)
|
|
{
|
|
return std::unique_ptr<T, Impl::stateless_unique_ptr_deleter<Ptr, Del>>(ptr);
|
|
}
|
|
}
|
|
|
|
#if TRINITY_COMPILER == TRINITY_COMPILER_GNU
|
|
#pragma GCC diagnostic pop
|
|
#endif
|
|
|
|
#endif // TRINITY_MEMORY_H
|