Disabled and enabled copy constructors and .dup

Biotronic simen.kjaras at gmail.com
Tue Oct 24 12:06:54 UTC 2017


On Tuesday, 24 October 2017 at 11:37:42 UTC, Per Nordlöw wrote:
> On Tuesday, 24 October 2017 at 07:56:34 UTC, Biotronic wrote:
>> struct SuppressPostblit(T)
>> {
>>     // Disguise T as a humble array.
>>     private ubyte[T.sizeof] _payload;
>> ...
>
> A bit too hackish for my taste, but does the job still.
>
> Thanks.

Cleaned up and slightly less hackish (yeah, it bothered me too):

enum SuppressOptions {
     destructor = 1,
     postblit = 2
}

struct Suppress(T, SuppressOptions options) if (options != 0)
{
     import std.traits : isCopyable;
     private enum suppressPostblit   = (options & 
SuppressOptions.postblit)   != 0;
     private enum suppressDestructor = (options & 
SuppressOptions.destructor) != 0;
     private enum postblitName = __traits(hasMember, T, 
"__xpostblit") ? "__xpostblit" : "__postblit";

     // Disguise T as a humble array.
     private ubyte[T.sizeof] _payload;

     // Create from instance of T.
     this(T arg) {
         _payload = *cast(ubyte[T.sizeof]*)&arg;
     }

     // Or forward constructor arguments to T's constructor.
     static if (__traits(hasMember, T, "__ctor"))
     {
         this(Args...)(Args args)
             if (__traits(compiles, (Args e){__traits(getMember, 
T.init, "__ctor")(e);}))
         {
             __traits(getMember, get, "__ctor")(args);
         }
     }

     // Call dtor
     static if (!suppressDestructor) {
         ~this() {
             destroy(get);
         }
     }

     // Call postblit
     static if (!suppressPostblit) {
         static if (!isCopyable!T) {
             @disable this(this);
         } else static if (__traits(hasMember, T, postblitName)) {
             this(this) {
                 __traits(getMember, get, postblitName)();
             }
         }
     }

     // Pretend to be a T.
     @property
     ref T get()
     {
         return *cast(T*)_payload.ptr;
     }

     alias get this;
}

struct S1 {
     @disable this(this);
     ~this() {
         throw new Exception("Don't touch my destructor!");
     }
}

unittest {
     import std.exception;
     static assert(!__traits(compiles, (Suppress!S1 a) { auto b = 
a; }));
     static assert(__traits(compiles, (Suppress!(S1, 
SuppressOptions.postblit) a) { auto b = a; }));

     assertThrown({ Suppress!(S1, SuppressOptions.postblit) a; 
}());
     assertNotThrown({ Suppress!(S1, SuppressOptions.postblit | 
SuppressOptions.destructor) a; }());
}

--
   Biotronic


More information about the Digitalmars-d-learn mailing list