diff options
author | HampusM <hampus@hampusmat.com> | 2022-04-10 17:20:49 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2022-06-13 17:56:58 +0200 |
commit | b36d072ad7a7b9c6e30fcb25d6bbb001a8393468 (patch) | |
tree | 7749fc877652bb2cf7bbd2b7c1fed5e3abe397fc /src/DI/alloc_functor.tpp | |
parent | b828d4799a84beb1afbd889e5c4cb939a8b3df78 (diff) |
refactor: add factory class & make DI container return unique ptrs
Diffstat (limited to 'src/DI/alloc_functor.tpp')
-rw-r--r-- | src/DI/alloc_functor.tpp | 165 |
1 files changed, 165 insertions, 0 deletions
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 <class Return> +template <class... Args> +auto InvokeReturnWrapper<Return>::call(Args &&...args) -> Return +{ + return std::invoke(std::forward<Args>(args)...); +} + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define ALLOC_FUNCTOR_TEMPLATE \ + template <class Function, class Allocator, class Return, class... Args> + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define ALLOC_FUNCTOR AllocFunctor<Function, Allocator, Return(Args...)> + +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>; + + return Invoker::call(_function.first(), std::forward<Args>(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<Alloc>; + + using AllocHelper = typename RebindAllocHelper<AllocTraits, AllocFunctor>::type; + + auto alloc_helper = AllocHelper(_function.second()); + + using Destructor = AllocDestructor<AllocHelper>; + + auto hold = std::unique_ptr<AllocFunctor, Destructor>(alloc_helper.allocate(1), + _Dp(alloc_helper, 1)); + + ::new (static_cast<void *>(hold.get())) + AllocFunctor(_function.first(), _Alloc(alloc_helper)); + + return hold.release(); +} + +ALLOC_FUNCTOR_TEMPLATE +void ALLOC_FUNCTOR::destroy() noexcept +{ + _function.~CompressedPair<Target, Alloc>(); +} + +ALLOC_FUNCTOR_TEMPLATE +void ALLOC_FUNCTOR::destroy_and_delete(AllocFunctor *functor) +{ + using AllocTraits = std::allocator_traits<Alloc>; + + using FunctorAlloc = typename RebindAllocHelper<AllocTraits, AllocFunctor>::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 <class Function, class Return, class... Args> + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define DEFAULT_ALLOC_FUNCTOR DefaultAllocFunctor<Function, Return(Args...)> + +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>; + + return Invoker::call(_function, std::forward<Args>(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<DefaultAllocFunctor> allocator; + + DefaultAllocFunctor *functor_ptr = allocator.allocate(1); + + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) + auto *res = ::new (static_cast<void *>(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<DefaultAllocFunctor> allocator; + + allocator.deallocate(function, 1); +} |