blocxx

Reference.hpp

Go to the documentation of this file.
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_