#pragma once #include "copyable_functor.hpp" #include #include // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define COPYABLE_FUNCTOR_TEMPLATE \ template // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define COPYABLE_FUNCTOR CopyableFunctor COPYABLE_FUNCTOR_TEMPLATE COPYABLE_FUNCTOR::CopyableFunctor(Function &&function) : _functor(std::move(function)) {} COPYABLE_FUNCTOR_TEMPLATE COPYABLE_FUNCTOR::CopyableFunctor(const Function &function, const Allocator &allocator) : _functor(function, allocator) { } COPYABLE_FUNCTOR_TEMPLATE COPYABLE_FUNCTOR::CopyableFunctor(const Function &function, Allocator &&allocator) : _functor(function, std::move(allocator)) { } COPYABLE_FUNCTOR_TEMPLATE COPYABLE_FUNCTOR::CopyableFunctor(Function &&function, Allocator &&allocator) : _functor(std::move(function), std::move(allocator)) { } COPYABLE_FUNCTOR_TEMPLATE auto COPYABLE_FUNCTOR::operator()(Args &&...args) -> Return { return _functor(std::forward(args)...); } COPYABLE_FUNCTOR_TEMPLATE auto COPYABLE_FUNCTOR::clone() const -> ICopyableFunctor * { using AllocTraits = std::allocator_traits; using AllocHelper = typename RebindAllocHelper::type; auto alloc_helper = AllocHelper(_functor.get_allocator()); using Destructor = AllocDestructor; auto hold = std::unique_ptr(alloc_helper.allocate(1), Destructor(alloc_helper, 1)); ::new (static_cast(hold.get())) CopyableFunctor(_functor.target(), Allocator(alloc_helper)); return hold.release(); } COPYABLE_FUNCTOR_TEMPLATE void COPYABLE_FUNCTOR::clone(ICopyableFunctor *functor) const { ::new (static_cast(functor)) CopyableFunctor(_functor.target(), _functor.get_allocator()); } COPYABLE_FUNCTOR_TEMPLATE void COPYABLE_FUNCTOR::destroy() noexcept { _functor.destroy(); } COPYABLE_FUNCTOR_TEMPLATE void COPYABLE_FUNCTOR::destroy_deallocate() noexcept { using AllocTraits = std::allocator_traits; using AllocHelper = typename RebindAllocHelper::type; auto alloc_helper = AllocHelper(_functor.get_allocator()); _functor.destroy(); alloc_helper.deallocate(this, 1); } COPYABLE_FUNCTOR_TEMPLATE auto COPYABLE_FUNCTOR::target(const std::type_info &type_info) const noexcept -> const void * { if (type_info == typeid(Function)) { return std::addressof(_functor.target()); } return nullptr; } COPYABLE_FUNCTOR_TEMPLATE auto COPYABLE_FUNCTOR::target_type() const noexcept -> const std::type_info & { return typeid(Function); }