14 struct ArgumentResolver;
19 typedef std::shared_ptr<TArg> Type;
21 template <
typename CONTAINER>
44 struct ArgumentResolver<std::
vector<std::shared_ptr<TArg>>>
46 typedef std::vector<std::shared_ptr<TArg>> Type;
48 template <
typename CONTAINER>
56 struct ArgumentResolver<Container&>
58 typedef Container& Type;
66 template <
class T,
class TArgumentPack>
67 struct ConstructorDescriptor;
70 struct ConstructorDescriptor<T, std::
tuple<>>
72 static std::function<std::shared_ptr<T>(Container&)> CreateFactory()
74 return [](Container&) {
return std::make_shared<T>(); };
76 static T* Create(Container& c)
83 concept IsSupportedArgument =
requires (Container&
cnt) { { ArgumentResolver<T>::Resolve(
cnt) }; };
86 struct ConstructorDescriptor<T, std::
tuple<TAnyArgument...>>
88 static std::function<std::shared_ptr<T>(Container&)> CreateFactory()
94 static T* Create(Container& c)
100 struct ConstructorTypologyNotSupported
102 using Type = ConstructorTypologyNotSupported;
105 template <
class TParent>
106 struct ArgumentResolverInvoker
114 return ArgumentResolver<T>::Resolve(mContainer);
121 return ArgumentResolver<T&>::Resolve(mContainer);
126 Container& mContainer;
129 template <
class TParent>
147 template <
class T,
int>
148 struct WrapAndGet : AnyArgument<T> {};
150 template <
class,
class>
151 struct ConstructorTypologyDeducer;
154 template <
typename T>
155 requires std::is_constructible_v<T>
158 using Type = std::tuple<>;
162 requires (!std::is_constructible_v<T>)
163 struct ConstructorTypologyDeducer<T, std::integer_sequence<int>>
168 static constexpr inline size_t MaximumArgumentCount = 20;
173 struct ConstructorTypologyDeducer<T, std::integer_sequence<int, NthArgument...>>
175 using Type = std::tuple<WrapAndGet<T, NthArgument>...>;
180 struct ConstructorTypologyDeducer<T, std::
integer_sequence<int, NthArgument...>>
182 using Type =
typename ConstructorTypologyDeducer<T, std::make_integer_sequence<
int,
sizeof...(NthArgument) + 1>>::Type;
187 requires (
sizeof...(NthArgument) == MaximumArgumentCount) && std::is_constructible_v<T, WrapAndGet<T, NthArgument>...>
188 struct ConstructorTypologyDeducer<T, std::
integer_sequence<int, NthArgument...>>
190 using Type = std::tuple<WrapAndGet<T, NthArgument>...>;
194 requires (
sizeof...(NthArgument) == MaximumArgumentCount) && (!std::is_constructible_v<T, WrapAndGet<T, NthArgument>...>)
195 struct ConstructorTypologyDeducer<T, std::integer_sequence<int, NthArgument...>> : ConstructorTypologyNotSupported
199 template <
typename T>
204 template <
typename INTERFACE>
205 struct Container::ImplementationContainer
207 Lifetime CustomLifetime = Lifetime::Default;
210 std::shared_ptr<INTERFACE> StrongInstancePointer;
211 std::map<std::thread::id, std::shared_ptr<INTERFACE>> ThreadInstances;
212 mutable std::weak_ptr<INTERFACE> WeakInstancePointer;
213 std::function<std::shared_ptr<INTERFACE>(Container&)> mFactory;
214 std::function<
void(Container&, std::shared_ptr<INTERFACE>)> mOnCreate;
217 void Set(std::string_view name) { Name = std::string{ name }; }
219 void Set(DefaultImplementationStruct) { }
220 template <std::derived_from<INTERFACE> T>
221 void Set(std::function<std::shared_ptr<T>(Container&)>
factory)
227 void Set(std::shared_ptr<INTERFACE> instance) { StrongInstancePointer = std::move(instance); }
228 void Set(
INTERFACE* instance) { StrongInstancePointer = std::shared_ptr<INTERFACE>{ std::shared_ptr<INTERFACE>{}, instance }; }
229 void Set(std::function<
void(Container&, std::shared_ptr<INTERFACE>)>
on_create) { mOnCreate = std::move(
on_create); }
233 if (CustomLifetime != Lifetime::Default)
236 if (StrongInstancePointer)
237 return StrongInstancePointer;
239 if (
lifetime == Lifetime::ThreadSingleton)
241 auto&
ptr = ThreadInstances[std::this_thread::get_id()];
246 else if (
lifetime == Lifetime::WeakSingleton)
248 if (
auto result = WeakInstancePointer.lock(); result)
251 WeakInstancePointer =
ptr;
254 else if (
lifetime == Lifetime::InstanceSingleton)
264 StrongInstancePointer.reset();
265 WeakInstancePointer.reset();
266 ThreadInstances.clear();
274 container.mDebugStore.emplace(
obj.get(), std::pair<std::type_index, std::weak_ptr<void>>{ typeid(*obj), std::weak_ptr<void>{obj} });
279 mOnCreate(
container, std::static_pointer_cast<INTERFACE>(std::move(instance)));
287 template <
typename T>
288 concept has_default_lifetime =
requires { { T::DefaultLifetime } -> std::convertible_to<Lifetime>; };
290 template <
typename INTERFACE>
291 struct Container::InterfaceContainer : Container::BaseInterfaceContainer
293 template <
typename I = INTERFACE>
294 static constexpr Lifetime GetDeclaredLifetime()
296 if constexpr (has_default_lifetime<I>)
297 return I::DefaultLifetime;
299 return Lifetime::Default;
302 InterfaceContainer() : BaseInterfaceContainer(GetDeclaredLifetime<INTERFACE>()) {}
304 template <
typename IMPLEMENTATION,
typename... ARGS>
305 void RegisterImplementationType(ARGS&&... args)
307 if (mImplementations.contains(
typeid(IMPLEMENTATION)))
308 throw "already registered";
310 auto&
impl = mImplementations[
typeid(IMPLEMENTATION)];
311 if constexpr (is_same_as_any_v<DefaultImplementationStruct, ARGS...>)
312 mImplementationsInDeclarationOrder.insert(mImplementationsInDeclarationOrder.begin(), &
impl);
314 mImplementationsInDeclarationOrder.push_back(&
impl);
316 impl.Set(GetDeclaredLifetime<IMPLEMENTATION>());
317 (
impl.Set(std::forward<ARGS>(args)), ...);
320 template <
typename IMPLEMENTATION>
321 ImplementationContainer<INTERFACE>* GetImplementationContainer()
323 auto it = mImplementations.find(
typeid(IMPLEMENTATION));
324 if (it == mImplementations.end())
329 std::shared_ptr<INTERFACE> Resolve(Container& container, Lifetime lifetime)
331 if (DefaultLifetime != Lifetime::Default)
332 lifetime = DefaultLifetime;
334 if (mImplementationsInDeclarationOrder.empty())
337 return mImplementationsInDeclarationOrder.back()->Resolve(container, lifetime);
340 std::vector<std::shared_ptr<INTERFACE>> ResolveAll(Container& container, Lifetime lifetime)
342 std::vector<std::shared_ptr<INTERFACE>> result;
344 for (
auto& [type,
impl] : mImplementations)
345 result.push_back(
impl.Resolve(container, lifetime));
352 std::map<std::type_index, ImplementationContainer<INTERFACE>> mImplementations;
353 std::vector<ImplementationContainer<INTERFACE>*> mImplementationsInDeclarationOrder;
357 template <
typename INTERFACE>
358 bool Container::HasAnyImplementationsOf()
const
360 if (
auto it = mContainers.find(
typeid(INTERFACE)); it != mContainers.end())
361 return !it->second->mImplementations.empty();
365 template<
typename INTERFACE,
typename IMPLEMENTATION,
typename ...ARGS>
366 void Container::RegisterType(ARGS&& ...args)
370 static_assert(std::is_base_of_v<INTERFACE, IMPLEMENTATION>,
"Implementation class must inherit from interface class");
371 static_assert(!std::is_abstract_v<IMPLEMENTATION>,
"Implementation cannot be abstract");
372 if constexpr (std::is_base_of_v<INTERFACE, IMPLEMENTATION> && !std::is_abstract_v<IMPLEMENTATION>)
374 constexpr auto instance_given = is_same_as_any_v<std::shared_ptr<IMPLEMENTATION>, ARGS...>;
375 constexpr auto interface_factory = is_same_as_any_v<std::function<std::shared_ptr<INTERFACE>(
Container&)>, ARGS...>;
376 constexpr auto impl_factory = is_same_as_any_v<std::function<std::shared_ptr<IMPLEMENTATION>(
Container&)>, ARGS...>;
377 static_assert(!(instance_given && (interface_factory || impl_factory)),
"Cannot register type with both factory and instance");
378 if constexpr (instance_given || interface_factory || impl_factory)
379 GetInterfaceContainer<INTERFACE>().RegisterImplementationType<IMPLEMENTATION>(std::forward<ARGS>(args)...);
381 GetInterfaceContainer<INTERFACE>().RegisterImplementationType<IMPLEMENTATION>(detail::ConstructorDescriptorForClass<IMPLEMENTATION>::CreateFactory(), std::forward<ARGS>(args)...);
385 template<
typename INTERFACE>
386 std::shared_ptr<INTERFACE> Container::Resolve()
388 return GetInterfaceContainer<INTERFACE>().Resolve(*
this, DefaultLifetime);
391 template<
typename INTERFACE>
392 std::shared_ptr<INTERFACE> Container::ResolveByName(std::string_view name)
394 auto& interface_container = GetInterfaceContainer<INTERFACE>();
395 for (
auto&
impl : interface_container.mImplementations)
397 if (
impl.Name == name)
398 return impl.Resolve(*
this, DefaultLifetime);
403 template<
typename INTERFACE>
404 std::vector<std::shared_ptr<INTERFACE>> Container::ResolveAll()
406 return GetInterfaceContainer<INTERFACE>().ResolveAll(*
this, DefaultLifetime);
409 template <
typename TYPE>
410 std::shared_ptr<TYPE> Container::Create()
412 return std::shared_ptr<TYPE>{ detail::ConstructorDescriptorForClass<TYPE>::Create(*
this) };
415 template <
typename TYPE>
416 std::unique_ptr<TYPE> Container::CreateRaw()
418 return std::unique_ptr<TYPE>{ detail::ConstructorDescriptorForClass<TYPE>::Create(*
this) };
421 template<
typename INTERFACE>
422 Container::InterfaceContainer<INTERFACE>& Container::GetInterfaceContainer()
424 auto& container = mContainers[
typeid(INTERFACE)];
426 container = std::make_unique<InterfaceContainer<INTERFACE>>();
427 return *
static_cast<InterfaceContainer<INTERFACE>*
>(container.get());
430 template<
typename INTERFACE,
typename IMPLEMENTATION>
431 Container::ImplementationContainer<INTERFACE>* Container::GetImplementationContainer()
433 return GetInterfaceContainer<INTERFACE>().GetImplementationContainer<IMPLEMENTATION>();
436 template<
typename INSTANCE>
437 void Container::ReportCreation(std::shared_ptr<INSTANCE>
const& obj, std::function<
void(Container&, std::shared_ptr<void>)> func)
439 for (
auto& [ptr, callback] : mCreationsToReport)
441 if (ptr.get() == obj.get())
444 mCreationsToReport.emplace_back(static_pointer_cast<void>(obj), std::move(func));
447 template<
typename INTERFACE,
typename T>
448 std::shared_ptr<INTERFACE> Container::Instantiate(T& factory)
450 if (find(mResolutionStack.begin(), mResolutionStack.end(),
typeid(INTERFACE)) != mResolutionStack.end())
451 throw "circular dependency";
452 mResolutionStack.push_back(
typeid(INTERFACE));
454 auto result = factory(*
this);
456 mResolutionStack.pop_back();
457 if (mResolutionStack.empty())
458 ReportAwaitingCreations();
460 return std::static_pointer_cast<INTERFACE>(std::move(result));
constexpr auto bit_count
Equal to the number of bits in the type.
The below code is based on Sun's libm library code, which is licensed under the following license:
TODO: Split into ContainerBuilder and Container (or [Dependency]Registry and [Dependency]Container) O...
std::shared_ptr< TYPE > Create()
Other.
std::shared_ptr< INTERFACE > Resolve()
Resolves.