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