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>
19struct GetFunctionArgumentTypesPlain // plain, i.e., without cvref
21 : GetFunctionArgumentTypesPlain<decltype(&Function::operator())>
23{
24};
25
26// member function
27template <typename Result, typename Class, typename... Args>
28struct GetFunctionArgumentTypesPlain<Result (Class::*)(Args...)>
29{
30 using type = boost::mp11::mp_list<std::remove_cvref_t<Args>...>;
31};
32
33// const member function
34template <typename Result, typename Class, typename... Args>
35struct GetFunctionArgumentTypesPlain<Result (Class::*)(Args...) const>
36{
37 using type = boost::mp11::mp_list<std::remove_cvref_t<Args>...>;
38};
39
40// standalone function
41template <typename Result, typename... Args>
42struct GetFunctionArgumentTypesPlain<Result (*)(Args...)>
43{
44 using type = boost::mp11::mp_list<std::remove_cvref_t<Args>...>;
45};
46
47template <typename Function>
50 : GetFunctionReturnType<decltype(&Function::operator())>
52{
53};
54
55// member function
56template <typename Result, typename Class, typename... Args>
57struct GetFunctionReturnType<Result (Class::*)(Args...)>
58{
59 using type = Result;
60};
61
62// const member function
63template <typename Result, typename Class, typename... Args>
64struct GetFunctionReturnType<Result (Class::*)(Args...) const>
65{
66 using type = Result;
67};
68
69// standalone function
70template <typename Result, typename... Args>
71struct GetFunctionReturnType<Result (*)(Args...)>
72{
73 using type = Result;
74};
75
76// Invokes the passed function object with arguments taken ("unpacked") from the
77// passed tuples ts. The arguments are picked/passed according to their data
78// type.
79//
80// overload for function objects
81template <typename Object,
82 typename... Tuples,
83 typename... MemberFunctionArgumentTypesPlain>
84auto unpackAndInvoke(boost::mp11::mp_list<MemberFunctionArgumentTypesPlain...>,
85 Object&& o,
86 Tuples&... ts) ->
87 // std::decay_t "decays" lambdas
88 typename GetFunctionReturnType<
89 decltype(&std::decay_t<Object>::operator())>::type
90{
91 return o(
92 ProcessLib::Graph::get<MemberFunctionArgumentTypesPlain>(ts...)...);
93}
94
95// member function
96template <typename Result,
97 typename Object,
98 typename... Args,
99 typename... Tuples,
100 typename... MemberFunctionArgumentTypesPlain>
102 boost::mp11::mp_list<MemberFunctionArgumentTypesPlain...>,
103 Result (Object::*m)(Args...),
104 Object& o,
105 Tuples&... ts)
106{
107 return (o.*m)(
108 ProcessLib::Graph::get<MemberFunctionArgumentTypesPlain>(ts...)...);
109}
110
111// member function & temporary object
112template <typename Result,
113 typename Object,
114 typename... Args,
115 typename... Tuples,
116 typename... MemberFunctionArgumentTypesPlain>
118 boost::mp11::mp_list<MemberFunctionArgumentTypesPlain...>,
119 Result (Object::*m)(Args...),
120 Object&& o,
121 Tuples&... ts)
122{
123 return (o.*m)(
124 ProcessLib::Graph::get<MemberFunctionArgumentTypesPlain>(ts...)...);
125}
126
127// const member function
128template <typename Result,
129 typename Object,
130 typename... Args,
131 typename... Tuples,
132 typename... MemberFunctionArgumentTypesPlain>
134 boost::mp11::mp_list<MemberFunctionArgumentTypesPlain...>,
135 Result (Object::*m)(Args...) const,
136 Object const& o,
137 Tuples&... ts)
138{
139 return (o.*m)(
140 ProcessLib::Graph::get<MemberFunctionArgumentTypesPlain>(ts...)...);
141}
142
143// standalone function
144template <typename Result,
145 typename... Args,
146 typename... Tuples,
147 typename... FunctionArgumentTypesPlain>
148Result unpackAndInvoke(boost::mp11::mp_list<FunctionArgumentTypesPlain...>,
149 Result (*fct)(Args...),
150 Tuples&... ts)
151{
152 return fct(ProcessLib::Graph::get<FunctionArgumentTypesPlain>(ts...)...);
153}
154
155template <typename Function, typename... PassedArgsTuples>
158 : GetFlattenedTupleOfPassedArgs<decltype(&Function::operator()),
159 Function,
160 PassedArgsTuples...>
162{
163};
164
165// member function
166template <typename Result,
167 typename Class,
168 typename... DeclaredArgs,
169 typename ClassAgain,
170 typename... PassedArgsTuples>
171struct GetFlattenedTupleOfPassedArgs<Result (Class::*)(DeclaredArgs...),
172 // first "argument" is the object to which
173 // the member function belongs
174 ClassAgain,
175 PassedArgsTuples...>
176{
178 std::remove_cvref_t<PassedArgsTuples>...>::type;
179};
180
181// const member function
182template <typename Result,
183 typename Class,
184 typename... DeclaredArgs,
185 typename... ClassAndPassedArgsTuples>
186struct GetFlattenedTupleOfPassedArgs<Result (Class::*)(DeclaredArgs...) const,
187 ClassAndPassedArgsTuples...>
188 // redirect to non-const member function implementation
189 : GetFlattenedTupleOfPassedArgs<Result (Class::*)(DeclaredArgs...),
190 ClassAndPassedArgsTuples...>
191{
192};
193
194// standalone function
195template <typename Result, typename... DeclaredArgs, typename... Tuples>
196struct GetFlattenedTupleOfPassedArgs<Result (*)(DeclaredArgs...), Tuples...>
197{
199 std::remove_cvref_t<Tuples>...>::type;
200};
201
212template <typename Function, typename... Args>
213auto applyImpl(Function&& f, Args&&... args) ->
215{
216 using namespace boost::mp11;
217
218 using FunctionPlain = std::decay_t<Function>;
219 using FlattenedTuple =
220 typename GetFlattenedTupleOfPassedArgs<FunctionPlain, Args...>::type;
221 using FlattenedTupleOfPlainTypes =
222 mp_transform<std::remove_cvref_t, FlattenedTuple>;
223
224 static_assert(
225 boost::mp11::mp_is_set<FlattenedTupleOfPlainTypes>::value,
226 "The types of all elements of all passed tuples must be unique.");
227
228 using FunctionArgumentTypesPlain =
230
231 static_assert(
232 boost::mp11::mp_is_set<FunctionArgumentTypesPlain>::value,
233 "The argument types of the function to be called must be unique.");
234
235 return unpackAndInvoke(FunctionArgumentTypesPlain{},
236 std::forward<Function>(f),
237 std::forward<Args>(args)...);
238}
239} // namespace detail
240
249template <typename Function, typename... Tuples>
250auto apply(Function& f, Tuples&... ts) ->
252{
253 static_assert(boost::mp11::mp_similar<std::tuple<>,
254 std::remove_cv_t<Tuples>...>::value,
255 "In the argument ts... there must be only std::tuple's.");
256
257 return detail::applyImpl(f, ts...);
258}
259
266template <typename Function, typename... Tuples>
267auto eval(Function& f, Tuples&... ts) ->
268 typename detail::GetFunctionReturnType<decltype(&Function::eval)>::type
269{
270 static_assert(boost::mp11::mp_similar<std::tuple<>,
271 std::remove_cv_t<Tuples>...>::value,
272 "In the argument ts... there must be only std::tuple's.");
273
274 return detail::applyImpl(&Function::eval, f, ts...);
275}
276} // 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:84
auto applyImpl(Function &&f, Args &&... args) -> typename detail::GetFunctionReturnType< std::decay_t< Function > >::type
Definition Apply.h:213
auto apply(Function &f, Tuples &... ts) -> typename detail::GetFunctionReturnType< std::decay_t< Function > >::type
Definition Apply.h:250
auto eval(Function &f, Tuples &... ts) -> typename detail::GetFunctionReturnType< decltype(&Function::eval)>::type
Definition Apply.h:267
typename detail::GetFlattenedTupleTypes< std::remove_cvref_t< PassedArgsTuples >... >::type type
Definition Apply.h:177
typename detail::GetFlattenedTupleTypes< std::remove_cvref_t< Tuples >... >::type type
Definition Apply.h:198
boost::mp11::mp_list< std::remove_cvref_t< Args >... > type
Definition Apply.h:30
boost::mp11::mp_list< std::remove_cvref_t< Args >... > type
Definition Apply.h:44