Any way to move in @disabled this(this) type in to a wrapping template?

Paul Backus snarwin at gmail.com
Thu Jul 25 21:23:33 UTC 2019


On Thursday, 25 July 2019 at 20:38:59 UTC, aliak wrote:
> On Thursday, 25 July 2019 at 19:35:36 UTC, aliak wrote:
>> Basically, can template W be made to handle an S that can't be 
>> copied?
>>
>> import std;
>>
>> static struct S {
>>     int i;
>>     @disable this(this);
>>     this(int i) { this.i = i; }
>> }
>>
>> [...]
>
> So this works - are there any problems with it?
>
> struct W(T) {
>     T value;
>     this(T value) {
>         static if (isMutable!T)
>             this.value = value.move;
>         else
>             this.value = value;
>     }
> }
>
> auto wrap(T)(T value) {
>     static if (isMutable!T)
>         return W!T(value.move);
>     else
>         return W!T(value);
> }
>
> Shouldn't this be happening by default? When would you not want 
> that to happen?

The way I handle this is with `auto ref` and 
`core.lifetime.forward`:

import core.lifetime: forward;

struct W(T)
{
     T value;
     this()(auto ref T value)
     {
         this.value = forward!value;
     }
}

auto wrap(T)(auto ref T value)
{
     return W!T(forward!value);
}

@safe unittest
{
     static struct NoCopy { @disable this(this); }
     assert(__traits(compiles, {
         auto test = wrap(NoCopy());
     }));
     assert(!__traits(compiles, {
         auto lval = NoCopy(); auto test = lval;
     }));
}

Interactive: https://run.dlang.io/is/kDJyYC

It's not very well documented, but `forward` does essentially the 
same thing as your `static if` + `move` combination.

Note that with both your version and mine, you will run into the 
same problem I did of `move` making it impossible to use 
instances of `W` in static initializers and CTFE. [1] The best 
compromise I was able to come up with was to only call move if 
`isCopyable!T == false`, which doesn't really solve the problem, 
but at least contains it.

[1] https://github.com/pbackus/sumtype/issues/22


More information about the Digitalmars-d-learn mailing list