1 module mutils.functional;
2 
3 //TODO use taggedPointer https://dlang.org/phobos/std_bitmanip.html
4 import std.traits;
5 
6 struct FunctionOrDelegate(DelegateOrFunctionType) {
7 	static assert(isSomeFunction!DelegateOrFunctionType);
8 	alias Ret = ReturnType!DelegateOrFunctionType;
9 	alias Par = Parameters!DelegateOrFunctionType;
10 
11 	alias DelegateType = Ret delegate(Par);
12 	alias FunctionType = Ret function(Par);
13 	union {
14 		DelegateType del;
15 		FunctionType func;
16 	}
17 
18 	bool isDelegate;
19 
20 	this(DelegateType cal) {
21 		opAssign(cal);
22 	}
23 
24 	this(FunctionType cal) {
25 		opAssign(cal);
26 	}
27 
28 	Ret opCall(Args...)(Args parameters) {
29 		static assert(is(Args == Par));
30 		assert(func !is null);
31 		static if (is(Ret == void)) {
32 			if (isDelegate) {
33 				del(parameters);
34 			} else {
35 				func(parameters);
36 			}
37 		} else {
38 			if (isDelegate) {
39 				return del(parameters);
40 			} else {
41 				return func(parameters);
42 			}
43 		}
44 	}
45 
46 	void opAssign(DelegateType cal) {
47 		del = cal;
48 		isDelegate = true;
49 	}
50 
51 	void opAssign(FunctionType cal) {
52 		func = cal;
53 		isDelegate = false;
54 	}
55 
56 	bool opEquals(typeof(this) a) {
57 		if (isDelegate != a.isDelegate) {
58 			return false;
59 		}
60 		if (isDelegate) {
61 			return del == a.del;
62 		} else {
63 			return func == a.func;
64 		}
65 	}
66 }