scoped classes

Alex via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Apr 27 11:36:08 PDT 2017


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



More information about the Digitalmars-d-learn mailing list