@@ -148,7 +148,7 @@ struct DynamicArray(T, Allocator = Mallocator, bool supportGC = shouldAddGCRange
148148 else
149149 (() @trusted => memcpy(arr.ptr + l, init.ptr, T.sizeof))();
150150 }
151- arr[l++ ] = value;
151+ emplace( arr[l++ ], value) ;
152152 }
153153
154154 // / ditto
@@ -189,29 +189,8 @@ struct DynamicArray(T, Allocator = Mallocator, bool supportGC = shouldAddGCRange
189189 import std.traits : hasElaborateAssign, hasElaborateDestructor;
190190 static if (is (T == struct ) && (hasElaborateAssign! T || hasElaborateDestructor! T))
191191 {
192- // If a destructor is run before blit or assignment involves
193- // more than just a blit, ensure that arr[l] is in a valid
194- // state before assigning to it.
195- import core.stdc.string : memcpy, memset;
196- const init = typeid (T).initializer();
197- if (init.ptr is null ) // null pointer means initialize to 0s
198- {
199- foreach (ref value; rhs)
200- {
201- // We could call memset just once for the entire range
202- // but this way has better memory locality.
203- (() @trusted => memset(arr.ptr + l, 0 , T.sizeof))();
204- arr[l++ ] = value;
205- }
206- }
207- else
208- {
209- foreach (ref value; rhs)
210- {
211- (() @trusted => memcpy(arr.ptr + l, init.ptr, T.sizeof))();
212- arr[l++ ] = value;
213- }
214- }
192+ foreach (ref value; rhs)
193+ emplace(arr[l++ ], value);
215194 }
216195 else
217196 {
@@ -288,6 +267,51 @@ struct DynamicArray(T, Allocator = Mallocator, bool supportGC = shouldAddGCRange
288267 }
289268 }
290269
270+ static if (is (typeof ({T value;}))) // default construction is allowed
271+ {
272+ /**
273+ * Change the array length.
274+ * When growing, initialize new elements to the default value.
275+ */
276+ void resize (size_t n)
277+ {
278+ resize(n, T.init);
279+ }
280+ }
281+
282+ /**
283+ * Change the array length.
284+ * When growing, initialize new elements to the given value.
285+ */
286+ void resize (size_t n, T value)
287+ {
288+ if (arr.length < n)
289+ reserve (n);
290+
291+ if (l < n) // Growing?
292+ {
293+ import std.traits : hasElaborateAssign, hasElaborateDestructor;
294+ static if (is (T == struct ) && (hasElaborateAssign! T || hasElaborateDestructor! T))
295+ {
296+ foreach (i; l.. n)
297+ emplace(arr[l], value);
298+ }
299+ else
300+ arr[l.. n] = value;
301+ }
302+ else
303+ {
304+ static if ((is (T == struct ) || is (T == union ))
305+ && __traits(hasMember, T, " __xdtor" ))
306+ {
307+ foreach (i; n.. l)
308+ arr[i].__xdtor();
309+ }
310+ }
311+
312+ l = n;
313+ }
314+
291315 /**
292316 * Remove the item at the given index from the array.
293317 */
@@ -377,6 +401,13 @@ struct DynamicArray(T, Allocator = Mallocator, bool supportGC = shouldAddGCRange
377401
378402private :
379403
404+ static void emplace (ref ContainerStorageType! T target, ref AppendT source)
405+ {
406+ (cast (void [])((&target)[0 .. 1 ]))[] = cast (void [])((&source)[0 .. 1 ]);
407+ static if (__traits(hasMember, T, " __xpostblit" ))
408+ target.__xpostblit();
409+ }
410+
380411 import containers.internal.storage_type : ContainerStorageType;
381412 import containers.internal.element_type : ContainerElementType;
382413 import containers.internal.mixins : AllocatorState;
@@ -588,3 +619,50 @@ version(emsi_containers_unittest) @nogc unittest
588619 a ~= a;
589620 assert (a[] == " abcdefabcdef" );
590621}
622+
623+ version (emsi_containers_unittest) unittest
624+ {
625+ static struct S
626+ {
627+ bool initialized;
628+ @nogc :
629+ @disable this ();
630+ this (int ) { initialized = true ; }
631+ ~this () { assert (initialized); }
632+ }
633+
634+ auto s = S(0 );
635+
636+ DynamicArray! S arr;
637+ arr.insertBack(s);
638+ arr ~= [s];
639+ }
640+
641+ version (emsi_containers_unittest) @nogc unittest
642+ {
643+ DynamicArray! int a;
644+ a.resize(5 , 42 );
645+ assert (a.length == 5 );
646+ assert (a[2 ] == 42 );
647+ a.resize(3 , 17 );
648+ assert (a.length == 3 );
649+ assert (a[2 ] == 42 );
650+
651+ struct Counter
652+ {
653+ @nogc :
654+ static int count;
655+ @disable this ();
656+ this (int ) { count++ ; }
657+ this (this ) { count++ ; }
658+ ~this () { count-- ; }
659+ }
660+
661+ DynamicArray! Counter b;
662+ assert (Counter.count == 0 );
663+ static assert (! is (typeof (b.resize(5 ))));
664+ b.resize(5 , Counter (0 ));
665+ assert (Counter.count == 5 );
666+ b.resize(3 , Counter (0 ));
667+ assert (Counter.count == 3 );
668+ }
0 commit comments