1 module lwdr.unique; 2 3 pragma(LDC_no_moduleinfo); 4 5 import lwdr.util.traits; 6 import lwdr : LWDR; 7 8 /++ Check if T is suitable for a unique pointer. 9 T must be a class, interface, pointer or dynamic array. ++/ 10 enum isSuitableForUnique(T) = 11 is(T == class) || 12 is(T == interface) || 13 is(T == U*, U) || 14 is(T == U[], U); 15 16 /++ A unique pointer. Only one pointer to a target may exist at a time. 17 Pointers can be explicitly moved, but not copied. ++/ 18 struct Unique(T) 19 if(isSuitableForUnique!T) 20 { 21 @disable this(this); /// Disable copy semantics 22 23 T payload; /// Payload 24 alias payload this; 25 26 /// Assign a payload to this unique pointer 27 this(T t) 28 { 29 payload = t; 30 } 31 32 /// Allocate the payload 33 this(Args...)(auto ref Args args) 34 { 35 static if(is(T == class)) 36 payload = new T(args); 37 static if(is(T == U*, U)) 38 { 39 alias root = rootType!T; 40 static if(is(root == struct) || is(root == union)) 41 payload = new root(args); 42 else 43 { 44 payload = new root; 45 *payload = args[0]; 46 } 47 } 48 static if(is(T == U[], U)) 49 { 50 alias root = rootType!T; 51 payload = [args]; 52 } 53 } 54 55 ~this() 56 { 57 if(payload !is null) 58 { 59 LWDR.free(payload); 60 payload = null; 61 } 62 } 63 64 /// Move to a new instance 65 Unique move() 66 { 67 Unique ret; 68 ret.payload = this.payload; 69 this.payload = null; 70 return ret; 71 } 72 73 /// Borrow the pointer 74 inout auto borrow() @system { return payload; } 75 76 /// Check if this unique instance has a payload 77 @property auto bool hasPayload() const 78 { return payload !is null; } 79 80 /// ditto. 81 auto opCast(CastTarget)() if(is(CastTarget == bool)) 82 { return hasPayload; } 83 }