1 /* 2 3 Copyright (C) 2011 Grame 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 19 Grame Research Laboratory, 9 rue du Garet, 69001 Lyon - France 20 research@grame.fr 21 22 */ 23 24 #ifndef __smartpointer__ 25 #define __smartpointer__ 26 27 #include <cassert> 28 29 /*! 30 \brief the base class for smart pointers implementation 31 32 Any object that want to support smart pointers should 33 inherit from the smartable class which provides reference counting 34 and automatic delete when the reference count drops to zero. 35 */ 36 class smartable { 37 private: 38 unsigned refCount; 39 public: 40 //! gives the reference count of the object refs()41 unsigned refs() const { return refCount; } 42 //! addReference increments the ref count and checks for refCount overflow addReference()43 void addReference() { refCount++; assert(refCount != 0); } 44 //! removeReference delete the object when refCount is zero removeReference()45 void removeReference() { if (--refCount == 0) delete this; } 46 47 protected: smartable()48 smartable() : refCount(0) {} smartable(const smartable &)49 smartable(const smartable&): refCount(0) {} 50 //! destructor checks for non-zero refCount ~smartable()51 virtual ~smartable() 52 { 53 //printf(" ~smartable() \n"); 54 //assert (refCount == 0); 55 } 56 smartable& operator=(const smartable&) { return *this; } 57 }; 58 59 /*! 60 \brief the smart pointer implementation 61 62 A smart pointer is in charge of maintaining the objects reference count 63 by the way of pointers operators overloading. It supports class 64 inheritance and conversion whenever possible. 65 \n Instances of the SMARTP class are supposed to use \e smartable types (or at least 66 objects that implements the \e addReference and \e removeReference 67 methods in a consistent way). 68 */ 69 template<class T> class SMARTP { 70 private: 71 //! the actual pointer to the class 72 T* fSmartPtr; 73 74 public: 75 //! an empty constructor - points to null SMARTP()76 SMARTP() : fSmartPtr(0) {} 77 //! build a smart pointer from a class pointer SMARTP(T * rawptr)78 SMARTP(T* rawptr) : fSmartPtr(rawptr) { if (fSmartPtr) fSmartPtr->addReference(); } 79 //! build a smart pointer from an convertible class reference 80 template<class T2> SMARTP(const SMARTP<T2> & ptr)81 SMARTP(const SMARTP<T2>& ptr) : fSmartPtr((T*)ptr) { if (fSmartPtr) fSmartPtr->addReference(); } 82 //! build a smart pointer from another smart pointer reference SMARTP(const SMARTP & ptr)83 SMARTP(const SMARTP& ptr) : fSmartPtr((T*)ptr) { if (fSmartPtr) fSmartPtr->addReference(); } 84 85 //! the smart pointer destructor: simply removes one reference count ~SMARTP()86 ~SMARTP() { if (fSmartPtr) fSmartPtr->removeReference(); } 87 88 //! cast operator to retrieve the actual class pointer 89 operator T*() const { return fSmartPtr; } 90 91 //! '*' operator to access the actual class pointer 92 T& operator*() const { 93 // checks for null dereference 94 assert (fSmartPtr != 0); 95 return *fSmartPtr; 96 } 97 98 //! operator -> overloading to access the actual class pointer 99 T* operator->() const { 100 // checks for null dereference 101 assert (fSmartPtr != 0); 102 return fSmartPtr; 103 } 104 105 //! operator = that moves the actual class pointer 106 template <class T2> 107 SMARTP& operator=(T2 p1_) { *this=(T*)p1_; return *this; } 108 109 //! operator = that moves the actual class pointer 110 SMARTP& operator=(T* p_) { 111 // check first that pointers differ 112 if (fSmartPtr != p_) { 113 // increments the ref count of the new pointer if not null 114 if (p_ != 0) p_->addReference(); 115 // decrements the ref count of the old pointer if not null 116 if (fSmartPtr != 0) fSmartPtr->removeReference(); 117 // and finally stores the new actual pointer 118 fSmartPtr = p_; 119 } 120 return *this; 121 } 122 //! operator < to support SMARTP map with Visual C++ 123 bool operator<(const SMARTP<T>& p_) const { return fSmartPtr < ((T *) p_); } 124 //! operator = to support inherited class reference 125 SMARTP& operator=(const SMARTP<T>& p_) { return operator=((T *) p_); } 126 //! dynamic cast support cast(T2 * p_)127 template<class T2> SMARTP& cast(T2* p_) { return operator=(dynamic_cast<T*>(p_)); } 128 //! dynamic cast support cast(const SMARTP<T2> & p_)129 template<class T2> SMARTP& cast(const SMARTP<T2>& p_) { return operator=(dynamic_cast<T*>(p_)); } 130 }; 131 132 #endif 133