/* * 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 . */ #ifndef TRINITY_MEMORY_H #define TRINITY_MEMORY_H #include "CompilerDefs.h" #include #include #if TRINITY_COMPILER == TRINITY_COMPILER_GNU #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wignored-attributes" #endif namespace Trinity { namespace Impl { template 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 struct stateless_unique_ptr_deleter { using pointer = T; void operator()(pointer ptr) const { if constexpr (std::is_member_function_pointer_v) (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(&FreeV1)); * * std::unique_ptr 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 requires std::invocable && std::is_pointer_v Impl::stateful_unique_ptr_deleter unique_ptr_deleter(Del deleter) { return Impl::stateful_unique_ptr_deleter(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()); * * class Resource * { * std::unique_ptr File; * }; * @endcode */ template requires std::invocable && std::is_pointer_v Impl::stateless_unique_ptr_deleter unique_ptr_deleter() { return Impl::stateless_unique_ptr_deleter(); } /** * 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) * @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 Del> requires std::invocable && std::is_pointer_v inline std::unique_ptr> make_unique_ptr_with_deleter(Ptr ptr, Del deleter) { return std::unique_ptr>(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) * @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> requires std::invocable && std::is_pointer_v inline std::unique_ptr> make_unique_ptr_with_deleter(Ptr ptr) { return std::unique_ptr>(ptr); } } #if TRINITY_COMPILER == TRINITY_COMPILER_GNU #pragma GCC diagnostic pop #endif #endif // TRINITY_MEMORY_H