On Thursday, 27 April 2017 at 17:39:42 UTC, ag0aep6g wrote:
On 04/27/2017 05:47 PM, Alex wrote:
void main()
{
S[] arr;
S s = S(42);
arr = [s]; // this doesn't work :(
}
struct S
{
@disable this();
@disable this(this);
this(size_t dummy){}
}
1) Construct the S instance directly in the array literal:
----
arr = [S(42]);
----
But I guess that's besides the point. So ...
2) Use std.algorithm.mutation.move [1]:
----
import std.algorithm.mutation: move;
S s = S(42);
arr = [move(s)];
----
`move` makes a "destructive copy" here; i.e, it resets `s` to
`S.init`.
You probably want to append to that array at some point. That's
going to be more tricky, because appending potentially involves
copying the whole array.
This might work:
----
import std.algorithm.mutation: moveEmplace;
import std.array: uninitializedArray;
/* Make a new, larger array: */
S[] new_arr = uninitializedArray!(S[])(arr.length + 1);
/* Copy existing elements; destroy old array: */
foreach (size_t i; 0 .. arr.length) moveEmplace(arr[i],
new_arr[i]);
/* Copy new element; destroy s: */
moveEmplace(s, new_arr[$ - 1]);
/* Replace old array with new one: */
arr = new_arr;
----
Cool! Works like a charm :)
Notes:
* `moveEmplace` and `uninitializedArray` are completely unsafe.
You must ensure safety yourself.
Yes, I'm aware of this...
* I'm not entirely sure that the code is completely correct. It
might be invalid and break some language rule.
:-) I'm not sure about what is worse: to be forced to use
pointers or to use black magic practices at preparation step
only. So... Now, I have at least a choice...
* I'm pretty sure that the code is going to be invalid when
you're dealing with const/immutable data.
Ok... this is important... I tried this out, and the value of the
immutable data even remains the same. But for safety reasons, I
would reconstruct the structs inside the array anyway, so I can
live with this, I think...
* The code destroys the old array. References to it (slices of
it, pointers into it) will show .init values.
That's ok... at creation time, there won't be any references
yet...
* Maybe one can make use of `.capacity` somehow. As it is, the
code makes a copy of the whole array every time.
Tried this out for some values, capacity of the new array is
always 0.
* If this "moveAppend" functionality can be done in a valid
manner, it might be a worthwhile addition to the "move"
function family.
:-)
Thanks a lot!
[1] http://dlang.org/phobos/std_algorithm_mutation.html#.move