#ifndef KGR_KANGARU_INCLUDE_KANGARU_SERVICE_HPP #define KGR_KANGARU_INCLUDE_KANGARU_SERVICE_HPP #include #include "detail/utils.hpp" #include "detail/single.hpp" #include "generic.hpp" namespace kgr { template struct Dependency {}; template> struct SingleService; template struct SingleService> : GenericService>, Type>, Single { private: using Parent = GenericService>, Type>; public: using typename Parent::Self; using Parent::Parent; static auto construct(Inject... deps) -> decltype(inject(deps.forward()...)) { return inject(deps.forward()...); } Type& forward() { return this->instance(); } template static detail::function_result_t call(Type& instance, T method, Args&&... args) { return (instance.*method)(std::forward(args)...); } }; template> struct Service; template struct Service> : GenericService>, Type> { private: using Parent = GenericService>, Type>; public: using typename Parent::Self; using Parent::Parent; template static auto construct(Inject... deps, Args&&... args) -> decltype(inject(deps.forward()..., std::declval()...)) { return inject(deps.forward()..., std::forward(args)...); } Type forward() { return std::move(this->instance()); } template static detail::function_result_t call(Type& instance, T method, Args&&... args) { return (instance.*method)(std::forward(args)...); } }; template> struct UniqueService; template struct UniqueService> : GenericService>, std::unique_ptr> { private: using Parent = GenericService>, std::unique_ptr>; public: using typename Parent::Self; using Parent::Parent; template static auto construct(Inject... deps, Args&&... args) -> decltype(inject(std::unique_ptr{new Type{deps.forward()..., std::declval()...}})) { return inject(std::unique_ptr{new Type{deps.forward()..., std::forward(args)...}}); } std::unique_ptr forward() { return std::move(this->instance()); } template static detail::function_result_t call(std::unique_ptr& instance, T method, Args&&... args) { return ((*instance).*method)(std::forward(args)...); } }; template> struct SharedService; template struct SharedService> : GenericService>, std::shared_ptr>, Single { private: using Parent = GenericService>, std::shared_ptr>; public: using typename Parent::Self; using Parent::Parent; static auto construct(Inject... deps) -> decltype(inject(std::make_shared(deps.forward()...))) { return inject(std::make_shared(deps.forward()...)); } std::shared_ptr forward() { return this->instance(); } template static detail::function_result_t call(std::shared_ptr& instance, T method, Args&&... args) { return ((*instance).*method)(std::forward(args)...); } }; template struct AbstractService : Abstract { T& forward(); }; template struct AbstractSharedService : Abstract { std::shared_ptr forward(); }; } // namespace kgr #endif // KGR_KANGARU_INCLUDE_KANGARU_SERVICE_HPP