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 }