Files
cpp-thirdparty/noarch/include/kangaru/service.hpp
Bassem Girgis 81b4b9e273 Initial commit
2018-12-20 17:34:07 -06:00

131 lines
3.9 KiB
C++

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