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 TestFoo f3; // new TestFoo; 56 f3.abc = "abc"; 57 f3.def = "def"; 58 f3.i = 100_135; 59 f3.f = 99.9f; 60 f3.aa = [ "abc" : 123, "ghi" : 789 ]; 61 f3.arr = [ 1, 0, 3, 0, 5 ]; 62 63 TestFoo f4; // new TestFoo; 64 f4.abc = "OVERWRITTEN"; 65 f4.def = "OVERWRITTEN TOO"; 66 f4.i = 0; 67 f4.f = 0.1f; 68 f4.d = 99.999; 69 f4.aa = [ "abc" : 999, "def" : 456 ]; 70 f4.arr = [ 9, 2, 0, 4 ]; 71 72 f4.meldInto!(MeldingStrategy.aggressive)(f3); 73 74 with (f3) 75 { 76 static if (__VERSION__ >= 2091) 77 { 78 import std.math : isClose; 79 } 80 else 81 { 82 import std.math : approxEqual; 83 alias isClose = approxEqual; 84 } 85 86 assert((abc == "OVERWRITTEN"), abc); 87 assert((def == "OVERWRITTEN TOO"), def); 88 assert((i == 100_135), i.to!string); // 0 is int.init 89 assert((f == 0.1f), f.to!string); 90 assert(isClose(d, 99.999), d.to!string); 91 assert((aa == [ "abc" : 999, "def" : 456, "ghi" : 789 ]), aa.to!string); 92 assert((arr == [ 9, 2, 3, 4, 5 ]), arr.to!string); 93 } 94 95 // Overwriting is just aggressive but always overwrites bools. 96 97 struct User 98 { 99 enum Class { anyone, blacklist, whitelist, admin } 100 string nickname; 101 string alias_; 102 string ident; 103 string address; 104 string login; 105 bool special; 106 Class class_; 107 } 108 109 User one; 110 with (one) 111 { 112 nickname = "foobar"; 113 ident = "NaN"; 114 address = "herpderp.net"; 115 special = false; 116 class_ = User.Class.whitelist; 117 } 118 119 User two; 120 with (two) 121 { 122 nickname = "foobar^"; 123 alias_ = "FooBar"; 124 address = "asdf.org"; 125 login = "kamelusu"; 126 special = true; 127 class_ = User.Class.blacklist; 128 } 129 130 //import lu.conv : Enum; 131 132 User twoCopy = two; 133 134 one.meldInto!(MeldingStrategy.conservative)(two); 135 with (two) 136 { 137 assert((nickname == "foobar^"), nickname); 138 assert((alias_ == "FooBar"), alias_); 139 assert((ident == "NaN"), ident); 140 assert((address == "asdf.org"), address); 141 assert((login == "kamelusu"), login); 142 assert(special); 143 assert(class_ == User.Class.whitelist);//, Enum!(User.Class).toString(class_)); 144 } 145 146 one.class_ = User.Class.blacklist; 147 148 one.meldInto!(MeldingStrategy.overwriting)(twoCopy); 149 with (twoCopy) 150 { 151 assert((nickname == "foobar"), nickname); 152 assert((alias_ == "FooBar"), alias_); 153 assert((ident == "NaN"), ident); 154 assert((address == "herpderp.net"), address); 155 assert((login == "kamelusu"), login); 156 assert(!special); 157 assert(class_ == User.Class.blacklist);//, Enum!(User.Class).toString(class_)); 158 } 159 160 struct EnumThing 161 { 162 enum Enum { unset, one, two, three } 163 Enum enum_; 164 } 165 166 EnumThing e1; 167 EnumThing e2; 168 e2.enum_ = EnumThing.Enum.three; 169 assert(e1.enum_ == EnumThing.Enum.init);//, Enum!(EnumThing.Enum).toString(e1.enum_)); 170 e2.meldInto(e1); 171 assert(e1.enum_ == EnumThing.Enum.three);//, Enum!(EnumThing.Enum).toString(e1.enum_)); 172 173 struct WithArray 174 { 175 string[] arr; 176 } 177 178 WithArray w1, w2; 179 w1.arr = [ "arr", "matey", "I'ma" ]; 180 w2.arr = [ "pirate", "stereotype", "unittest" ]; 181 w2.meldInto(w1); 182 assert((w1.arr == [ "arr", "matey", "I'ma", "pirate", "stereotype", "unittest" ]), w1.arr.to!string); 183 184 WithArray w3, w4; 185 w3.arr = [ "arr", "matey", "I'ma" ]; 186 w4.arr = [ "arr", "matey", "I'ma" ]; 187 w4.meldInto(w3); 188 assert((w3.arr == [ "arr", "matey", "I'ma" ]), w3.arr.to!string); 189 190 struct Server 191 { 192 string address; 193 } 194 195 struct Bot 196 { 197 string nickname; 198 Server server; 199 } 200 201 Bot b1, b2; 202 b1.nickname = "foobar"; 203 b1.server.address = "freenode.net"; 204 205 assert(!b2.nickname.length, b2.nickname); 206 assert(!b2.server.address.length, b2.nickname); 207 b1.meldInto(b2); 208 assert((b2.nickname == "foobar"), b2.nickname); 209 assert((b2.server.address == "freenode.net"), b2.server.address); 210 211 b2.nickname = "harbl"; 212 b2.server.address = "rizon.net"; 213 214 b2.meldInto!(MeldingStrategy.aggressive)(b1); 215 assert((b1.nickname == "harbl"), b1.nickname); 216 assert((b1.server.address == "rizon.net"), b1.server.address); 217 218 class Class 219 { 220 static int i; 221 string s; 222 bool b; 223 } 224 225 Class abc = new Class; 226 abc.i = 42; 227 abc.s = "some string"; 228 abc.b = true; 229 230 Class def = new Class; 231 def.s = "other string"; 232 abc.meldInto(def); 233 234 assert((def.i == 42), def.i.to!string); 235 assert((def.s == "other string"), def.s); 236 assert(def.b); 237 238 abc.meldInto!(MeldingStrategy.aggressive)(def); 239 assert((def.s == "some string"), def.s); 240 241 struct Bools 242 { 243 bool a = true; 244 bool b = false; 245 } 246 247 Bools bools1, bools2, inverted, backupInverted; 248 249 bools2.a = false; 250 251 inverted.a = false; 252 inverted.b = true; 253 backupInverted = inverted; 254 255 bools2.meldInto(bools1); 256 assert(!bools1.a); 257 assert(!bools1.b); 258 259 bools2.meldInto(inverted); 260 assert(!inverted.a); 261 assert(inverted.b); 262 inverted = backupInverted; 263 264 bools2.meldInto!(MeldingStrategy.overwriting)(inverted); 265 assert(!inverted.a); 266 assert(!inverted.b); 267 inverted = backupInverted; 268 269 struct Asdf 270 { 271 string nickname = "sadf"; 272 string server = "asdf.net"; 273 } 274 275 Asdf a, b; 276 a.server = "a"; 277 b.server = "b"; 278 b.meldInto!(MeldingStrategy.aggressive)(a); 279 assert((a.server == "b"), a.server); 280 281 a.server = "a"; 282 b.server = Asdf.init.server; 283 b.meldInto!(MeldingStrategy.aggressive)(a); 284 assert((a.server == "a"), a.server); 285 286 struct Blah 287 { 288 int yes = 42; 289 @Unmeldable int no = 24; 290 } 291 292 Blah blah1, blah2; 293 blah1.yes = 5; 294 blah1.no = 42; 295 blah1.meldInto!(MeldingStrategy.aggressive)(blah2); 296 assert((blah2.yes == 5), blah2.yes.to!string); 297 assert((blah2.no == 24), blah2.no.to!string);
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.