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/value_functor.tpp | 189 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 src/DI/value_functor.tpp (limited to 'src/DI/value_functor.tpp') diff --git a/src/DI/value_functor.tpp b/src/DI/value_functor.tpp new file mode 100644 index 0000000..3665f18 --- /dev/null +++ b/src/DI/value_functor.tpp @@ -0,0 +1,189 @@ +#pragma once + +#include "value_functor.hpp" + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define VALUE_FUNCTOR_TEMPLATE template + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define VALUE_FUNCTOR ValueFunctor + +VALUE_FUNCTOR_TEMPLATE +VALUE_FUNCTOR::ValueFunctor() noexcept : _functor(nullptr) {} + +VALUE_FUNCTOR_TEMPLATE +template +VALUE_FUNCTOR::ValueFunctor(Function &&function, const Allocator &allocator) + : _functor(nullptr) +{ + using AllocTraits = std::allocator_traits; + + using Functor = CopyableFunctor; + + using FunctorAlloc = typename RebindAllocHelper::type; + + if (not_null(function)) + { + auto functor_alloc = FunctorAlloc(allocator); + + if (sizeof(Functor) <= sizeof(_buf) && + std::is_nothrow_copy_constructible::value && + std::is_nothrow_copy_constructible::value) + { + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) + _functor = ::new (static_cast(&_buf)) + Functor(std::forward(function), Allocator(functor_alloc)); + } + else + { + using Destructor = AllocDestructor; + + auto hold = std::unique_ptr( + functor_alloc.allocate(1), Destructor(functor_alloc, 1)); + + ::new (static_cast(hold.get())) + Functor(std::forward(function), Allocator(allocator)); + + _functor = hold.release(); + } + } +} + +VALUE_FUNCTOR_TEMPLATE +VALUE_FUNCTOR::ValueFunctor(const ValueFunctor &val_functor) +{ + if (val_functor._functor == nullptr) + { + _functor = nullptr; + } + else if (static_cast(val_functor._functor) == &val_functor._buf) + { + _functor = _as_copyable_functor(&_buf); + val_functor._functor->clone(_functor); + } + else + { + _functor = val_functor._functor->clone(); + } +} + +VALUE_FUNCTOR_TEMPLATE +VALUE_FUNCTOR::ValueFunctor(ValueFunctor &&val_functor) noexcept +{ + if (val_functor._functor == nullptr) + { + _functor = nullptr; + } + else if (static_cast(val_functor._functor) == &val_functor._buf) + { + _functor = _as_copyable_functor(&_buf); + val_functor._functor->clone(_functor); + } + else + { + _functor = val_functor._functor; + val_functor._functor = nullptr; + } +} + +VALUE_FUNCTOR_TEMPLATE +VALUE_FUNCTOR::~ValueFunctor() +{ + if (static_cast(_functor) == &_buf) + { + _functor->destroy(); + } + else if (_functor) + { + _functor->destroy_deallocate(); + } +} + +VALUE_FUNCTOR_TEMPLATE +auto VALUE_FUNCTOR::operator=(ValueFunctor &&val_functor) noexcept -> ValueFunctor & +{ + *this = nullptr; + + if (val_functor._functor == nullptr) + { + _functor = nullptr; + } + else if (static_cast(val_functor._functor) == &val_functor._buf) + { + _functor = _as_copyable_functor(&_buf); + val_functor._functor->clone(_functor); + } + else + { + _functor = val_functor._functor; + val_functor._functor = nullptr; + } + + return *this; +} + +VALUE_FUNCTOR_TEMPLATE +auto VALUE_FUNCTOR::operator=(std::nullptr_t) -> ValueFunctor & +{ + TargetFunctor *old_functor = _functor; + + _functor = nullptr; + + if (static_cast(old_functor) == &_buf) + { + old_functor->destroy(); + } + else if (old_functor) + { + old_functor->destroy_deallocate(); + } + + return *this; +} + +VALUE_FUNCTOR_TEMPLATE +auto VALUE_FUNCTOR::operator()(Args &&...args) const -> Return +{ + if (_functor == nullptr) + { + std::abort(); + } + + return (*_functor)(std::forward(args)...); +} + +VALUE_FUNCTOR_TEMPLATE +VALUE_FUNCTOR::operator bool() const noexcept +{ + return _functor != nullptr; +} + +VALUE_FUNCTOR_TEMPLATE +auto VALUE_FUNCTOR::target_type() const noexcept -> const std::type_info & +{ + if (_functor == nullptr) + { + return typeid(void); + } + + return _functor->target_type(); +} + +VALUE_FUNCTOR_TEMPLATE +template +auto VALUE_FUNCTOR::target() const noexcept -> const Target * +{ + if (_functor == nullptr) + { + return nullptr; + } + + return static_cast(_functor->target(typeid(Target))); +} + +VALUE_FUNCTOR_TEMPLATE +auto VALUE_FUNCTOR::_as_copyable_functor(void *function_ptr) -> TargetFunctor * +{ + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + return reinterpret_cast(function_ptr); +} -- cgit v1.2.3-18-g5258