To what extent the source object should overwrite set (non-init) values in the receiving object.
Object to meld (source).
Reference to object to meld (target).
struct Foo { string abc; int def; bool b = true; } Foo foo, bar; foo.abc = "from foo" foo.b = false; bar.def = 42; foo.meldInto(bar); assert(bar.abc == "from foo"); assert(bar.def == 42); assert(!bar.b); // false overwrote default value true
1 import std.conv : to; 2 3 static struct TestFoo 4 { 5 string abc; 6 string def; 7 int i; 8 float f; 9 double d; 10 int[string] aa; 11 int[] arr; 12 int* ip; 13 14 void blah() {} 15 16 const string kek; 17 immutable bool bur; 18 19 this(bool bur) 20 { 21 kek = "uden lo"; 22 this.bur = bur; 23 } 24 } 25 { 26 TestFoo f1; // = new TestFoo; 27 f1.abc = "ABC"; 28 f1.def = "DEF"; 29 f1.aa = [ "abc" : 123, "ghi" : 789 ]; 30 f1.arr = [ 1, 0, 3, 0, 5 ]; 31 32 TestFoo f2; // = new TestFoo; 33 f2.abc = "this won't get copied"; 34 f2.def = "neither will this"; 35 f2.i = 42; 36 f2.f = 3.14f; 37 f2.aa = [ "abc" : 999, "def" : 456 ]; 38 f2.arr = [ 0, 2, 0, 4 ]; 39 40 f2.meldInto(f1); 41 42 with (f1) 43 { 44 import std.math : isNaN; 45 46 assert((abc == "ABC"), abc); 47 assert((def == "DEF"), def); 48 assert((i == 42), i.to!string); 49 assert((f == 3.14f), f.to!string); 50 assert(d.isNaN, d.to!string); 51 assert((aa == [ "abc" : 123, "def" : 456, "ghi" : 789 ]), aa.to!string); 52 assert((arr == [ 1, 2, 3, 4, 5 ]), arr.to!string); 53 } 54 } 55 { 56 TestFoo f3; // new TestFoo; 57 f3.abc = "abc"; 58 f3.def = "def"; 59 f3.i = 100_135; 60 f3.f = 99.9f; 61 f3.aa = [ "abc" : 123, "ghi" : 789 ]; 62 f3.arr = [ 1, 0, 3, 0, 5 ]; 63 64 TestFoo f4; // new TestFoo; 65 f4.abc = "OVERWRITTEN"; 66 f4.def = "OVERWRITTEN TOO"; 67 f4.i = 0; 68 f4.f = 0.1f; 69 f4.d = 99.999; 70 f4.aa = [ "abc" : 999, "def" : 456 ]; 71 f4.arr = [ 9, 2, 0, 4 ]; 72 73 f4.meldInto!(MeldingStrategy.aggressive)(f3); 74 75 with (f3) 76 { 77 import std.math : isClose; 78 79 assert((abc == "OVERWRITTEN"), abc); 80 assert((def == "OVERWRITTEN TOO"), def); 81 assert((i == 100_135), i.to!string); // 0 is int.init 82 assert((f == 0.1f), f.to!string); 83 assert(d.isClose(99.999), d.to!string); 84 assert((aa == [ "abc" : 999, "def" : 456, "ghi" : 789 ]), aa.to!string); 85 assert((arr == [ 9, 2, 3, 4, 5 ]), arr.to!string); 86 } 87 } 88 { 89 // Overwriting is just aggressive but always overwrites bools. 90 struct User 91 { 92 enum Class { anyone, blacklist, whitelist, admin } 93 string nickname; 94 string alias_; 95 string ident; 96 string address; 97 string login; 98 bool special; 99 Class class_; 100 } 101 102 User one; 103 with (one) 104 { 105 nickname = "foobar"; 106 ident = "NaN"; 107 address = "herpderp.net"; 108 special = false; 109 class_ = User.Class.whitelist; 110 } 111 112 User two; 113 with (two) 114 { 115 nickname = "foobar^"; 116 alias_ = "FooBar"; 117 address = "asdf.org"; 118 login = "kamelusu"; 119 special = true; 120 class_ = User.Class.blacklist; 121 } 122 123 //import lu.conv : Enum; 124 125 User twoCopy = two; 126 127 one.meldInto!(MeldingStrategy.conservative)(two); 128 with (two) 129 { 130 assert((nickname == "foobar^"), nickname); 131 assert((alias_ == "FooBar"), alias_); 132 assert((ident == "NaN"), ident); 133 assert((address == "asdf.org"), address); 134 assert((login == "kamelusu"), login); 135 assert(special); 136 assert(class_ == User.Class.whitelist);//, Enum!(User.Class).toString(class_)); 137 } 138 139 one.class_ = User.Class.blacklist; 140 141 one.meldInto!(MeldingStrategy.overwriting)(twoCopy); 142 with (twoCopy) 143 { 144 assert((nickname == "foobar"), nickname); 145 assert((alias_ == "FooBar"), alias_); 146 assert((ident == "NaN"), ident); 147 assert((address == "herpderp.net"), address); 148 assert((login == "kamelusu"), login); 149 assert(!special); 150 assert(class_ == User.Class.blacklist);//, Enum!(User.Class).toString(class_)); 151 } 152 } 153 { 154 struct EnumThing 155 { 156 enum Enum { unset, one, two, three } 157 Enum enum_; 158 } 159 160 EnumThing e1; 161 EnumThing e2; 162 e2.enum_ = EnumThing.Enum.three; 163 assert(e1.enum_ == EnumThing.Enum.init);//, Enum!(EnumThing.Enum).toString(e1.enum_)); 164 e2.meldInto(e1); 165 assert(e1.enum_ == EnumThing.Enum.three);//, Enum!(EnumThing.Enum).toString(e1.enum_)); 166 167 struct WithArray 168 { 169 string[] arr; 170 } 171 172 WithArray w1, w2; 173 w1.arr = [ "arr", "matey", "I'ma" ]; 174 w2.arr = [ "pirate", "stereotype", "unittest" ]; 175 w2.meldInto(w1); 176 assert((w1.arr == [ "arr", "matey", "I'ma", "pirate", "stereotype", "unittest" ]), w1.arr.to!string); 177 178 WithArray w3, w4; 179 w3.arr = [ "arr", "matey", "I'ma" ]; 180 w4.arr = [ "arr", "matey", "I'ma" ]; 181 w4.meldInto(w3); 182 assert((w3.arr == [ "arr", "matey", "I'ma" ]), w3.arr.to!string); 183 } 184 { 185 struct Server 186 { 187 string address; 188 } 189 190 struct Bot 191 { 192 string nickname; 193 Server server; 194 } 195 196 Bot b1, b2; 197 b1.nickname = "foobar"; 198 b1.server.address = "freenode.net"; 199 200 assert(!b2.nickname.length, b2.nickname); 201 assert(!b2.server.address.length, b2.nickname); 202 b1.meldInto(b2); 203 assert((b2.nickname == "foobar"), b2.nickname); 204 assert((b2.server.address == "freenode.net"), b2.server.address); 205 206 b2.nickname = "harbl"; 207 b2.server.address = "rizon.net"; 208 209 b2.meldInto!(MeldingStrategy.aggressive)(b1); 210 assert((b1.nickname == "harbl"), b1.nickname); 211 assert((b1.server.address == "rizon.net"), b1.server.address); 212 } 213 { 214 class Class 215 { 216 static int i; 217 string s; 218 bool b; 219 } 220 221 Class abc = new Class; 222 abc.i = 42; 223 abc.s = "some string"; 224 abc.b = true; 225 226 Class def = new Class; 227 def.s = "other string"; 228 abc.meldInto(def); 229 230 assert((def.i == 42), def.i.to!string); 231 assert((def.s == "other string"), def.s); 232 assert(def.b); 233 234 abc.meldInto!(MeldingStrategy.aggressive)(def); 235 assert((def.s == "some string"), def.s); 236 } 237 { 238 struct Bools 239 { 240 bool a = true; 241 bool b = false; 242 } 243 244 Bools bools1, bools2, inverted, backupInverted; 245 246 bools2.a = false; 247 248 inverted.a = false; 249 inverted.b = true; 250 backupInverted = inverted; 251 252 bools2.meldInto(bools1); 253 assert(!bools1.a); 254 assert(!bools1.b); 255 256 bools2.meldInto(inverted); 257 assert(!inverted.a); 258 assert(inverted.b); 259 inverted = backupInverted; 260 261 bools2.meldInto!(MeldingStrategy.overwriting)(inverted); 262 assert(!inverted.a); 263 assert(!inverted.b); 264 inverted = backupInverted; 265 } 266 { 267 struct Asdf 268 { 269 string nickname = "sadf"; 270 string server = "asdf.net"; 271 } 272 273 Asdf a, b; 274 a.server = "a"; 275 b.server = "b"; 276 b.meldInto!(MeldingStrategy.aggressive)(a); 277 assert((a.server == "b"), a.server); 278 279 a.server = "a"; 280 b.server = Asdf.init.server; 281 b.meldInto!(MeldingStrategy.aggressive)(a); 282 assert((a.server == "a"), a.server); 283 } 284 { 285 struct Blah 286 { 287 int yes = 42; 288 @Unmeldable int no = 24; 289 } 290 291 Blah blah1, blah2; 292 blah1.yes = 5; 293 blah1.no = 42; 294 blah1.meldInto!(MeldingStrategy.aggressive)(blah2); 295 assert((blah2.yes == 5), blah2.yes.to!string); 296 assert((blah2.no == 24), blah2.no.to!string); 297 }
Takes two structs or classes of the same type and melds them together, making the members a union of the two.
In the case of classes it only overwrites members in intoThis that are typeof(member).init, so only unset members get their values overwritten by the melding class. It also does not work with static members.
In the case of structs it also overwrites members that still have their default values, in cases where such is applicable.
Supply a template parameter MeldingStrategy to decide to which extent values are overwritten.