1 /** Various suppressing hacks. 2 */ 3 module nxt.suppressing; 4 5 enum SuppressOptions 6 { 7 destructor = 1, 8 postblit = 2 9 } 10 11 /** Suppress. 12 * 13 * See_Also: http://forum.dlang.org/post/dxakoknmzblxpgiibfmu@forum.dlang.org 14 */ 15 struct Suppress(T, SuppressOptions options) 16 if (options != 0) 17 { 18 private enum suppressPostblit = (options & SuppressOptions.postblit) != 0; 19 private enum suppressDestructor = (options & SuppressOptions.destructor) != 0; 20 private enum postblitName = __traits(hasMember, T, "__xpostblit") ? "__xpostblit" : "__postblit"; 21 22 // Disguise T as a humble array. 23 private ubyte[T.sizeof] _payload; 24 25 // Create from instance of T. 26 this(T arg) 27 { 28 _payload = *cast(ubyte[T.sizeof]*)&arg; 29 } 30 31 // Or forward constructor arguments to T's constructor. 32 static if (__traits(hasMember, T, "__ctor")) 33 { 34 this(Args...)(Args args) 35 if (__traits(compiles, (Args e){__traits(getMember, T.init, "__ctor")(e);})) 36 { 37 __traits(getMember, get, "__ctor")(args); 38 } 39 } 40 41 // Call dtor 42 static if (!suppressDestructor) 43 { 44 ~this() nothrow @nogc 45 { 46 destroy(get); 47 } 48 } 49 50 // Call postblit 51 static if (!suppressPostblit) 52 { 53 static if (!__traits(isCopyable, T)) 54 { 55 this(this) @disable; 56 } 57 else static if (__traits(hasMember, T, postblitName)) 58 { 59 this(this) 60 { 61 __traits(getMember, get, postblitName)(); 62 } 63 } 64 } 65 66 // Pretend to be a T. 67 @property 68 ref T get() 69 { 70 return *cast(T*)_payload.ptr; 71 } 72 73 alias get this; 74 } 75 76 struct S1 77 { 78 this(this) @disable; 79 ~this() nothrow @nogc 80 { 81 assert(0, "Don't touch my destructor!"); 82 } 83 } 84 85 unittest { 86 import std.exception; 87 static assert(!__traits(compiles, (Suppress!S1 a) { auto b = a; })); 88 static assert(__traits(compiles, (Suppress!(S1, SuppressOptions.postblit) a) { auto b = a; })); 89 90 /+ TODO: assertThrown({ Suppress!(S1, SuppressOptions.postblit) a; }()); +/ 91 assertNotThrown({ Suppress!(S1, SuppressOptions.postblit | SuppressOptions.destructor) a; }()); 92 }