From b36d072ad7a7b9c6e30fcb25d6bbb001a8393468 Mon Sep 17 00:00:00 2001 From: HampusM Date: Sun, 10 Apr 2022 17:20:49 +0200 Subject: refactor: add factory class & make DI container return unique ptrs --- src/DI/alloc_functor.tpp | 165 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 src/DI/alloc_functor.tpp (limited to 'src/DI/alloc_functor.tpp') diff --git a/src/DI/alloc_functor.tpp b/src/DI/alloc_functor.tpp new file mode 100644 index 0000000..d3f6946 --- /dev/null +++ b/src/DI/alloc_functor.tpp @@ -0,0 +1,165 @@ +#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); +} -- cgit v1.2.3-18-g5258