blocxx
Reference.hpp
Go to the documentation of this file.
1 /*******************************************************************************
2 * Copyright (C) 2005, Vintela, Inc. All rights reserved.
3 * Copyright (C) 2006, Novell, Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of
14 * Vintela, Inc.,
15 * nor Novell, Inc.,
16 * nor the names of its contributors or employees may be used to
17 * endorse or promote products derived from this software without
18 * specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *******************************************************************************/
32 
33 
39 #ifndef BLOCXX_REFERENCE_HPP_
40 #define BLOCXX_REFERENCE_HPP_
41 #include "blocxx/BLOCXX_config.h"
42 #include "blocxx/ReferenceBase.hpp"
44 #include "blocxx/SafeBool.hpp"
45 
46 namespace BLOCXX_NAMESPACE
47 {
48 
50 template<class T>
51 class Reference :
52 #if !defined(__GNUC__) || __GNUC__ > 2 // because of a gcc 2.95 ICE
53  private ReferenceBase
54 #else
55  public ReferenceBase
56 #endif
57 {
58  public:
59  typedef T element_type;
60 
61  Reference();
62  explicit Reference(T* ptr);
63  Reference(const Reference<T>& arg);
64 
65  /* construct out of a reference to a derived type. U should be
66  derived from T */
67  template <class U>
68  Reference(const Reference<U>& arg);
69  ~Reference();
71  Reference<T>& operator= (T* newObj);
72  void swap(Reference<T>& arg);
73  T* operator->() const;
74  T& operator*() const;
75  T* getPtr() const;
76  bool isNull() const BLOCXX_DEPRECATED; // in 3.1.0
77 
78  BLOCXX_SAFE_BOOL_IMPL(Reference, T* volatile, Reference::m_pObj, m_pObj)
79 
80  template <class U>
81  Reference<U> cast_to() const;
82  template <class U>
83  void useRefCountOf(const Reference<U>&);
84 #if !defined(__GNUC__) || __GNUC__ > 2 // causes gcc 2.95 to ICE
85  /* This is so the templated constructor will work */
86  template <class U> friend class Reference;
87  private:
88 #endif
89  void decRef();
90  T* volatile m_pObj;
91 };
93 template<class T>
95  : ReferenceBase(), m_pObj(0)
96 {
97 }
99 template<class T>
101  : ReferenceBase(), m_pObj(ptr)
102 {
103 }
105 template<class T>
107  : ReferenceBase(arg), m_pObj(arg.m_pObj)
108 {
109 }
111 template<class T>
112 template<class U>
114  : ReferenceBase(arg),
115  m_pObj(arg.m_pObj)
116 {
117 }
119 template<class T>
121 {
122  // we don't catch(...) here because nothing we do will throw, and any
123  // class we wrap should have a non-throwing destructor.
124  decRef();
125 }
127 template<class T>
128 inline void Reference<T>::decRef()
129 {
130  typedef char type_must_be_complete[sizeof(T)];
131  if (ReferenceBase::decRef())
132  {
133  delete m_pObj;
134  }
135 }
137 template<class T>
139 {
140  Reference<T>(arg).swap(*this);
141  return *this;
142 }
144 template<class T>
146 {
147  Reference<T>(newObj).swap(*this);
148  return *this;
149 }
151 template <class T>
153 {
154  ReferenceBase::swap(arg);
155  RefSwap(m_pObj, arg.m_pObj);
156 }
158 template<class T>
159 inline T* Reference<T>::operator->() const
160 {
161 #ifdef BLOCXX_CHECK_NULL_REFERENCES
162  ReferenceHelpers::checkNull(this);
163  ReferenceHelpers::checkNull(m_pObj);
164 #endif
165 
166  return m_pObj;
167 }
169 template<class T>
170 inline T& Reference<T>::operator*() const
171 {
172 #ifdef BLOCXX_CHECK_NULL_REFERENCES
173  ReferenceHelpers::checkNull(this);
174  ReferenceHelpers::checkNull(m_pObj);
175 #endif
176 
177  return *(m_pObj);
178 }
180 template<class T>
181 inline T* Reference<T>::getPtr() const
182 {
183  return m_pObj;
184 }
186 template<class T>
187 inline bool Reference<T>::isNull() const
188 {
189  return (m_pObj == 0);
190 }
192 template <class T>
193 template <class U>
194 inline Reference<U>
196 {
197  Reference<U> rval;
198  rval.m_pObj = dynamic_cast<U*>(m_pObj);
199  if (rval.m_pObj)
200  {
201  rval.useRefCountOf(*this);
202  }
203  return rval;
204 }
206 template <class T>
207 template <class U>
208 inline void
210 {
212 }
214 // Comparisons
215 template <class T, class U>
216 inline bool operator==(const Reference<T>& a, const Reference<U>& b)
217 {
218  return a.getPtr() == b.getPtr();
219 }
221 template <class T, class U>
222 inline bool operator!=(const Reference<T>& a, const Reference<U>& b)
223 {
224  return a.getPtr() != b.getPtr();
225 }
227 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
228 // Resolve the ambiguity between our op!= and the one in rel_ops
229 template <class T>
230 inline bool operator!=(const Reference<T>& a, const Reference<T>& b)
231 {
232  return a.getPtr() != b.getPtr();
233 }
234 #endif
235 
236 template <class T, class U>
237 inline bool operator<(const Reference<T>& a, const Reference<U>& b)
238 {
239  return a.getPtr() < b.getPtr();
240 }
241 
242 } // end namespace BLOCXX_NAMESPACE
243 
244 #endif // BLOCXX_REFERENCE_HPP_