1 module dpq.smartptr; 2 3 import dpq.exception; 4 5 version(unittest) 6 { 7 int nFrees = 0; 8 void fakeFree(T)(T* val) 9 { 10 ++nFrees; 11 } 12 } 13 14 class SmartPointer(T, alias _free) 15 { 16 private T _ptr; 17 18 alias get this; 19 20 this() 21 { 22 _ptr = null; 23 } 24 25 this(T ptr) 26 { 27 _ptr = ptr; 28 } 29 30 ~this() 31 { 32 clear(); 33 } 34 35 @property T get() 36 { 37 if (_ptr == null) 38 throw new DPQException("get called on a null SmartPointer!(" ~ T.stringof ~ ")"); 39 return _ptr; 40 } 41 42 @property bool isNull() 43 { 44 return _ptr == null; 45 } 46 47 void opAssign(typeof(null) n) 48 { 49 clear(); 50 } 51 52 void opAssign(T ptr) 53 { 54 if (ptr == _ptr) 55 return; 56 57 clear(); 58 _ptr = ptr; 59 } 60 61 void clear() 62 { 63 if (_ptr == null) 64 return; 65 66 _free(_ptr); 67 68 _ptr = null; 69 } 70 } 71 72 unittest 73 { 74 import std.stdio; 75 76 writeln(" * SmartPointer"); 77 78 alias Ptr = SmartPointer!(ubyte*, fakeFree); 79 80 ubyte* p = new ubyte; 81 *p = 2; 82 auto sp = new Ptr; 83 84 assert(sp._ptr == null); 85 86 sp = p; 87 assert(sp._ptr == p); 88 89 // assign the same ptr 90 sp = p; 91 assert(nFrees == 0); 92 assert(!sp.isNull); 93 assert(sp._ptr == p); 94 95 ubyte* p2 = new ubyte; 96 *p2 = 255; 97 98 sp = p2; 99 assert(nFrees == 1); 100 assert(sp._ptr == p2); 101 102 sp = new Ptr(p2); 103 assert(sp._ptr == p2); 104 105 sp.clear(); 106 assert(sp.isNull); 107 assert(sp._ptr == null); 108 } 109