1 /* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org> 2 * Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */ 3 4 #ifndef __SPTR_HH_INCLUDED__ 5 #define __SPTR_HH_INCLUDED__ 6 7 // A generic non-intrusive smart-pointer template. We could use boost::, tr1:: 8 // or whatever, but since there's no standard solution yet, it isn't worth 9 // the dependency given the simplicity of the template. 10 11 template< class T > 12 class sptr_base 13 { 14 template< class TT > friend class sptr_base; 15 16 T * p; 17 unsigned * count; 18 19 increment()20 void increment() 21 { 22 if ( count ) 23 ++*count; 24 } 25 26 public: 27 sptr_base()28 sptr_base(): p( 0 ), count( 0 ) {} 29 sptr_base(T * p_)30 sptr_base( T * p_ ): p( p_ ), count( p ? new unsigned( 1 ) : 0 ) 31 { 32 } 33 sptr_base(sptr_base<T> const & other)34 sptr_base( sptr_base< T > const & other ): p( other.p ), count( other.count ) 35 { increment(); } 36 37 // TT is meant to be a derivative of T 38 template< class TT > sptr_base(sptr_base<TT> const & other)39 sptr_base( sptr_base< TT > const & other ): p( ( T * ) other.p ), 40 count( other.count ) 41 { increment(); } 42 reset()43 void reset() 44 { 45 if ( count ) 46 { 47 if ( ! -- *count ) 48 { 49 delete count; 50 51 count = 0; 52 53 if ( p ) 54 { 55 T * p_ = p; 56 57 p = 0; 58 59 delete p_; 60 } 61 } 62 else 63 { 64 p = 0; 65 count = 0; 66 } 67 } 68 } 69 operator =(sptr_base const & other)70 sptr_base & operator = ( sptr_base const & other ) 71 { if ( &other != this ) { reset(); p = other.p; count = other.count; increment(); } 72 return * this; } 73 operator !(void) const74 bool operator ! ( void ) const 75 { return !p; } 76 operator ==(sptr_base const & other) const77 bool operator == ( sptr_base const & other ) const 78 { return p == other.p; } 79 operator !=(sptr_base const & other) const80 bool operator != ( sptr_base const & other ) const 81 { return p != other.p; } 82 ~sptr_base()83 ~sptr_base() 84 { reset(); } 85 86 protected: 87 get_base(void) const88 T * get_base( void ) const 89 { return p; } 90 }; 91 92 template< class T > 93 class sptr: public sptr_base< T > 94 { 95 public: 96 sptr()97 sptr() {} 98 sptr(T * p)99 sptr( T * p ): sptr_base< T >( p ) {} 100 101 // TT is meant to be a derivative of T 102 template< class TT > sptr(sptr<TT> const & other)103 sptr( sptr< TT > const & other ): sptr_base< T >( other ) {} 104 105 // Retrieval 106 get(void) const107 T * get( void ) const 108 { return sptr_base< T > :: get_base(); } 109 operator ->(void) const110 T * operator -> ( void ) const 111 { return get(); } 112 operator *(void) const113 T & operator * ( void ) const 114 { return * get(); } 115 116 // Check 117 operator bool(void) const118 operator bool( void ) const 119 { return get(); } 120 operator !(void) const121 bool operator ! ( void ) const 122 { return !get(); } 123 }; 124 125 template< class T > 126 class const_sptr: public sptr_base< T > 127 { 128 public: 129 const_sptr()130 const_sptr() {} 131 const_sptr(T * p_)132 const_sptr( T * p_ ): sptr_base< T >( p_ ) {} 133 const_sptr(sptr<T> const & other)134 const_sptr( sptr< T > const & other ): sptr_base< T >( other ) {} 135 136 // TT is meant to be a derivative of T 137 template< class TT > const_sptr(sptr_base<TT> const & other)138 const_sptr( sptr_base< TT > const & other ): sptr_base< T >( other ) {} 139 140 // Retrieval 141 get(void) const142 T const * get( void ) const 143 { return sptr_base< T > :: get_base(); } 144 operator ->(void) const145 T const * operator -> ( void ) const 146 { return get(); } 147 operator *(void) const148 T const & operator * ( void ) const 149 { return * get(); } 150 }; 151 152 153 #endif 154 155