capydi
Loading...
Searching...
No Matches
DiAction.hpp
Go to the documentation of this file.
1#ifndef CAPYDI_DI_ACTION_HPP_
2#define CAPYDI_DI_ACTION_HPP_
3
6
9#include <expected>
10#include <array>
11#include <ranges>
12
13namespace capy::di
14{
15
16template<
17 typename ActionFunctor,
18 std::size_t DEPENDENCY_TAGS_COUNT
19>
21{
22public:
24 = meta::return_value_t<decltype(&ActionFunctor::operator())>;
26 using ArgsPack
27 = meta::args_pack_t<decltype(&ActionFunctor::operator())>;
29public:
30 ActionFunctor action;
31
32 std::array<
34 DEPENDENCY_TAGS_COUNT
36};
37
38template<typename T>
39concept MaybeLike = requires (T maybe) {
40 { maybe.has_value() } -> std::convertible_to<bool>;
41 { maybe.value() };
42 typename T::value_type;
43};
44
45template<typename DiAction_>
46using di_action_return_t = typename DiAction_::ReturnType;
47
48template<typename DiAction_>
49using di_action_args_pack_t = typename DiAction_::ArgsPack;
50
56
57template<typename DiAction_>
59 DiAction_ const& di_action,
60 auto& context
61) {
62 using ActionReturnType = di_action_return_t<DiAction_>;
63 using ActionDependenciesPack = di_action_args_pack_t<DiAction_>;
64
65 using ResultType = meta::unit_inner_type_t<decltype([] {
66 if constexpr (MaybeLike<ActionReturnType>)
67 {
68 return meta::Unit<
69 std::expected<
70 typename ActionReturnType::value_type,
72 >
73 >{};
74 }
75 else
76 {
77 return meta::Unit<
78 std::expected<
79 ActionReturnType,
81 >
82 >{};
83 }
84 }())>;
85
86 auto maybe_args = [di_action, &context]<typename... ActionDependencies>(
87 meta::Pack<ActionDependencies...>
88 ) {
89 auto args_preparations = [di_action, &context]<std::size_t... Idx>(std::index_sequence<Idx...>) {
90 return std::tuple {
92 context,
93 [di_action]() -> std::optional<tag_t> {
94 auto it = std::ranges::find_if(
95 di_action.dependency_tags,
96 [](const auto& tag_pair){
97 return tag_pair.first == Idx;
98 }
99 );
100
101 if (it == std::ranges::end(di_action.dependency_tags)) [[unlikely]]
102 {
103 return std::nullopt;
104 }
105
106 return it->second;
107 }()
108 )...
109 };
110 }(std::index_sequence_for<ActionDependencies...>{});
111
112 return std::apply([](auto&&... preparations) {
113 using TupleResult = std::tuple<ActionDependencies...>;
114
115 if ((preparations.has_value() && ...))
116 {
117 return std::expected<TupleResult, Error> {
118 std::tuple { std::move(preparations.value())... }
119 };
120 }
121
122 return std::expected<TupleResult, Error> {
124 };
125 }, std::move(args_preparations));
126 }(ActionDependenciesPack{});
127
128 if (!maybe_args.has_value()) [[unlikely]]
129 {
130 return ResultType { std::unexpected {
132 }};
133 }
134
135 auto& args = maybe_args.value();
136
137 if constexpr (MaybeLike<ActionReturnType>)
138 {
139 ActionReturnType action_result
140 = std::apply(di_action.action, args);
141
142 if (!action_result.has_value()) [[unlikely]]
143 {
144 return ResultType { std::unexpected {
146 }};
147 }
148
149 return ResultType { action_result.value() };
150 }
151 else if constexpr (std::is_void_v<ActionReturnType>)
152 {
153 std::apply(di_action.action, args);
154 return ResultType {};
155 }
156 else
157 {
158 ActionReturnType action_result
159 = std::apply(di_action.action, args);
160
161 return ResultType { action_result };
162 }
163}
164
165
166}
167
168#endif // !CAPYDI_DI_ACTION_HPP_
Definition DiAction.hpp:39
Definition Decorator.hpp:19
typename DiAction_::ReturnType di_action_return_t
Definition DiAction.hpp:46
typename DiAction_::ArgsPack di_action_args_pack_t
Definition DiAction.hpp:49
auto execute_di_action(DiAction_ const &di_action, auto &context)
Definition DiAction.hpp:58
std::pair< std::size_t, tag_t > DependencyTagPair
Definition DependencyTags.hpp:15
@ OBSERVER_COULD_NOT_RESOLVE_TYPE
Definition Error.hpp:45
DiActionError
Definition DiAction.hpp:52
@ DI_ACTION_UNABLE_TO_RESOLVE_ARGS
Definition DiAction.hpp:53
@ DI_ACTION_EXECUTION_ERROR
Definition DiAction.hpp:54
typename function_traits< Function >::Params args_pack_t
Definition FunctionTraits.hpp:34
typename Unit_::InnerType unit_inner_type_t
Definition Pack.hpp:50
typename function_traits< Function >::ReturnValue return_value_t
Definition FunctionTraits.hpp:31
Definition ActionArgMatcher.hpp:14
Definition DiAction.hpp:21
ActionFunctor action
Definition DiAction.hpp:28
meta::args_pack_t< decltype(&ActionFunctor::operator())> ArgsPack
Definition DiAction.hpp:25
std::array< DependencyTagPair, DEPENDENCY_TAGS_COUNT > dependency_tags
Definition DiAction.hpp:33
meta::return_value_t< decltype(&ActionFunctor::operator())> ReturnType
Definition DiAction.hpp:23
A compile-time heterogeneous type list.
Definition Pack.hpp:70
A zero-cost wrapper for forwarding compile-time type information.
Definition Pack.hpp:45