1 /*
2     Copyright (c) 2005-2021 Intel Corporation
3 
4     Licensed under the Apache License, Version 2.0 (the "License");
5     you may not use this file except in compliance with the License.
6     You may obtain a copy of the License at
7 
8         http://www.apache.org/licenses/LICENSE-2.0
9 
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15 */
16 
17 #ifndef __TBB_flow_graph_nodes_deduction_H
18 #define __TBB_flow_graph_nodes_deduction_H
19 
20 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
21 
22 namespace tbb {
23 namespace detail {
24 namespace d1 {
25 
26 template <typename Input, typename Output>
27 struct declare_body_types {
28     using input_type = Input;
29     using output_type = Output;
30 };
31 
32 struct NoInputBody {};
33 
34 template <typename Output>
35 struct declare_body_types<NoInputBody, Output> {
36     using output_type = Output;
37 };
38 
39 template <typename T> struct body_types;
40 
41 template <typename T, typename Input, typename Output>
42 struct body_types<Output (T::*)(const Input&) const> : declare_body_types<Input, Output> {};
43 
44 template <typename T, typename Input, typename Output>
45 struct body_types<Output (T::*)(const Input&)> : declare_body_types<Input, Output> {};
46 
47 template <typename T, typename Input, typename Output>
48 struct body_types<Output (T::*)(Input&) const> : declare_body_types<Input, Output> {};
49 
50 template <typename T, typename Input, typename Output>
51 struct body_types<Output (T::*)(Input&)> : declare_body_types<Input, Output> {};
52 
53 template <typename T, typename Output>
54 struct body_types<Output (T::*)(flow_control&) const> : declare_body_types<NoInputBody, Output> {};
55 
56 template <typename T, typename Output>
57 struct body_types<Output (T::*)(flow_control&)> : declare_body_types<NoInputBody, Output> {};
58 
59 template <typename Input, typename Output>
60 struct body_types<Output (*)(Input&)> : declare_body_types<Input, Output> {};
61 
62 template <typename Input, typename Output>
63 struct body_types<Output (*)(const Input&)> : declare_body_types<Input, Output> {};
64 
65 template <typename Output>
66 struct body_types<Output (*)(flow_control&)> : declare_body_types<NoInputBody, Output> {};
67 
68 template <typename Body>
69 using input_t = typename body_types<Body>::input_type;
70 
71 template <typename Body>
72 using output_t = typename body_types<Body>::output_type;
73 
74 template <typename T, typename Input, typename Output>
75 auto decide_on_operator_overload(Output (T::*name)(const Input&) const)->decltype(name);
76 
77 template <typename T, typename Input, typename Output>
78 auto decide_on_operator_overload(Output (T::*name)(const Input&))->decltype(name);
79 
80 template <typename T, typename Input, typename Output>
81 auto decide_on_operator_overload(Output (T::*name)(Input&) const)->decltype(name);
82 
83 template <typename T, typename Input, typename Output>
84 auto decide_on_operator_overload(Output (T::*name)(Input&))->decltype(name);
85 
86 template <typename Input, typename Output>
87 auto decide_on_operator_overload(Output (*name)(const Input&))->decltype(name);
88 
89 template <typename Input, typename Output>
90 auto decide_on_operator_overload(Output (*name)(Input&))->decltype(name);
91 
92 template <typename Body>
93 decltype(decide_on_operator_overload(&Body::operator())) decide_on_callable_type(int);
94 
95 template <typename Body>
96 decltype(decide_on_operator_overload(std::declval<Body>())) decide_on_callable_type(...);
97 
98 // Deduction guides for Flow Graph nodes
99 
100 template <typename GraphOrSet, typename Body>
101 input_node(GraphOrSet&&, Body)
102 ->input_node<output_t<decltype(decide_on_callable_type<Body>(0))>>;
103 
104 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
105 
106 template <typename NodeSet>
107 struct decide_on_set;
108 
109 template <typename Node, typename... Nodes>
110 struct decide_on_set<node_set<order::following, Node, Nodes...>> {
111     using type = typename Node::output_type;
112 };
113 
114 template <typename Node, typename... Nodes>
115 struct decide_on_set<node_set<order::preceding, Node, Nodes...>> {
116     using type = typename Node::input_type;
117 };
118 
119 template <typename NodeSet>
120 using decide_on_set_t = typename decide_on_set<std::decay_t<NodeSet>>::type;
121 
122 template <typename NodeSet>
123 broadcast_node(const NodeSet&)
124 ->broadcast_node<decide_on_set_t<NodeSet>>;
125 
126 template <typename NodeSet>
127 buffer_node(const NodeSet&)
128 ->buffer_node<decide_on_set_t<NodeSet>>;
129 
130 template <typename NodeSet>
131 queue_node(const NodeSet&)
132 ->queue_node<decide_on_set_t<NodeSet>>;
133 #endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
134 
135 template <typename GraphOrProxy, typename Sequencer>
136 sequencer_node(GraphOrProxy&&, Sequencer)
137 ->sequencer_node<input_t<decltype(decide_on_callable_type<Sequencer>(0))>>;
138 
139 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
140 template <typename NodeSet, typename Compare>
141 priority_queue_node(const NodeSet&, const Compare&)
142 ->priority_queue_node<decide_on_set_t<NodeSet>, Compare>;
143 
144 template <typename NodeSet>
145 priority_queue_node(const NodeSet&)
146 ->priority_queue_node<decide_on_set_t<NodeSet>, std::less<decide_on_set_t<NodeSet>>>;
147 #endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
148 
149 template <typename Key>
150 struct join_key {
151     using type = Key;
152 };
153 
154 template <typename T>
155 struct join_key<const T&> {
156     using type = T&;
157 };
158 
159 template <typename Key>
160 using join_key_t = typename join_key<Key>::type;
161 
162 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
163 template <typename Policy, typename... Predecessors>
164 join_node(const node_set<order::following, Predecessors...>&, Policy)
165 ->join_node<std::tuple<typename Predecessors::output_type...>,
166             Policy>;
167 
168 template <typename Policy, typename Successor, typename... Successors>
169 join_node(const node_set<order::preceding, Successor, Successors...>&, Policy)
170 ->join_node<typename Successor::input_type, Policy>;
171 
172 template <typename... Predecessors>
173 join_node(const node_set<order::following, Predecessors...>)
174 ->join_node<std::tuple<typename Predecessors::output_type...>,
175             queueing>;
176 
177 template <typename Successor, typename... Successors>
178 join_node(const node_set<order::preceding, Successor, Successors...>)
179 ->join_node<typename Successor::input_type, queueing>;
180 #endif
181 
182 template <typename GraphOrProxy, typename Body, typename... Bodies>
183 join_node(GraphOrProxy&&, Body, Bodies...)
184 ->join_node<std::tuple<input_t<decltype(decide_on_callable_type<Body>(0))>,
185                        input_t<decltype(decide_on_callable_type<Bodies>(0))>...>,
186             key_matching<join_key_t<output_t<decltype(decide_on_callable_type<Body>(0))>>>>;
187 
188 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
189 template <typename... Predecessors>
190 indexer_node(const node_set<order::following, Predecessors...>&)
191 ->indexer_node<typename Predecessors::output_type...>;
192 #endif
193 
194 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
195 template <typename NodeSet>
196 limiter_node(const NodeSet&, size_t)
197 ->limiter_node<decide_on_set_t<NodeSet>>;
198 
199 template <typename Predecessor, typename... Predecessors>
200 split_node(const node_set<order::following, Predecessor, Predecessors...>&)
201 ->split_node<typename Predecessor::output_type>;
202 
203 template <typename... Successors>
204 split_node(const node_set<order::preceding, Successors...>&)
205 ->split_node<std::tuple<typename Successors::input_type...>>;
206 
207 #endif
208 
209 template <typename GraphOrSet, typename Body, typename Policy>
210 function_node(GraphOrSet&&,
211               size_t, Body,
212               Policy, node_priority_t = no_priority)
213 ->function_node<input_t<decltype(decide_on_callable_type<Body>(0))>,
214                 output_t<decltype(decide_on_callable_type<Body>(0))>,
215                 Policy>;
216 
217 template <typename GraphOrSet, typename Body>
218 function_node(GraphOrSet&&, size_t,
219               Body, node_priority_t = no_priority)
220 ->function_node<input_t<decltype(decide_on_callable_type<Body>(0))>,
221                 output_t<decltype(decide_on_callable_type<Body>(0))>,
222                 queueing>;
223 
224 template <typename Output>
225 struct continue_output {
226     using type = Output;
227 };
228 
229 template <>
230 struct continue_output<void> {
231     using type = continue_msg;
232 };
233 
234 template <typename T>
235 using continue_output_t = typename continue_output<T>::type;
236 
237 template <typename GraphOrSet, typename Body, typename Policy>
238 continue_node(GraphOrSet&&, Body,
239               Policy, node_priority_t = no_priority)
240 ->continue_node<continue_output_t<std::invoke_result_t<Body, continue_msg>>,
241                 Policy>;
242 
243 template <typename GraphOrSet, typename Body, typename Policy>
244 continue_node(GraphOrSet&&,
245               int, Body,
246               Policy, node_priority_t = no_priority)
247 ->continue_node<continue_output_t<std::invoke_result_t<Body, continue_msg>>,
248                 Policy>;
249 
250 template <typename GraphOrSet, typename Body>
251 continue_node(GraphOrSet&&,
252               Body, node_priority_t = no_priority)
253 ->continue_node<continue_output_t<std::invoke_result_t<Body, continue_msg>>, Policy<void>>;
254 
255 template <typename GraphOrSet, typename Body>
256 continue_node(GraphOrSet&&, int,
257               Body, node_priority_t = no_priority)
258 ->continue_node<continue_output_t<std::invoke_result_t<Body, continue_msg>>,
259                 Policy<void>>;
260 
261 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
262 
263 template <typename NodeSet>
264 overwrite_node(const NodeSet&)
265 ->overwrite_node<decide_on_set_t<NodeSet>>;
266 
267 template <typename NodeSet>
268 write_once_node(const NodeSet&)
269 ->write_once_node<decide_on_set_t<NodeSet>>;
270 #endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
271 } // namespace d1
272 } // namespace detail
273 } // namespace tbb
274 
275 #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
276 
277 #endif // __TBB_flow_graph_nodes_deduction_H
278