diff options
Diffstat (limited to 'src/DI')
-rw-r--r-- | src/DI/concepts.hpp | 11 | ||||
-rw-r--r-- | src/DI/container.cpp | 6 | ||||
-rw-r--r-- | src/DI/container.hpp | 26 | ||||
-rw-r--r-- | src/DI/container.tpp | 46 |
4 files changed, 61 insertions, 28 deletions
diff --git a/src/DI/concepts.hpp b/src/DI/concepts.hpp new file mode 100644 index 0000000..12be546 --- /dev/null +++ b/src/DI/concepts.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "type_traits.hpp" + +#include <type_traits> + +template <typename Type> +concept Function = is_func_v<Type>; + +template <typename Type> +concept Abstract = std::is_abstract_v<Type>; diff --git a/src/DI/container.cpp b/src/DI/container.cpp new file mode 100644 index 0000000..4b86186 --- /dev/null +++ b/src/DI/container.cpp @@ -0,0 +1,6 @@ +#include "container.hpp" + +void Container::add(BaseObjectType type, const Ptr<IGenericWrapper> &wrapper) noexcept +{ + _bindings.insert({type, wrapper}); +} diff --git a/src/DI/container.hpp b/src/DI/container.hpp index 83f24ae..0c0155c 100644 --- a/src/DI/container.hpp +++ b/src/DI/container.hpp @@ -1,11 +1,12 @@ #pragma once #include "DI/interfaces/wrapper.hpp" + +#include "DI/concepts.hpp" #include "DI/object_type.hpp" -#include "DI/type_traits.hpp" +#include <concepts> #include <memory> -#include <type_traits> #include <unordered_map> class Container; @@ -16,8 +17,8 @@ class BindingBuilder public: explicit BindingBuilder(Container *container) noexcept; - template <class ObjectImpl, - class = std::enable_if_t<std::is_base_of_v<Interface, ObjectImpl>>> + template <typename Impl> + requires std::derived_from<Impl, Interface> void to() noexcept; void to_factory(Interface func) noexcept; @@ -31,17 +32,24 @@ class Container public: Container() noexcept = default; + template <typename Type> + using Ptr = std::shared_ptr<Type>; + template <class Interface> auto bind() noexcept -> BindingBuilder<Interface>; - template <class Interface, class = std::enable_if_t<std::is_abstract_v<Interface>>> - auto get() const noexcept -> std::shared_ptr<Interface>; + template <class Interface> + requires Abstract<Interface> + auto get() const noexcept -> Ptr<Interface>; - template <typename Interface, typename = std::enable_if_t<is_func_v<Interface>>> + template <typename Interface> + requires Function<Interface> auto get() const noexcept -> Interface; - std::unordered_map<BaseObjectType, std::shared_ptr<IGenericWrapper>, ObjectTypeHasher> - bindings; + void add(BaseObjectType type, const Ptr<IGenericWrapper> &wrapper) noexcept; + +private: + std::unordered_map<BaseObjectType, Ptr<IGenericWrapper>, ObjectTypeHasher> _bindings; }; #include "container.tpp" diff --git a/src/DI/container.tpp b/src/DI/container.tpp index 2573223..54b09c6 100644 --- a/src/DI/container.tpp +++ b/src/DI/container.tpp @@ -7,42 +7,49 @@ #include <iostream> -template <class Interface> +template <typename Interface> BindingBuilder<Interface>::BindingBuilder(Container *container) noexcept : _container(container) { } -template <class Interface> -template <class ObjectImpl, class> +template <typename Interface> +template <typename Impl> +requires std::derived_from<Impl, Interface> void BindingBuilder<Interface>::to() noexcept { - _container->bindings.emplace( - ObjectType<Interface>(), - std::dynamic_pointer_cast<IGenericWrapper>( - std::make_shared<ObjectWrapper<Interface, ObjectImpl>>(*_container))); + using Wrapper = ObjectWrapper<Interface, Impl>; + + auto wrapper = Container::Ptr<Wrapper>(new Wrapper(*_container)); + + _container->add(ObjectType<Interface>(), + std::dynamic_pointer_cast<IGenericWrapper>(wrapper)); } -template <class Interface> +template <typename Interface> void BindingBuilder<Interface>::to_factory(Interface func) noexcept { - _container->bindings.emplace(ObjectType<Interface>(), - std::dynamic_pointer_cast<IGenericWrapper>( - std::make_shared<FunctionWrapper<Interface>>(func))); + using Wrapper = FunctionWrapper<Interface>; + + auto wrapper = Container::Ptr<Wrapper>(new Wrapper(func)); + + _container->add(ObjectType<Interface>(), + std::dynamic_pointer_cast<IGenericWrapper>(wrapper)); } -template <class Interface> +template <typename Interface> auto Container::bind() noexcept -> BindingBuilder<Interface> { return BindingBuilder<Interface>(this); } -template <class Interface, class> -auto Container::get() const noexcept -> std::shared_ptr<Interface> +template <typename Interface> +requires Abstract<Interface> +auto Container::get() const noexcept -> Ptr<Interface> { ObjectType<Interface> interface_type; - if (bindings.count(interface_type) == 0) + if (_bindings.count(interface_type) == 0) { std::cerr << "Error: Tried to get a item from the container using unbound interface '" @@ -50,17 +57,18 @@ auto Container::get() const noexcept -> std::shared_ptr<Interface> exit(EXIT_FAILURE); } - auto wrapper = std::dynamic_pointer_cast<IWrapper<std::shared_ptr<Interface>>>( - bindings.at(interface_type)); + auto wrapper = + std::dynamic_pointer_cast<IWrapper<Ptr<Interface>>>(_bindings.at(interface_type)); return wrapper->get(); } -template <typename Interface, typename> +template <typename Interface> +requires Function<Interface> auto Container::get() const noexcept -> Interface { auto wrapper = std::dynamic_pointer_cast<IWrapper<Interface>>( - bindings.at(ObjectType<Interface>())); + _bindings.at(ObjectType<Interface>())); return wrapper->get(); } |