diff options
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-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 | ||||
-rw-r--r-- | src/bootstrap.cpp | 6 |
6 files changed, 64 insertions, 32 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4aa4a40..6daeadb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,6 +32,7 @@ file(GLOB SOURCES commands/move_cursor.cpp commands/quit.cpp commands/toggle_pause.cpp + DI/container.cpp DI/object_type.cpp) add_executable(${PROJECT_NAME} ${SOURCES}) 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(); } diff --git a/src/bootstrap.cpp b/src/bootstrap.cpp index 1436301..f22c689 100644 --- a/src/bootstrap.cpp +++ b/src/bootstrap.cpp @@ -31,6 +31,7 @@ #include "randomization/generator.hpp" #include "randomization/seed_generator.hpp" +#include "DI/concepts.hpp" #include "util/function.hpp" #include <concepts> @@ -38,11 +39,8 @@ #include <random> #include <string_view> -template <typename Type> -concept abstract = std::is_abstract_v<Type>; - template <typename Interface, typename Impl, typename... Params> -requires abstract<Interface> && std::derived_from<Impl, Interface> && +requires Abstract<Interface> && std::derived_from<Impl, Interface> && std::constructible_from<Impl, Params...> auto construct_as_interface(Params &&...parameters) -> std::shared_ptr<Interface> { |