1 /** 2 * Method binding - using alias inference patch 3 * 4 * License: 5 * This Source Code Form is subject to the terms of 6 * the Mozilla Public License, v. 2.0. If a copy of 7 * the MPL was not distributed with this file, You 8 * can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * Authors: 11 * Vladimir Panteleev <vladimir@thecybershadow.net> 12 */ 13 14 module ae.utils.meta.binding; 15 16 import ae.utils.meta : thisOf; 17 import ae.utils.meta.caps; 18 import ae.utils.meta.reference; 19 20 /// Create unbound functor of a method 21 template unboundFunctorOf(alias f) 22 { 23 static @property auto unboundFunctorOf() 24 { 25 UnboundFunctorOf!f r; 26 return r; 27 } 28 } 29 struct UnboundFunctorOf(alias f) 30 { 31 alias opCall = f; 32 33 alias R = RefType!(thisOf!f); 34 auto bind(R r) { return boundFunctorOf!f(r); } 35 } 36 37 /// Create bound functor of a method 38 template boundFunctorOf(alias f) 39 { 40 static @property auto boundFunctorOf(T)(T context) 41 { 42 BoundFunctorOf!(T, f) r; 43 r.context = context; 44 return r; 45 } 46 } 47 48 /// ditto 49 @property auto boundFunctorOf(alias f)() 50 if (is(typeof(this))) // haveMethodAliasBinding 51 { 52 BoundFunctorOf!(RefType!(typeof(this)), f) r; 53 r.context = this.reference; 54 return r; 55 } 56 57 struct BoundFunctorOf(R, alias f) 58 { 59 R context; 60 template opCall(Args...) 61 { 62 alias Ret = typeof(__traits(child, context, f)(Args.init)); 63 Ret opCall(auto ref Args args) 64 { 65 return __traits(child, context, f)(args); 66 } 67 } 68 69 /// Ignore - BoundFunctors are already bound 70 auto bind(R)(R r) { return this; } 71 } 72 73 static if (haveChildTrait) 74 unittest 75 { 76 static struct Test 77 { 78 void caller(Func)(Func func) 79 { 80 func(); 81 } 82 83 int i = 0; 84 85 void callee() 86 { 87 i++; 88 } 89 90 void test() 91 { 92 caller(unboundFunctorOf!callee.bind(&this)); 93 assert(i == 1); 94 95 static if (haveMethodAliasBinding) // or is it haveAliasCtxInference ? 96 { 97 caller(unboundFunctorOf!callee); 98 caller( boundFunctorOf!callee); 99 100 assert(i == 3); 101 } 102 103 static struct S 104 { 105 int i = 0; 106 107 void callee() 108 { 109 i++; 110 } 111 } 112 S s; 113 caller(boundFunctorOf!(S.callee)(&s)); 114 115 assert(s.i == 1); 116 } 117 } 118 119 Test test; 120 test.test(); 121 }