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