Reference.hpp

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

Generated on Fri Jun 16 15:39:08 2006 for blocxx by  doxygen 1.4.6