blocxx
|
00001 /******************************************************************************* 00002 * Copyright (C) 2005, Vintela, Inc. All rights reserved. 00003 * Copyright (C) 2006, Novell, Inc. All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * * Redistributions of source code must retain the above copyright notice, 00009 * this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Neither the name of 00014 * Vintela, Inc., 00015 * nor Novell, Inc., 00016 * nor the names of its contributors or employees may be used to 00017 * endorse or promote products derived from this software without 00018 * specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00021 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00022 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00023 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00024 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00025 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00026 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00029 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00030 * POSSIBILITY OF SUCH DAMAGE. 00031 *******************************************************************************/ 00032 00033 00039 #ifndef BLOCXX_REFERENCE_HPP_ 00040 #define BLOCXX_REFERENCE_HPP_ 00041 #include "blocxx/BLOCXX_config.h" 00042 #include "blocxx/ReferenceBase.hpp" 00043 #include "blocxx/ReferenceHelpers.hpp" 00044 #include "blocxx/SafeBool.hpp" 00045 00046 namespace BLOCXX_NAMESPACE 00047 { 00048 00050 template<class T> 00051 class Reference : 00052 #if !defined(__GNUC__) || __GNUC__ > 2 // because of a gcc 2.95 ICE 00053 private ReferenceBase 00054 #else 00055 public ReferenceBase 00056 #endif 00057 { 00058 public: 00059 typedef T element_type; 00060 00061 Reference(); 00062 explicit Reference(T* ptr); 00063 Reference(const Reference<T>& arg); 00064 00065 /* construct out of a reference to a derived type. U should be 00066 derived from T */ 00067 template <class U> 00068 Reference(const Reference<U>& arg); 00069 ~Reference(); 00070 Reference<T>& operator= (const Reference<T>& arg); 00071 Reference<T>& operator= (T* newObj); 00072 void swap(Reference<T>& arg); 00073 T* operator->() const; 00074 T& operator*() const; 00075 T* getPtr() const; 00076 bool isNull() const BLOCXX_DEPRECATED; // in 3.1.0 00077 00078 BLOCXX_SAFE_BOOL_IMPL(Reference, T* volatile, Reference::m_pObj, m_pObj) 00079 00080 template <class U> 00081 Reference<U> cast_to() const; 00082 template <class U> 00083 void useRefCountOf(const Reference<U>&); 00084 #if !defined(__GNUC__) || __GNUC__ > 2 // causes gcc 2.95 to ICE 00085 /* This is so the templated constructor will work */ 00086 template <class U> friend class Reference; 00087 private: 00088 #endif 00089 void decRef(); 00090 T* volatile m_pObj; 00091 }; 00093 template<class T> 00094 inline Reference<T>::Reference() 00095 : ReferenceBase(), m_pObj(0) 00096 { 00097 } 00099 template<class T> 00100 inline Reference<T>::Reference(T* ptr) 00101 : ReferenceBase(), m_pObj(ptr) 00102 { 00103 } 00105 template<class T> 00106 inline Reference<T>::Reference(const Reference<T>& arg) 00107 : ReferenceBase(arg), m_pObj(arg.m_pObj) 00108 { 00109 } 00111 template<class T> 00112 template<class U> 00113 inline Reference<T>::Reference(const Reference<U>& arg) 00114 : ReferenceBase(arg), 00115 m_pObj(arg.m_pObj) 00116 { 00117 } 00119 template<class T> 00120 inline Reference<T>::~Reference() 00121 { 00122 // we don't catch(...) here because nothing we do will throw, and any 00123 // class we wrap should have a non-throwing destructor. 00124 decRef(); 00125 } 00127 template<class T> 00128 inline void Reference<T>::decRef() 00129 { 00130 typedef char type_must_be_complete[sizeof(T)]; 00131 if (ReferenceBase::decRef()) 00132 { 00133 delete m_pObj; 00134 } 00135 } 00137 template<class T> 00138 inline Reference<T>& Reference<T>::operator= (const Reference<T>& arg) 00139 { 00140 Reference<T>(arg).swap(*this); 00141 return *this; 00142 } 00144 template<class T> 00145 inline Reference<T>& Reference<T>::operator= (T* newObj) 00146 { 00147 Reference<T>(newObj).swap(*this); 00148 return *this; 00149 } 00151 template <class T> 00152 inline void Reference<T>::swap(Reference<T>& arg) 00153 { 00154 ReferenceBase::swap(arg); 00155 RefSwap(m_pObj, arg.m_pObj); 00156 } 00158 template<class T> 00159 inline T* Reference<T>::operator->() const 00160 { 00161 #ifdef BLOCXX_CHECK_NULL_REFERENCES 00162 ReferenceHelpers::checkNull(this); 00163 ReferenceHelpers::checkNull(m_pObj); 00164 #endif 00165 00166 return m_pObj; 00167 } 00169 template<class T> 00170 inline T& Reference<T>::operator*() const 00171 { 00172 #ifdef BLOCXX_CHECK_NULL_REFERENCES 00173 ReferenceHelpers::checkNull(this); 00174 ReferenceHelpers::checkNull(m_pObj); 00175 #endif 00176 00177 return *(m_pObj); 00178 } 00180 template<class T> 00181 inline T* Reference<T>::getPtr() const 00182 { 00183 return m_pObj; 00184 } 00186 template<class T> 00187 inline bool Reference<T>::isNull() const 00188 { 00189 return (m_pObj == 0); 00190 } 00192 template <class T> 00193 template <class U> 00194 inline Reference<U> 00195 Reference<T>::cast_to() const 00196 { 00197 Reference<U> rval; 00198 rval.m_pObj = dynamic_cast<U*>(m_pObj); 00199 if (rval.m_pObj) 00200 { 00201 rval.useRefCountOf(*this); 00202 } 00203 return rval; 00204 } 00206 template <class T> 00207 template <class U> 00208 inline void 00209 Reference<T>::useRefCountOf(const Reference<U>& arg) 00210 { 00211 ReferenceBase::useRefCountOf(arg); 00212 } 00214 // Comparisons 00215 template <class T, class U> 00216 inline bool operator==(const Reference<T>& a, const Reference<U>& b) 00217 { 00218 return a.getPtr() == b.getPtr(); 00219 } 00221 template <class T, class U> 00222 inline bool operator!=(const Reference<T>& a, const Reference<U>& b) 00223 { 00224 return a.getPtr() != b.getPtr(); 00225 } 00227 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 00228 // Resolve the ambiguity between our op!= and the one in rel_ops 00229 template <class T> 00230 inline bool operator!=(const Reference<T>& a, const Reference<T>& b) 00231 { 00232 return a.getPtr() != b.getPtr(); 00233 } 00234 #endif 00235 00236 template <class T, class U> 00237 inline bool operator<(const Reference<T>& a, const Reference<U>& b) 00238 { 00239 return a.getPtr() < b.getPtr(); 00240 } 00241 00242 } // end namespace BLOCXX_NAMESPACE 00243 00244 #endif // BLOCXX_REFERENCE_HPP_