Inferno
0.2
|
00001 /* 00002 * shared_ptr.hpp 00003 * 00004 * Created on: 9 Jun 2010 00005 * Author: jgraley 00006 */ 00007 00008 #ifndef SHARED_PTR_HPP 00009 #define SHARED_PTR_HPP 00010 00011 #include "common/common.hpp" 00012 #include "common/magic.hpp" 00013 00014 // Covariant NULL pointer bug 00015 // 00016 // JSG: There's an unfortunate bug in GCC 3.4.4 on cygwin whereby a covariant return thunk 00017 // for a pointer goes wrong when the pointer is NULL. We can end up dereferencing a NULL (or offset-from-NULL) 00018 // pointer inside the thunk itself which is opaque code, not a lot of fun overall. 00019 // 00020 // It seems to be OK on GCC4 on Linux, and c++/20746 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20746) seems to have a fix, 00021 // but I think it only applies to GCC4 (4.0.2 and 4.1). 00022 // 00023 // So I've just hacked covariant returns to not be covariant whenever I get a problem (just returns same as 00024 // base class, is this "isovariant"?) 00025 // 00026 00027 // Shared pointer wrapper with OO support 00028 00029 namespace OOStd { 00030 00031 template<typename SUB_BASE, typename VALUE_INTERFACE, typename VALUE_TYPE> 00032 struct SharedPtr; 00033 00034 // An interface for our SharedPtr object. This interface works regardless of pointed-to 00035 // type; it also masquerades as a SharedPtr to the VALUE_INTERFACE type, which should be the 00036 // base class of the pointed-to things. 00037 template<typename SUB_BASE, typename VALUE_INTERFACE> 00038 struct SharedPtrInterface : virtual SUB_BASE, public Traceable 00039 { 00040 // Convert to and from shared_ptr<VALUE_INTERFACE> and SharedPtr<VALUE_INTERFACE> 00041 virtual operator shared_ptr<VALUE_INTERFACE>() const = 0; 00042 virtual operator SharedPtr<SUB_BASE, VALUE_INTERFACE, VALUE_INTERFACE>() const = 0; 00043 00044 virtual operator bool() const = 0; // for testing against NULL 00045 virtual VALUE_INTERFACE *get() const = 0; // As per shared_ptr<>, ie gets the actual C pointer 00046 virtual VALUE_INTERFACE &operator *() const = 0; 00047 virtual SharedPtrInterface &operator=( const SharedPtrInterface &o ) 00048 { 00049 (void)SUB_BASE::operator=( o ); // vital for itemiser! 00050 (void)Traceable::operator=( o ); 00051 return *this; 00052 } 00053 virtual SharedPtr<SUB_BASE, VALUE_INTERFACE, VALUE_INTERFACE> MakeValueArchitype() const = 0; // construct an object of the VALUE_TYPE type (NOT a clone 00054 // of the object we're pointing to) 00055 }; 00056 00057 template<typename SUB_BASE, typename VALUE_INTERFACE, typename VALUE_TYPE> 00058 struct SharedPtr : virtual SharedPtrInterface<SUB_BASE, VALUE_INTERFACE>, shared_ptr<VALUE_TYPE> 00059 { 00060 inline SharedPtr() {} 00061 00062 inline SharedPtr( VALUE_TYPE *o ) : 00063 shared_ptr<VALUE_TYPE>( o ) 00064 { 00065 } 00066 00067 template< typename OTHER > 00068 inline SharedPtr( const shared_ptr<OTHER> &o ) : 00069 shared_ptr<VALUE_TYPE>( o ) 00070 { 00071 } 00072 00073 template< typename OTHER > 00074 inline SharedPtr( const SharedPtr<SUB_BASE, VALUE_INTERFACE, OTHER> &o ) : 00075 shared_ptr<VALUE_TYPE>( (shared_ptr<OTHER>)(o) ) 00076 { 00077 } 00078 00079 virtual operator shared_ptr<VALUE_INTERFACE>() const 00080 { 00081 const shared_ptr<VALUE_TYPE> p = (const shared_ptr<VALUE_TYPE>)*this; 00082 return p; 00083 } 00084 00085 virtual operator SharedPtr<SUB_BASE, VALUE_INTERFACE, VALUE_INTERFACE>() const 00086 { 00087 const shared_ptr<VALUE_TYPE> p1 = *(const shared_ptr<VALUE_TYPE> *)this; 00088 return SharedPtr<SUB_BASE, VALUE_INTERFACE, VALUE_INTERFACE>( p1 ); 00089 } 00090 00091 00092 virtual VALUE_TYPE *get() const 00093 { 00094 VALUE_TYPE *e = shared_ptr<VALUE_TYPE>::get(); 00095 //TRACE("sp::get() returns %p\n", e ); 00096 return e; 00097 } 00098 00099 virtual VALUE_TYPE &operator *() const 00100 { 00101 return shared_ptr<VALUE_TYPE>::operator *(); 00102 } 00103 00104 virtual SharedPtr &operator=( shared_ptr<VALUE_INTERFACE> n ) 00105 { 00106 if( n ) 00107 { 00108 shared_ptr<VALUE_TYPE> p = dynamic_pointer_cast<VALUE_TYPE>(shared_ptr<VALUE_INTERFACE>(n)); 00109 ASSERT( p )("OOStd inferred dynamic cast has failed: from ")(*n) 00110 (" to type ")(Traceable::CPPFilt( typeid( VALUE_TYPE ).name() ))("\n"); 00111 (void)shared_ptr<VALUE_TYPE>::operator=( p ); 00112 } 00113 else 00114 { 00115 (void)shared_ptr<VALUE_TYPE>::operator=( shared_ptr<VALUE_TYPE>() ); 00116 } 00117 return *this; 00118 } 00119 00120 template< typename OTHER > 00121 inline SharedPtr &operator=( SharedPtr<SUB_BASE, VALUE_INTERFACE, OTHER> n ) 00122 { 00123 (void)operator=( shared_ptr<OTHER>(n) ); 00124 return *this; 00125 } 00126 00127 virtual SharedPtr &operator=( const SharedPtrInterface<SUB_BASE, VALUE_INTERFACE> &n ) 00128 { 00129 (void)operator=( shared_ptr<VALUE_INTERFACE>(n) ); 00130 return *this; 00131 } 00132 00133 virtual operator bool() const 00134 { 00135 return !!*(const shared_ptr<VALUE_TYPE> *)this; 00136 } 00137 00138 static inline SharedPtr<SUB_BASE, VALUE_INTERFACE, VALUE_TYPE> 00139 DynamicCast( const SharedPtrInterface<SUB_BASE, VALUE_INTERFACE> &g ) 00140 { 00141 if( g ) 00142 { 00143 shared_ptr<VALUE_TYPE> v = dynamic_pointer_cast<VALUE_TYPE>(shared_ptr<VALUE_INTERFACE>(g)); 00144 return SharedPtr<SUB_BASE, VALUE_INTERFACE, VALUE_TYPE>(v); 00145 } 00146 else 00147 { 00148 return SharedPtr<SUB_BASE, VALUE_INTERFACE, VALUE_TYPE>(); 00149 } 00150 } 00151 // For when OOStd itself needs to dyncast, as opposed to the user asking for it. 00152 static inline SharedPtr<SUB_BASE, VALUE_INTERFACE, VALUE_TYPE> 00153 InferredDynamicCast( const SharedPtrInterface<SUB_BASE, VALUE_INTERFACE> &g ) 00154 { 00155 if( g ) 00156 { 00157 shared_ptr<VALUE_TYPE> v = dynamic_pointer_cast<VALUE_TYPE>(shared_ptr<VALUE_INTERFACE>(g)); 00158 ASSERT( v )("OOStd inferred dynamic cast has failed: from ")(*g) 00159 (" to type ")(Traceable::CPPFilt( typeid( VALUE_TYPE ).name() ))("\n"); 00160 return SharedPtr<SUB_BASE, VALUE_INTERFACE, VALUE_TYPE>(v); 00161 } 00162 else 00163 { 00164 // Null came in, null goes out. 00165 return SharedPtr<SUB_BASE, VALUE_INTERFACE, VALUE_TYPE>(); 00166 } 00167 } 00168 virtual SharedPtr<SUB_BASE, VALUE_INTERFACE, VALUE_INTERFACE> MakeValueArchitype() const 00169 { 00170 ASSERTFAIL("MakeValueArchitype() not implemented for this SharedPtr\n"); 00171 } 00172 }; 00173 00174 // Similar signature to boost shared_ptr operator==, and we restrict the pointers 00175 // to having the same subbase and base target 00176 template< typename SUB_BASE, typename VALUE_INTERFACE, typename X, typename Y > 00177 inline bool operator==( const SharedPtr<SUB_BASE, VALUE_INTERFACE, X> &x, 00178 const SharedPtr<SUB_BASE, VALUE_INTERFACE, Y> &y) 00179 { 00180 return operator==( (const shared_ptr<X> &)x, (const shared_ptr<Y> &)y ); 00181 } 00182 00183 // Similar signature to boost shared_ptr operator==, and we restrict the pointers 00184 // to having the same subbase and base target 00185 template< typename SUB_BASE, typename VALUE_INTERFACE > 00186 inline bool operator==( const SharedPtrInterface<SUB_BASE, VALUE_INTERFACE> &x, 00187 const SharedPtrInterface<SUB_BASE, VALUE_INTERFACE> &y) 00188 { 00189 return x.get() == y.get(); 00190 } 00191 00192 template< typename SUB_BASE, typename VALUE_INTERFACE, typename X, typename Y > 00193 inline bool operator!=( const SharedPtr<SUB_BASE, VALUE_INTERFACE, X> &x, 00194 const SharedPtr<SUB_BASE, VALUE_INTERFACE, Y> &y) 00195 { 00196 return operator!=( (const shared_ptr<X> &)x, (const shared_ptr<Y> &)y ); 00197 } 00198 00199 }; // namespace 00200 00201 #endif /* SHARED_PTR_HPP */