#ifndef KGR_KANGARU_INCLUDE_KANGARU_DETAIL_INJECTED_HPP #define KGR_KANGARU_INCLUDE_KANGARU_DETAIL_INJECTED_HPP #include "utils.hpp" #include "single.hpp" #include "traits.hpp" namespace kgr { struct Container; namespace detail { template struct BaseInjectedHelper { virtual ~BaseInjectedHelper() = default; kgr::detail::Sink forward(); }; template struct BaseInjectedHelper>> { virtual ~BaseInjectedHelper() = default; virtual ServiceType forward() = 0; }; template struct BaseInjected : BaseInjectedHelper {}; template struct SingleInjected final : BaseInjected { friend struct kgr::Container; template::value, int> = 0> explicit SingleInjected(Args&&... args) : _service{std::forward(args)...} {} template::value && std::is_constructible::value, int> = 0> explicit SingleInjected(Args&&... args) : _service(std::forward(args)...) {} ServiceType forward() override { return _service.forward(); } private: T& get() { return _service; } const T& get() const { return _service; } T _service; }; template struct ServiceOverride final : BaseInjected { explicit ServiceOverride(Original& service) : _service{service} {} ServiceType forward() override { return static_cast>(_service.forward()); } private: Original& _service; }; template struct Injected final { friend struct kgr::Container; template::value, int> = 0> explicit Injected(Args&&... args) : _service{std::forward(args)...} {} template::value && std::is_constructible::value, int> = 0> explicit Injected(Args&&... args) : _service(std::forward(args)...) {} ServiceType forward() { return _service.forward(); } private: T& get() { return _service; } const T& get() const { return _service; } T _service; }; template struct original; template struct original&> { using type = T; }; template struct original&&> { using type = T; }; template using original_t = typename original::type; template using injected_argument_t = original_t>; } // namespace detail template using Inject = typename std::conditional::value || detail::is_single::value, detail::BaseInjected&, detail::Injected&&>::type; template std::tuple...> inject(Args&&... args) { return std::tuple...>{std::forward(args)...}; } } // namespace kgr #endif // KGR_KANGARU_INCLUDE_KANGARU_DETAIL_INJECTED_HPP