#ifndef KGR_KANGARU_INCLUDE_KANGARU_GENERIC_HPP #define KGR_KANGARU_INCLUDE_KANGARU_GENERIC_HPP #include "container.hpp" #include "detail/injected.hpp" #include "detail/traits.hpp" namespace kgr { namespace detail { template struct GenericServiceDestruction { ~GenericServiceDestruction() { static_cast(*this).instance().~Type(); } }; template struct GenericServiceDestruction::value>> {}; template struct autocall_function; } // namespace detail template struct GenericService : detail::GenericServiceDestruction, Type> { friend struct Container; using Self = CRTP; GenericService() = default; GenericService(GenericService&& other) { emplace(std::move(other.instance())); } GenericService& operator=(GenericService&& other) { emplace(std::move(other.instance())); return *this; } GenericService(const GenericService& other) { emplace(other.instance()); } GenericService& operator=(const GenericService& other) { emplace(other.instance()); return *this; } template::value, int> = 0> GenericService(in_place_t, Args&&... args) { emplace(std::forward(args)...); } protected: Type& instance() { return *reinterpret_cast(&_instance); } const Type& instance() const { return *reinterpret_cast(&_instance); } private: friend struct detail::GenericServiceDestruction, Type>; template friend struct detail::has_emplace_helper; template friend struct detail::autocall_function; template::value, int> = 0> void emplace(Args&&... args) { new (&_instance) Type(std::forward(args)...); } template::value, int> = 0> void emplace(Args&&... args) { new (&_instance) Type{std::forward(args)...}; } template void autocall(Inject... others) { CRTP::call(instance(), F::value, std::forward>(others).forward()...); } template class Map> void autocall(Inject cs) { autocall(detail::tuple_seq>{}, std::move(cs)); } template class Map, typename F, std::size_t... S> void autocall(detail::seq, Inject cs) { cs.forward().invoke([this](detail::function_argument_t... args){ CRTP::call(instance(), F::value, std::forward>(args)...); }); } detail::aligned_storage_t _instance; }; } // namespace kgr #endif // KGR_KANGARU_INCLUDE_KANGARU_GENERIC_HPP