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