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 	bool isDelegate;
18 	
19 	this(DelegateType cal){
20 		opAssign(cal);
21 	}
22 	this(FunctionType cal){
23 		opAssign(cal);
24 	}
25 	Ret opCall(Args...)(Args parameters){
26 		static assert(is(Args==Par));
27 		assert(func !is null);
28 		static if(is(Ret==void)){
29 			if(isDelegate){
30 				del(parameters);
31 			}else{
32 				func(parameters);
33 			}
34 		}else{
35 			if(isDelegate){
36 				return del(parameters);
37 			}else{
38 				return func(parameters);
39 			}
40 		}
41 	}
42 	
43 	void opAssign(DelegateType cal){
44 		del=cal;
45 		isDelegate=true;
46 	}
47 	void opAssign(FunctionType cal){
48 		func=cal;
49 		isDelegate=false;
50 	}
51 	bool opEquals(typeof(this) a){
52 		if(isDelegate!=a.isDelegate){
53 			return false;
54 		}
55 		if(isDelegate){
56 			return del==a.del;
57 		}else{
58 			return func==a.func;
59 		}
60 	}
61 }
62