240#define MakeGenericTwoInputFunc(name, f) \
241 template <typename Out, typename In1, typename In2> \
242 struct name : Evaluatable<Out> \
243 { \
244 template <typename In1_t, typename In2_t> \
245 struct ReferenceCase : Evaluatable<Out> \
246 { \
247 In1_t* input1; \
248 In2_t* input2; \
249 operator Out() const { return f(*input1, *input2); } \
250 ReferenceCase(In1_t* in1, In2_t* in2) : input1(in1), input2(in2) {} \
251 }; \
252 template <typename In2_type> \
253 struct ConstCase1 : Evaluatable<Out> \
254 { \
255 In1 input1; \
256 In2_type* input2; \
257 operator Out() const { return f(input1, *input2); } \
258 ConstCase1(In1 in1, In2_type* in2) : input1(in1), input2(in2) {} \
259 }; \
260 template <typename In1_type> \
261 struct ConstCase2 : Evaluatable<Out> \
262 { \
263 In1_type* input1; \
264 In2 input2; \
265 operator Out() const { return f(*input1, input2); } \
266 ConstCase2(In1_type* in1, In2 in2) : input1(in1), input2(in2) {} \
267 }; \
268 Evaluatable<In1>* input1; \
269 Evaluatable<In2>* input2; \
270 operator Out() const { return f(*input1, *input2); } \
271 name(Evaluatable<In1>* in1, Evaluatable<In2>* in2) : input1(in1), input2(in2) {} \
272 Evaluatable<Out>* \
273 optimize(MemoryManager& m) \
274 { \
275 Evaluatable<In1>* input1 = this->input1->optimize(m); \
276 Evaluatable<In2>* input2 = this->input2->optimize(m); \
277 if (auto const1 = dynamic_cast<GenericConstant<In1>*>(input1)) { \
278 if (auto const2 = dynamic_cast<GenericConstant<In2>*>(input2)) \
279 return m.New<GenericConstant<Out>>(f(*input1, *input2)); \
280 else if (auto ref2 = dynamic_cast<GenericReference<In2>*>(input2)) \
281 return m.New<ConstCase1<In2>>(const1->value, ref2->value); \
282 else \
283 return m.New<ConstCase1<Evaluatable<In2>>>(const1->value, input2); \
284 } else if (auto ref1 = dynamic_cast<GenericReference<In1>*>(input1)) { \
285 if (auto const2 = dynamic_cast<GenericConstant<In2>*>(input2)) \
286 return m.New<ConstCase2<In1>>(ref1->value, const2->value); \
287 else if (auto ref2 = dynamic_cast<GenericReference<In2>*>(input2)) \
288 return m.New<ReferenceCase<In1, In2>>(ref1->value, ref2->value); \
289 else \
290 return m.New<ReferenceCase<In1, Evaluatable<In2>>>(ref1->value, input2); \
291 } else if (auto const2 = dynamic_cast<GenericConstant<In2>*>(input2)) \
292 return m.New<ConstCase2<Evaluatable<In1>>>(input1, const2->value); \
293 else if (auto ref2 = dynamic_cast<GenericReference<In2>*>(input2)) \
294 return m.New<ReferenceCase<Evaluatable<In1>, In2>>(input1, ref2->value); \
295 this->input1 = input1; \
296 this->input2 = input2; \
297 return this; \
298 } \
299 };