capydi
Loading...
Searching...
No Matches
Decorator.hpp
Go to the documentation of this file.
1#ifndef DECORATOR_HPP_
2#define DECORATOR_HPP_
3
8#include "capydi/Error.hpp"
9
17
18namespace capy::di
19{
20
21template<
22 typename Decorator_,
23 typename Decoratee,
24 std::size_t SIZE = 0
25>
28 Decorator<Decorator_, Decoratee, SIZE>
29 >
30{
31public:
32 using RelatedEntity = Decoratee;
34
35public:
37
38public:
39 explicit Decorator(std::array<DependencyTagPair, SIZE> dependency_tags = {})
40 : inner_config_{}
41 , dependency_tags_ { dependency_tags }
42 {}
43
47 std::array<DependencyTagPair, SIZE> dependency_tags = {}
48 )
49 : inner_config_{}
50 , dependency_tags_ { dependency_tags }
51 {}
52
53public:
54 Resolution<RelatedEntity, Error> auto
56 meta::Reference<RelatedEntity> auto decoratee,
58 ) const
59 {
60 using DependenciesPack = meta::args_pack_t<decltype(Decorator_::create)>;
61
62 if constexpr (
64 !std::same_as<
65 std::decay_t<meta::pack_head_t<DependenciesPack>>,
66 std::decay_t<Decoratee>
67 >
68 )
69 {
70 return std::expected<meta::RuntimeRef<RelatedEntity>, Error> {
71 std::unexpected { Error::INVALID_DECORATOR_CONFIG }
72 };
73 }
74 else
75 {
76 using NonDecoratedDependenciesPack
78
79 auto decorated_dependencies = std::tuple { decoratee };
80
81 auto maybe_non_decorated_dependencies_tuple = [this, &context]<
82 typename... NonDecoratedDependencies
83 >(
84 meta::Pack<NonDecoratedDependencies...>
85 ) {
86 return [this, &context]<std::size_t... Idx>(std::index_sequence<Idx...>) {
87 return std::tuple {
88 [this, &context] {
89 auto it = std::ranges::find_if(
90 this->dependency_tags_,
91 [](const auto& tag_pair){
92 return tag_pair.first == Idx + 1;
93 }
94 );
95
96 if (it == std::ranges::end(this->dependency_tags_)) [[unlikely]]
97 {
98 return context
99 .container
100 .template resolve<std::decay_t<NonDecoratedDependencies>>();
101 }
102
103 return context
104 .container
105 .template resolve<std::decay_t<NonDecoratedDependencies>>(std::tuple { TagInput {
106 it->second
107 }});
108 }()...
109 };
110 }(std::index_sequence_for<NonDecoratedDependencies...>{});
111 }(NonDecoratedDependenciesPack{});
112
113 auto maybe_non_decorated_dependencies = std::apply(
114 [](auto&&... maybe_dependencies) {
115 using DependenciesTuple = std::tuple<
116 typename std::remove_reference_t<decltype(maybe_dependencies)>::value_type...
117 >;
118
119 if ((maybe_dependencies.has_value() && ...))
120 {
121 return std::expected<DependenciesTuple, Error> {
122 std::tuple { std::move(maybe_dependencies.value())... }
123 };
124 }
125 else
126 {
127 return std::expected<DependenciesTuple, Error> {
128 std::unexpected { Error::INVALID_DECORATOR_DEPENDENCIES }
129 };
130 }
131 },
132 std::move(maybe_non_decorated_dependencies_tuple)
133 );
134
135 if (!maybe_non_decorated_dependencies.has_value()) [[unlikely]]
136 {
137 return std::expected<meta::RuntimeRef<RelatedEntity>, Error> {
138 std::unexpected { maybe_non_decorated_dependencies.error() }
139 };
140 }
141
142 auto non_decorated_dependencies
143 = std::move(maybe_non_decorated_dependencies).value();
144
145 auto dependencies = std::tuple_cat(
146 std::move(decorated_dependencies),
147 std::move(non_decorated_dependencies)
148 );
149
150 return inner_config_
151 .do_resolve(meta::Pack<Decorator_>{}, dependencies, context, std::tuple{})
152 .transform([](auto decorator_ref) {
153 return meta::RuntimeRef (static_cast<RelatedEntity&>(decorator_ref));
154 });
155 }
156 }
157
158private:
159 Transient<Decorator_> inner_config_;
160 std::array<DependencyTagPair, SIZE> dependency_tags_;
161};
162
163}
164
165#endif // !DECORATOR_HPP_
Error codes and diagnostics for dependency injection operations.
Compile-time type pack utilities and metaprogramming foundations.
Definition Transient.hpp:25
Definition RuntimeRef.hpp:13
Definition Reference.hpp:10
Definition WrappedWIth.hpp:30
Definition Decorator.hpp:19
ConfigType
Categorization of configuration strategies in the DI container.
Definition ConfigType.hpp:24
@ CHAINABLE
Chainable configs form a pipeline of transformations applied after creation. Examples: proxies,...
Definition ConfigType.hpp:35
@ SIZE
Sentinel value for bounds checking and iteration.
Definition ConfigType.hpp:38
Error
Enumeration of possible errors during dependency injection resolution.
Definition Error.hpp:26
@ INVALID_DECORATOR_DEPENDENCIES
Definition Error.hpp:51
@ INVALID_DECORATOR_CONFIG
Definition Error.hpp:49
typename function_traits< Function >::Params args_pack_t
Definition FunctionTraits.hpp:34
constexpr bool pack_is_empty_v
Definition Pack.hpp:78
typename PackPopHead< Pack_ >::type pack_pop_head_t
Definition PopHead.hpp:24
Definition DecoratableConfig.hpp:22
Decoratee RelatedEntity
Definition Decorator.hpp:32
static constexpr ConfigType CONFIG_TYPE
Definition Decorator.hpp:36
meta::Pack< meta::Pack< Decoratee > > RelatedKeysPack
Definition Decorator.hpp:33
Resolution< RelatedEntity, Error > auto pipe(meta::Reference< RelatedEntity > auto decoratee, meta::wrapped_with< ResolutionContext > auto &context) const
Definition Decorator.hpp:55
Decorator(meta::Unit< Decorator_ >, meta::Unit< Decoratee >, std::array< DependencyTagPair, SIZE > dependency_tags={})
Definition Decorator.hpp:44
Decorator(std::array< DependencyTagPair, SIZE > dependency_tags={})
Definition Decorator.hpp:39
Definition TagInput.hpp:12
A compile-time heterogeneous type list.
Definition Pack.hpp:70
A zero-cost wrapper for forwarding compile-time type information.
Definition Pack.hpp:45