meldInto

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.

  1. void meldInto(QualThing meldThis, Thing intoThis)
    void
    meldInto
    (
    QualThing
    Thing
    )
    (
    auto ref QualThing meldThis
    ,
    ref Thing intoThis
    )
    if (
    isAggregateType!Thing &&
    is(QualThing : Thing)
    &&
    isMutable!Thing
    )
  2. void meldInto(Array1 meldThis, Array2 intoThis)
  3. void meldInto(QualAA meldThis, AA intoThis)

Parameters

strategy

To what extent the source object should overwrite set (non-init) values in the receiving object.

meldThis QualThing

Object to meld (source).

intoThis Thing

Reference to object to meld (target).

Examples

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 }