capydi
Loading...
Searching...
No Matches
ChainableConfigDispatcher.hpp
Go to the documentation of this file.
1#ifndef CHAINABLE_CONFIG_DISPATCHER_HPP_
2#define CHAINABLE_CONFIG_DISPATCHER_HPP_
3
6#include "capydi/Error.hpp"
7
13#include <boost/mp11.hpp>
14#include <concepts>
15#include <expected>
16#include <variant>
17#include <tuple>
18
19namespace capy::di
20{
21
22template<ChainableConfig... Configs>
24{
25public:
26 constexpr explicit ChainableConfigDispatcher(
27 Configs&&... configs
28 )
29 : configs_tuple_ { std::move(configs)... }
30 , configs_dispatch_map_ {
31 populate_configs_map(this->configs_tuple_)
32 }
33 {}
34
35public:
36 template<typename RelatedKey, typename RelatedEntity>
37 [[nodiscard]] constexpr Resolution<
38 RelatedEntity,
39 Error
40 > auto
44 ) const
45 {
46 auto maybe_configs_array = this->configs_dispatch_map_
47 .static_find(meta::Unit<RelatedKey>{});
48
49 if constexpr (!maybe_configs_array.has_value()) [[unlikely]]
50 {
51 return std::expected<meta::RuntimeRef<RelatedEntity>, Error> {
52 entity
53 };
54 }
55 else
56 {
57 auto configs_array_reference = maybe_configs_array.value();
58 typename decltype(configs_array_reference)::ReferenceType configs_array = configs_array_reference;
59 return this->perform_piping<RelatedEntity>(configs_array, context, entity, 0);
60 }
61 }
62
63 template<typename RelatedEntity>
64 [[nodiscard]] constexpr Resolution<
65 RelatedEntity,
66 Error
67 > auto
69 const auto& configs_array,
72 std::size_t current_index
73 ) const
74 {
75 if (current_index >= configs_array.size())
76 {
77 return std::expected<meta::RuntimeRef<RelatedEntity>, Error> {
78 entity
79 };
80 }
81
82 return
83 std::visit(
84 [&entity, &context](const auto& config_reference) {
85 typename std::decay_t<decltype(config_reference)>::ReferenceType config = config_reference;
86 return config.pipe(entity, context);
87 },
88 configs_array[current_index]
89 )
90 .and_then([this, &configs_array, current_index, &context](
91 meta::Reference<RelatedEntity> auto processed_entity
92 ) {
94 configs_array,
95 context,
96 processed_entity,
97 current_index + 1
98 );
99 });
100 }
101
102private:
103 template<typename UniqueType, typename... NonUniqueConfigs>
104 static constexpr auto collect(NonUniqueConfigs&... args)
105 {
106 using namespace boost::mp11;
107
108 auto configs_tuple = std::tuple_cat(
109 ([&]() {
110 if constexpr (meta::pack_contains_t<
112 UniqueType
113 >) {
114 return std::tuple<meta::RuntimeRef<NonUniqueConfigs>> {
116 };
117 }
118 else {
119 return std::tuple<>{};
120 }
121 }())...
122 );
123
124 return std::apply(
125 []<typename... T>(T&&... configs) {
126 using UniqueTs = mp_unique<mp_list<std::decay_t<T>...>>;
127 using VariantType = meta::rebind_t<
128 UniqueTs,
129 mp_list,
130 std::variant
131 >;
132 return std::array<VariantType, sizeof...(configs)> {
133 VariantType { std::forward<T>(configs) }...
134 };
135 },
136 std::move(configs_tuple)
137 );
138 }
139
140 template<meta::wrapped_with<std::tuple> ConfigsTuple>
141 static constexpr auto populate_configs_map(
142 ConfigsTuple& configs_tuple
143 ) {
144 using namespace boost::mp11;
145
146 using KeysList = mp_flatten<mp_list<
149 meta::Pack,
150 mp_list
151 >...
152 >>;
153
154 using UniqueKeysList = mp_unique<KeysList>;
155
156 return [&]<typename... UniqueKeys>(mp_list<UniqueKeys...>&& list) {
157 return meta::MetaMap {
158 meta::KVPair {
159 meta::Unit<UniqueKeys>{},
160 std::apply(
161 [](auto&... args) {
162 return collect<UniqueKeys>(args...);
163 },
164 configs_tuple
165 )
166 }...
167 };
168 }(UniqueKeysList{});
169 }
170
171private:
172 using ConfigsTupleType = std::tuple<Configs...>;
173 using MapType = decltype(populate_configs_map(std::declval<ConfigsTupleType&>()));
174
175 ConfigsTupleType configs_tuple_;
176 MapType configs_dispatch_map_;
177};
178
179}
180
181#endif // !CHAINABLE_CONFIG_DISPATCHER_HPP_
Concept and utilities for chainable (decorator/pipeline) configurations.
Error codes and diagnostics for dependency injection operations.
Compile-time type pack utilities and metaprogramming foundations.
Resolution concept and result type for dependency injection queries.
constexpr ChainableConfigDispatcher(Configs &&... configs)
Definition ChainableConfigDispatcher.hpp:26
constexpr Resolution< RelatedEntity, Error > auto apply_configs_chain(meta::Reference< RelatedEntity > auto entity, meta::wrapped_with< ResolutionContext > auto &context) const
Definition ChainableConfigDispatcher.hpp:41
constexpr Resolution< RelatedEntity, Error > auto perform_piping(const auto &configs_array, meta::wrapped_with< ResolutionContext > auto &context, meta::Reference< RelatedEntity > auto entity, std::size_t current_index) const
Definition ChainableConfigDispatcher.hpp:68
Definition RuntimeRef.hpp:13
Concept for configuration objects that transform/decorate dependencies.
Definition ChainableConfig.hpp:58
Definition Resolution.hpp:30
Definition Reference.hpp:10
Definition WrappedWIth.hpp:30
Definition Decorator.hpp:19
typename Config::RelatedKeysPack get_related_keys_pack_t
Helper alias to extract the key type from a ChainableConfig.
Definition ChainableConfig.hpp:96
Error
Enumeration of possible errors during dependency injection resolution.
Definition Error.hpp:26
typename typed__::Rebind< Type, SrcContainer, DstContainer >::type rebind_t
Definition Rebind.hpp:121
constexpr bool pack_contains_t
Definition Contains.hpp:13
A zero-cost wrapper for forwarding compile-time type information.
Definition Pack.hpp:45