Thread overview
NoCopy for overriding @disable this(this)
Apr 12, 2018
Shachar Shemesh
Apr 12, 2018
Uknown
Apr 12, 2018
Shachar Shemesh
Apr 15, 2018
Eduard Staniloiu
April 12, 2018
I'm trying to build a wrapper that will allow you to copy structs that have members that disabled copying. The idea is that copying these members will revert them to init.

This is what I have so far:

struct NoCopy(T) {
    static assert( !hasElaborateDestructor!T, "NoCopy does not support type " ~ T.stringof ~ " with elaborate destructor" );

private:
    ubyte[T.sizeof] __bytes;

public:
    this(T val) {
        __bytes[] = (cast(const ubyte *)&val)[0..T.sizeof][];
    }

    @property ref inout(T) value() inout nothrow @trusted @nogc {
        return *cast(inout T*)__bytes.ptr;
    }

    this(this) {
        value = T.init;
    }

    void opAssign(NoCopy rhs) {
        value = T.init;
    }

    void opAssign(T rhs) {
        value = move(rhs);
    }

    alias this value;
}

I'm having problems with setting the initial value for the byte array. The technique I use in "value" does not work for initialization:

test.d(19): Error: cannot convert &S to const(ubyte*) at compile time

At first, I said "fine, the user will do it". That doesn't work, however. It doesn't matter who tries to do it, I cannot get the byte value of the type at compile time.

I tried using a union, but that, too, doesn't work.

I understand why the restriction is in place. What I'm wondering is whether there is any other solution, either to the init problem or to the overriding disable problem.

Thank you,
Shachar
April 12, 2018
On Thursday, 12 April 2018 at 12:16:53 UTC, Shachar Shemesh wrote:
> [...]
> test.d(19): Error: cannot convert &S to const(ubyte*) at compile time
> [...]
> Thank you,
> Shachar

The problem seems to be that cast is happening at compile time, as opposed to run time, as you might have already figured out. Do you need to really do this cast at compile time? I tried running the snippet you gave here: https://run.dlang.io/is/im19nL

Is this how you intend for it to be used? Then there's no need for compile time casts. If not, could you give an example of how `NoCopy` would be used?
April 12, 2018
On 12/04/18 18:42, Uknown wrote:
> On Thursday, 12 April 2018 at 12:16:53 UTC, Shachar Shemesh wrote:
>> [...]
>> test.d(19): Error: cannot convert &S to const(ubyte*) at compile time
>> [...]
>> Thank you,
>> Shachar
> 
> The problem seems to be that cast is happening at compile time, as opposed to run time, as you might have already figured out. Do you need to really do this cast at compile time? I tried running the snippet you gave here: https://run.dlang.io/is/im19nL
> 
> Is this how you intend for it to be used? Then there's no need for compile time casts. If not, could you give an example of how `NoCopy` would be used?

struct Disabled {
  int i = 17;

  @disable this(this);
}

struct Container {
  NoCopy!Disabled disabled;
}

Any instance you create of "Container" will have i initialized to 0 by default.
April 15, 2018
On Thursday, 12 April 2018 at 17:09:22 UTC, Shachar Shemesh wrote:
> On 12/04/18 18:42, Uknown wrote:
>> On Thursday, 12 April 2018 at 12:16:53 UTC, Shachar Shemesh wrote:
>>> [...]
>> 
>> The problem seems to be that cast is happening at compile time, as opposed to run time, as you might have already figured out. Do you need to really do this cast at compile time? I tried running the snippet you gave here: https://run.dlang.io/is/im19nL
>> 
>> Is this how you intend for it to be used? Then there's no need for compile time casts. If not, could you give an example of how `NoCopy` would be used?
>
> struct Disabled {
>   int i = 17;
>
>   @disable this(this);
> }
>
> struct Container {
>   NoCopy!Disabled disabled;
> }
>
> Any instance you create of "Container" will have i initialized to 0 by default.

Since `T` has the postblit disabled, I'm guessing the ctor should take a `ref T`.

Since `T` has the postblit disabled, I'm guessing the ctor should take a `ref T`.