diff --git a/include/cserver/engine/components.hpp b/include/cserver/engine/components.hpp index e7e62b3..f2a97e8 100644 --- a/include/cserver/engine/components.hpp +++ b/include/cserver/engine/components.hpp @@ -5,7 +5,7 @@ namespace cserver { struct SeparatedComponent {}; template -using Options = utempl::TypeList; +struct Options : utempl::TypeList {}; template struct ComponentConfig {}; @@ -97,7 +97,127 @@ struct ServiceContext { }; +namespace impl { +namespace loopholes { + +template +struct Getter { + friend constexpr auto Magic(Getter); +}; +template +struct Injector { + friend constexpr auto Magic(Getter) {return Value;}; +}; + + +template +concept Injected = requires{Magic(Getter{});}; + +template +struct TagWithTalue {}; + + +template {}>{}> +constexpr auto CounterImpl(...) { + return I; +}; + +template +consteval auto CounterImpl(std::size_t arg) requires Injected{}, Ts...> { + return CounterImpl(arg); +}; + + +template < + typename Tag, + typename... Ts, + auto R = CounterImpl<0, Tag, Ts...>(std::size_t{}) +> +consteval auto Counter(auto...) { + return R; +}; + + +} // namespace loopholes + + +template +struct DependencyInfoKey {}; + +template +inline constexpr auto Use() { + std::ignore = T{Args...}; +}; + +template +consteval auto Ignore() {}; + +template +struct DependencyInfoInjector { + static constexpr ConstexprConfig kConfig = config; +private: + template + static consteval auto FindComponentTypeImpl(ComponentConfig...) { + constexpr auto I = utempl::Find(utempl::Tuple{std::string_view{names}...}, std::string_view{name}); + return [] -> decltype(utempl::Get(utempl::TypeList{})) {}(); + }; +public: + template + using FindComponentType = decltype(FindComponentTypeImpl(Ts{}...)); + + template + static constexpr auto FindComponentName = + [] + (ComponentConfig...) { + return Get(utempl::TypeList{})>(utempl::Tuple{names...}); + }(Ts{}...); + + template < + utempl::ConstexprString name, + typename..., + std::size_t I = loopholes::Counter>(), + auto = loopholes::Injector< + DependencyInfoKey< + Current, + I + >{}, + utempl::TypeList>>{} + >{} + > + static constexpr auto FindComponent() -> FindComponentType&; + + template < + typename T, + typename..., + std::size_t I = loopholes::Counter>>(), + auto = loopholes::Injector< + DependencyInfoKey< + Current, + I + >{}, + utempl::TypeList{} + >{} + > + static constexpr auto FindComponent() -> T&; + + template + static consteval auto GetDependencies() requires + requires {Magic(loopholes::Getter{}>{});} { + if constexpr(requires{GetDependencies();}) { + return GetDependencies{}>{}))::Type>(); + } else { + return utempl::kTypeList{}>{}))::Type>; + }; + }; + + template + static inline consteval auto Inject() { + Ignore{}, DependencyInfoInjector{}>())>(); + }; +}; + +} // namespace impl template struct ServiceContextBuilder {