1 // Copyright (c) 2012-2014 Konstantin Isakov <ikm@zbackup.org> and ZBackup contributors, see CONTRIBUTORS 2 // Part of ZBackup. Licensed under GNU GPLv2 or later + OpenSSL, see LICENSE 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( nullptr ), count( nullptr ) {} 29 sptr_base(T * p_)30 sptr_base( T * p_ ): p( p_ ), count( p ? new unsigned( 1 ) : nullptr ) 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 = nullptr; 52 53 if ( p ) 54 { 55 T * p_ = p; 56 57 p = nullptr; 58 59 delete p_; 60 } 61 } 62 else 63 { 64 p = nullptr; 65 count = nullptr; 66 } 67 } 68 } 69 use_count() const70 unsigned use_count() const 71 { return *count; } 72 operator =(sptr_base const & other)73 sptr_base & operator = ( sptr_base const & other ) 74 { if ( &other != this ) { reset(); p = other.p; count = other.count; increment(); } 75 return * this; } 76 operator bool(void) const77 operator bool( void ) const 78 { return !!p; } 79 operator !(void) const80 bool operator ! ( void ) const 81 { return !p; } 82 operator ==(sptr_base const & other) const83 bool operator == ( sptr_base const & other ) const 84 { return p == other.p; } 85 operator !=(sptr_base const & other) const86 bool operator != ( sptr_base const & other ) const 87 { return p != other.p; } 88 ~sptr_base()89 ~sptr_base() 90 { reset(); } 91 92 protected: 93 get_base(void) const94 T * get_base( void ) const 95 { return p; } 96 }; 97 98 template< class T > 99 class sptr: public sptr_base< T > 100 { 101 public: 102 sptr()103 sptr() {} 104 sptr(T * p)105 sptr( T * p ): sptr_base< T >( p ) {} 106 107 // TT is meant to be a derivative of T 108 template< class TT > sptr(sptr<TT> const & other)109 sptr( sptr< TT > const & other ): sptr_base< T >( other ) {} 110 111 // Retrieval 112 get(void) const113 T * get( void ) const 114 { return sptr_base< T > :: get_base(); } 115 operator ->(void) const116 T * operator -> ( void ) const 117 { return get(); } 118 operator *(void) const119 T & operator * ( void ) const 120 { return * get(); } 121 122 // Check 123 operator bool(void) const124 operator bool( void ) const 125 { return get(); } 126 operator !(void) const127 bool operator ! ( void ) const 128 { return !get(); } 129 }; 130 131 template< class T > 132 class const_sptr: public sptr_base< T > 133 { 134 public: 135 const_sptr()136 const_sptr() {} 137 const_sptr(T * p_)138 const_sptr( T * p_ ): sptr_base< T >( p_ ) {} 139 const_sptr(sptr<T> const & other)140 const_sptr( sptr< T > const & other ): sptr_base< T >( other ) {} 141 142 // TT is meant to be a derivative of T 143 template< class TT > const_sptr(sptr_base<TT> const & other)144 const_sptr( sptr_base< TT > const & other ): sptr_base< T >( other ) {} 145 146 // Retrieval 147 get(void) const148 T const * get( void ) const 149 { return sptr_base< T > :: get_base(); } 150 operator ->(void) const151 T const * operator -> ( void ) const 152 { return get(); } 153 operator *(void) const154 T const & operator * ( void ) const 155 { return * get(); } 156 }; 157 158 159 #endif 160