OGS
Apply.h
Go to the documentation of this file.
1
10#pragma once
11
12#include "Get.h"
13
15{
16namespace detail
17{
18template <typename Function>
21 : GetFunctionArgumentTypes<decltype(&Function::operator())>
23{
24};
25
26// member function
27template <typename Result, typename Class, typename... Args>
28struct GetFunctionArgumentTypes<Result (Class::*)(Args...)>
29{
30 using type = boost::mp11::mp_list<Args...>;
31};
32
33// const member function
34template <typename Result, typename Class, typename... Args>
35struct GetFunctionArgumentTypes<Result (Class::*)(Args...) const>
36{
37 using type = boost::mp11::mp_list<Args...>;
38};
39
40// standalone function
41template <typename Result, typename... Args>
42struct GetFunctionArgumentTypes<Result (*)(Args...)>
43{
44 using type = boost::mp11::mp_list<Args...>;
45};
46
47// plain, i.e., without cvref
48template <typename Function>
50 std::type_identity<boost::mp11::mp_transform<
51 std::remove_cvref_t,
53
54template <typename Function>
57 : GetFunctionReturnType<decltype(&Function::operator())>
59{
60};
61
62// member function
63template <typename Result, typename Class, typename... Args>
64struct GetFunctionReturnType<Result (Class::*)(Args...)>
65{
66 using type = Result;
67};
68
69// const member function
70template <typename Result, typename Class, typename... Args>
71struct GetFunctionReturnType<Result (Class::*)(Args...) const>
72{
73 using type = Result;
74};
75
76// standalone function
77template <typename Result, typename... Args>
78struct GetFunctionReturnType<Result (*)(Args...)>
79{
80 using type = Result;
81};
82
83// Invokes the passed function object with arguments taken ("unpacked") from the
84// passed tuples ts. The arguments are picked/passed according to their data
85// type.
86//
87// overload for function objects
88template <typename Object,
89 typename... Tuples,
90 typename... MemberFunctionArgumentTypesPlain>
91auto unpackAndInvoke(boost::mp11::mp_list<MemberFunctionArgumentTypesPlain...>,
92 Object&& o,
93 Tuples&... ts) ->
94 // std::decay_t "decays" lambdas
95 typename GetFunctionReturnType<
96 decltype(&std::decay_t<Object>::operator())>::type
97{
98 return o(
99 ProcessLib::Graph::get<MemberFunctionArgumentTypesPlain>(ts...)...);
100}
101
102// member function
103template <typename Result,
104 typename Object,
105 typename... Args,
106 typename... Tuples,
107 typename... MemberFunctionArgumentTypesPlain>
109 boost::mp11::mp_list<MemberFunctionArgumentTypesPlain...>,
110 Result (Object::*m)(Args...),
111 Object& o,
112 Tuples&... ts)
113{
114 return (o.*m)(
115 ProcessLib::Graph::get<MemberFunctionArgumentTypesPlain>(ts...)...);
116}
117
118// member function & temporary object
119template <typename Result,
120 typename Object,
121 typename... Args,
122 typename... Tuples,
123 typename... MemberFunctionArgumentTypesPlain>
125 boost::mp11::mp_list<MemberFunctionArgumentTypesPlain...>,
126 Result (Object::*m)(Args...),
127 Object&& o,
128 Tuples&... ts)
129{
130 return (o.*m)(
131 ProcessLib::Graph::get<MemberFunctionArgumentTypesPlain>(ts...)...);
132}
133
134// const member function
135template <typename Result,
136 typename Object,
137 typename... Args,
138 typename... Tuples,
139 typename... MemberFunctionArgumentTypesPlain>
141 boost::mp11::mp_list<MemberFunctionArgumentTypesPlain...>,
142 Result (Object::*m)(Args...) const,
143 Object const& o,
144 Tuples&... ts)
145{
146 return (o.*m)(
147 ProcessLib::Graph::get<MemberFunctionArgumentTypesPlain>(ts...)...);
148}
149
150// standalone function
151template <typename Result,
152 typename... Args,
153 typename... Tuples,
154 typename... FunctionArgumentTypesPlain>
155Result unpackAndInvoke(boost::mp11::mp_list<FunctionArgumentTypesPlain...>,
156 Result (*fct)(Args...),
157 Tuples&... ts)
158{
159 return fct(ProcessLib::Graph::get<FunctionArgumentTypesPlain>(ts...)...);
160}
161
162template <typename Function, typename... PassedArgsTuples>
165 : GetFlattenedTupleOfPassedArgs<decltype(&Function::operator()),
166 Function,
167 PassedArgsTuples...>
169{
170};
171
172// member function
173template <typename Result,
174 typename Class,
175 typename... DeclaredArgs,
176 typename ClassAgain,
177 typename... PassedArgsTuples>
178struct GetFlattenedTupleOfPassedArgs<Result (Class::*)(DeclaredArgs...),
179 // first "argument" is the object to which
180 // the member function belongs
181 ClassAgain,
182 PassedArgsTuples...>
183{
185 std::remove_cvref_t<PassedArgsTuples>...>::type;
186};
187
188// const member function
189template <typename Result,
190 typename Class,
191 typename... DeclaredArgs,
192 typename... ClassAndPassedArgsTuples>
193struct GetFlattenedTupleOfPassedArgs<Result (Class::*)(DeclaredArgs...) const,
194 ClassAndPassedArgsTuples...>
195 // redirect to non-const member function implementation
196 : GetFlattenedTupleOfPassedArgs<Result (Class::*)(DeclaredArgs...),
197 ClassAndPassedArgsTuples...>
198{
199};
200
201// standalone function
202template <typename Result, typename... DeclaredArgs, typename... Tuples>
203struct GetFlattenedTupleOfPassedArgs<Result (*)(DeclaredArgs...), Tuples...>
204{
206 std::remove_cvref_t<Tuples>...>::type;
207};
208
219template <typename Function, typename... Args>
220auto applyImpl(Function&& f, Args&&... args) ->
222{
223 using namespace boost::mp11;
224
225 using FunctionPlain = std::decay_t<Function>;
226 using FlattenedTuple =
227 typename GetFlattenedTupleOfPassedArgs<FunctionPlain, Args...>::type;
228 using FlattenedTupleOfPlainTypes =
229 mp_transform<std::remove_cvref_t, FlattenedTuple>;
230
231 static_assert(
232 mp_is_set_v<FlattenedTupleOfPlainTypes>,
233 "The types of all elements of all passed tuples must be unique.");
234
235 using FunctionArgumentTypesPlain =
237
238 static_assert(
239 mp_is_set_v<FunctionArgumentTypesPlain>,
240 "The argument types of the function to be called must be unique.");
241
242 return unpackAndInvoke(FunctionArgumentTypesPlain{},
243 std::forward<Function>(f),
244 std::forward<Args>(args)...);
245}
246} // namespace detail
247
256template <typename Function, typename... Tuples>
257auto apply(Function& f, Tuples&... ts) ->
259{
260 static_assert(boost::mp11::mp_similar<std::tuple<>,
261 std::remove_cv_t<Tuples>...>::value,
262 "In the argument ts... there must be only std::tuple's.");
263
264 return detail::applyImpl(f, ts...);
265}
266
273template <typename Function, typename... Tuples>
274auto eval(Function& f, Tuples&... ts) ->
275 typename detail::GetFunctionReturnType<decltype(&Function::eval)>::type
276{
277 static_assert(boost::mp11::mp_similar<std::tuple<>,
278 std::remove_cv_t<Tuples>...>::value,
279 "In the argument ts... there must be only std::tuple's.");
280
281 return detail::applyImpl(&Function::eval, f, ts...);
282}
283
293template <typename Functions, typename... Tuples>
294void evalAllInOrder(Functions& fs, Tuples&... ts)
295{
296 boost::mp11::tuple_for_each(fs, [&ts...](auto& f) { eval(f, ts...); });
297}
298} // namespace ProcessLib::Graph
auto unpackAndInvoke(boost::mp11::mp_list< MemberFunctionArgumentTypesPlain... >, Object &&o, Tuples &... ts) -> typename GetFunctionReturnType< decltype(&std::decay_t< Object >::operator())>::type
Definition Apply.h:91
auto applyImpl(Function &&f, Args &&... args) -> typename detail::GetFunctionReturnType< std::decay_t< Function > >::type
Definition Apply.h:220
std::type_identity< boost::mp11::mp_transform< std::remove_cvref_t, typename GetFunctionArgumentTypes< Function >::type > > GetFunctionArgumentTypesPlain
Definition Apply.h:49
auto apply(Function &f, Tuples &... ts) -> typename detail::GetFunctionReturnType< std::decay_t< Function > >::type
Definition Apply.h:257
void evalAllInOrder(Functions &fs, Tuples &... ts)
Definition Apply.h:294
auto eval(Function &f, Tuples &... ts) -> typename detail::GetFunctionReturnType< decltype(&Function::eval)>::type
Definition Apply.h:274
typename detail::GetFlattenedTupleTypes< std::remove_cvref_t< PassedArgsTuples >... >::type type
Definition Apply.h:184
typename detail::GetFlattenedTupleTypes< std::remove_cvref_t< Tuples >... >::type type
Definition Apply.h:205