1 /++ 2 Type constructors. 3 +/ 4 module lu.typecons; 5 6 private: 7 8 public: 9 10 11 // UnderscoreOpDispatcher 12 /++ 13 Mixin template generating an `opDispatch` redirecting calls to members whose 14 names match the passed variable string but with an underscore prepended. 15 +/ 16 mixin template UnderscoreOpDispatcher() 17 { 18 version(unittest) 19 { 20 import lu.traits : MixinConstraints, MixinScope; 21 mixin MixinConstraints!( 22 (MixinScope.struct_ | MixinScope.class_ | MixinScope.union_), 23 typeof(this).stringof); 24 } 25 26 /++ 27 Mutator. 28 29 Params: 30 var = The variable name to set. 31 value = The value to set the variable to. 32 33 Returns: 34 A reference to the object which this is mixed into. 35 +/ 36 ref auto opDispatch(string var, T)(T value) 37 { 38 import std.traits : isArray, isAssociativeArray, isSomeString; 39 40 enum realVar = '_' ~ var; 41 alias V = typeof(mixin(realVar)); 42 43 static if (isAssociativeArray!V) 44 { 45 import lu.meld : MeldingStrategy, meldInto; 46 value.meldInto!(MeldingStrategy.overwriting)(mixin(realVar)); 47 } 48 else static if (isArray!V && !isSomeString!V) 49 { 50 mixin(realVar) ~= value; 51 } 52 else 53 { 54 mixin(realVar) = value; 55 } 56 57 return this; 58 } 59 60 /++ 61 Accessor. 62 63 Params: 64 var = The variable name to get. 65 66 Returns: 67 The value of the variable. 68 +/ 69 auto opDispatch(string var)() inout 70 { 71 enum realVar = '_' ~ var; 72 return mixin(realVar); 73 } 74 } 75 76 /// 77 unittest 78 { 79 { 80 struct Foo 81 { 82 int _i; 83 string _s; 84 bool _b; 85 string[] _add; 86 alias wordList = _add; 87 88 mixin UnderscoreOpDispatcher; 89 } 90 91 Foo f; 92 f.i = 42; // f.opDispatch!"i"(42); 93 f.s = "hello"; // f.opDispatch!"s"("hello"); 94 f.b = true; // f.opDispatch!"b"(true); 95 f.add("hello"); // f.opDispatch!"add"("hello"); 96 f.add("world"); // f.opDispatch!"add"("world"); 97 98 assert(f.i == 42); 99 assert(f.s == "hello"); 100 assert(f.b); 101 assert(f.wordList == [ "hello", "world" ]); 102 103 /+ 104 Returns `this` by reference, so we can chain calls. 105 +/ 106 auto f2 = Foo() 107 .i(9001) 108 .s("world") 109 .b(false) 110 .add("hello") 111 .add("world"); 112 113 assert(f2.i == 9001); 114 assert(f2.s == "world"); 115 assert(!f2.b); 116 assert(f2.wordList == [ "hello", "world" ]); 117 } 118 { 119 struct Bar 120 { 121 string[string] _aa; 122 123 mixin UnderscoreOpDispatcher; 124 } 125 126 Bar bar; 127 bar.aa = [ "hello" : "world" ]; 128 bar.aa = [ "foo" : "bar" ]; 129 assert(bar.aa == [ "hello" : "world", "foo" : "bar"]); 130 } 131 }