#pragma once #include "alloc_functor.hpp" template template auto InvokeReturnWrapper::call(Args &&...args) -> Return { return std::invoke(std::forward(args)...); } // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define ALLOC_FUNCTOR_TEMPLATE \ template // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define ALLOC_FUNCTOR AllocFunctor ALLOC_FUNCTOR_TEMPLATE ALLOC_FUNCTOR::AllocFunctor(Target &&function) : _function(std::piecewise_construct, std::forward_as_tuple(std::move(function)), std::forward_as_tuple()) { } ALLOC_FUNCTOR_TEMPLATE ALLOC_FUNCTOR::AllocFunctor(const Target &function, const Alloc &allocator) : _function(std::piecewise_construct, std::forward_as_tuple(function), std::forward_as_tuple(allocator)) { } ALLOC_FUNCTOR_TEMPLATE ALLOC_FUNCTOR::AllocFunctor(const Target &function, Alloc &&allocator) : _function(std::piecewise_construct, std::forward_as_tuple(function), std::forward_as_tuple(std::move(allocator))) { } ALLOC_FUNCTOR_TEMPLATE ALLOC_FUNCTOR::AllocFunctor(Target &&function, Alloc &&allocator) : _function(std::piecewise_construct, std::forward_as_tuple(std::move(function)), std::forward_as_tuple(std::move(allocator))) { } ALLOC_FUNCTOR_TEMPLATE auto ALLOC_FUNCTOR::operator()(Args &&...args) -> Return { using Invoker = InvokeReturnWrapper; return Invoker::call(_function.first(), std::forward(args)...); } ALLOC_FUNCTOR_TEMPLATE auto ALLOC_FUNCTOR::target() const -> const Target & { return _function.first(); } ALLOC_FUNCTOR_TEMPLATE auto ALLOC_FUNCTOR::get_allocator() const -> const Alloc & { return _function.second(); } ALLOC_FUNCTOR_TEMPLATE auto ALLOC_FUNCTOR::clone() const -> AllocFunctor * { using AllocTraits = std::allocator_traits; using AllocHelper = typename RebindAllocHelper::type; auto alloc_helper = AllocHelper(_function.second()); using Destructor = AllocDestructor; auto hold = std::unique_ptr(alloc_helper.allocate(1), _Dp(alloc_helper, 1)); ::new (static_cast(hold.get())) AllocFunctor(_function.first(), _Alloc(alloc_helper)); return hold.release(); } ALLOC_FUNCTOR_TEMPLATE void ALLOC_FUNCTOR::destroy() noexcept { _function.~CompressedPair(); } ALLOC_FUNCTOR_TEMPLATE void ALLOC_FUNCTOR::destroy_and_delete(AllocFunctor *functor) { using AllocTraits = std::allocator_traits; using FunctorAlloc = typename RebindAllocHelper::type; auto functor_alloc = FunctorAlloc(functor->get_allocator()); functor->destroy(); functor_alloc.deallocate(functor, 1); } // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define DEFAULT_ALLOC_FUNCTOR_TEMPLATE \ template // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define DEFAULT_ALLOC_FUNCTOR DefaultAllocFunctor DEFAULT_ALLOC_FUNCTOR_TEMPLATE DEFAULT_ALLOC_FUNCTOR::DefaultAllocFunctor(Target &&function) : _function(std::move(function)) { } DEFAULT_ALLOC_FUNCTOR_TEMPLATE DEFAULT_ALLOC_FUNCTOR::DefaultAllocFunctor(const Target &function) : _function(function) { } DEFAULT_ALLOC_FUNCTOR_TEMPLATE auto DEFAULT_ALLOC_FUNCTOR::operator()(Args &&...args) -> Return { using Invoker = InvokeReturnWrapper; return Invoker::call(_function, std::forward(args)...); } DEFAULT_ALLOC_FUNCTOR_TEMPLATE auto DEFAULT_ALLOC_FUNCTOR::target() const -> const Target & { return _function; } DEFAULT_ALLOC_FUNCTOR_TEMPLATE auto DEFAULT_ALLOC_FUNCTOR::clone() const -> DefaultAllocFunctor * { std::allocator allocator; DefaultAllocFunctor *functor_ptr = allocator.allocate(1); // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) auto *res = ::new (static_cast(functor_ptr)) DefaultAllocFunctor(_function); return res; } DEFAULT_ALLOC_FUNCTOR_TEMPLATE void DEFAULT_ALLOC_FUNCTOR::destroy() noexcept { _function.~_Target(); } DEFAULT_ALLOC_FUNCTOR_TEMPLATE void DEFAULT_ALLOC_FUNCTOR::destroy_and_delete(DefaultAllocFunctor *function) { function->destroy(); std::allocator allocator; allocator.deallocate(function, 1); }