ATLAS Offline Software
RefCountedPtr.icc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration.
3  */
4 /**
5  * @file CxxUtils/RefCountedPtr.icc
6  * @author scott snyder <snyder@bnl.gov>
7  * @date Oct, 2025
8  * @brief Simple smart pointer for Gaudi-style refcounted objects.
9  */
10 
11 
12 namespace CxxUtils {
13 
14 
15 /// Constructor from pointer. Adds to the refcount.
16 template <CxxUtils::detail::RefCounted T>
17 inline
18 RefCountedPtr<T>::RefCountedPtr (T* p)
19  : m_ptr (p)
20 {
21  if (m_ptr) m_ptr->addRef();
22 }
23 
24 
25 /// Constructor from unique_ptr. Adds to the refcount.
26 template <CxxUtils::detail::RefCounted T>
27 template <CxxUtils::detail::RefCounted OTHER>
28 requires std::convertible_to<OTHER*, T*>
29 inline
30 RefCountedPtr<T>::RefCountedPtr (std::unique_ptr<OTHER>&& other)
31  : RefCountedPtr (other.release())
32 {
33 }
34 
35 
36 /// Copy constructor.
37 template <CxxUtils::detail::RefCounted T>
38 inline
39 RefCountedPtr<T>::RefCountedPtr (const RefCountedPtr& other)
40  : RefCountedPtr (other.m_ptr)
41 {
42 }
43 
44 
45 /// Move constructor.
46 template <CxxUtils::detail::RefCounted T>
47 inline
48 RefCountedPtr<T>::RefCountedPtr (RefCountedPtr&& other)
49  : m_ptr (other.release())
50 {
51 }
52 
53 
54 /// Constructor from another RefCountedPtr, with a different type.
55 template <CxxUtils::detail::RefCounted T>
56 template <CxxUtils::detail::RefCounted OTHER>
57 requires std::convertible_to<OTHER*, T*>
58 inline
59 RefCountedPtr<T>::RefCountedPtr (const RefCountedPtr<OTHER>& other)
60  : RefCountedPtr (other.m_ptr)
61 {
62 }
63 
64 
65 /// Move from another RefCountedPtr, with a different type.
66 template <CxxUtils::detail::RefCounted T>
67 template <CxxUtils::detail::RefCounted OTHER>
68 requires std::convertible_to<OTHER*, T*>
69 inline
70 RefCountedPtr<T>::RefCountedPtr (RefCountedPtr<OTHER>&& other)
71  : m_ptr (other.release())
72 {
73 }
74 
75 
76 /// Assignment.
77 template <CxxUtils::detail::RefCounted T>
78 inline
79 RefCountedPtr<T>& RefCountedPtr<T>::operator= (const RefCountedPtr& other)
80 {
81  reset (other.m_ptr);
82  return *this;
83 }
84 
85 
86 /// Move.
87 template <CxxUtils::detail::RefCounted T>
88 inline
89 RefCountedPtr<T>& RefCountedPtr<T>::operator= (RefCountedPtr&& other)
90 {
91  if (m_ptr) m_ptr->release();
92  m_ptr = other.release();
93  return *this;
94 }
95 
96 
97 /// Assignment from pointer.
98 template <CxxUtils::detail::RefCounted T>
99 inline
100 RefCountedPtr<T>& RefCountedPtr<T>::operator= (T* p)
101 {
102  reset (p);
103  return *this;
104 }
105 
106 
107 /// Assignment from different type.
108 template <CxxUtils::detail::RefCounted T>
109 template <CxxUtils::detail::RefCounted OTHER>
110 requires std::convertible_to<OTHER*, T*>
111 inline
112 RefCountedPtr<T>& RefCountedPtr<T>::operator= (const RefCountedPtr<OTHER>& other)
113 {
114  reset (other.m_ptr);
115  return *this;
116 }
117 
118 
119 /// Move from different type.
120 template <CxxUtils::detail::RefCounted T>
121 template <CxxUtils::detail::RefCounted OTHER>
122 requires std::convertible_to<OTHER*, T*>
123 inline
124 RefCountedPtr<T>& RefCountedPtr<T>::operator= (RefCountedPtr<OTHER>&& other)
125 {
126  if (m_ptr) m_ptr->release();
127  m_ptr = other.release();
128  return *this;
129 }
130 
131 
132 /// Destructor.
133 template <CxxUtils::detail::RefCounted T>
134 inline
135 RefCountedPtr<T>::~RefCountedPtr()
136 {
137  if (m_ptr) m_ptr->release();
138 }
139 
140 
141 /// Change the pointer.
142 template <CxxUtils::detail::RefCounted T>
143 inline
144 void RefCountedPtr<T>::reset (T* p)
145 {
146  if (p == m_ptr) return;
147  if (m_ptr) m_ptr->release();
148  m_ptr = p;
149  if (m_ptr) m_ptr->addRef();
150 }
151 
152 
153 /// Check if the pointer is valid.
154 template <CxxUtils::detail::RefCounted T>
155 inline
156 bool RefCountedPtr<T>::isValid() const
157 {
158  return m_ptr != nullptr;
159 }
160 
161 
162 /// Check if the pointer is valid.
163 template <CxxUtils::detail::RefCounted T>
164 inline
165 RefCountedPtr<T>::operator bool() const
166 {
167  return m_ptr != nullptr;
168 }
169 
170 
171 /// Check if the pointer is invalid.
172 template <CxxUtils::detail::RefCounted T>
173 inline
174 bool RefCountedPtr<T>::operator!() const
175 {
176  return m_ptr == nullptr;
177 }
178 
179 
180 /// Get the pointer.
181 template <CxxUtils::detail::RefCounted T>
182 inline
183 T* RefCountedPtr<T>::get()
184 {
185  return m_ptr;
186 }
187 template <CxxUtils::detail::RefCounted T>
188 inline
189 const T* RefCountedPtr<T>::get() const
190 {
191  return m_ptr;
192 }
193 
194 
195 /// Convert to pointer.
196 template <CxxUtils::detail::RefCounted T>
197 inline
198 RefCountedPtr<T>::operator T*()
199 {
200  return m_ptr;
201 }
202 template <CxxUtils::detail::RefCounted T>
203 inline
204 RefCountedPtr<T>::operator const T*() const
205 {
206  return m_ptr;
207 }
208 
209 
210 /// Dereference.
211 template <CxxUtils::detail::RefCounted T>
212 inline
213 T* RefCountedPtr<T>::operator->()
214 {
215  return m_ptr;
216 }
217 template <CxxUtils::detail::RefCounted T>
218 inline
219 const T* RefCountedPtr<T>::operator->() const
220 {
221  return m_ptr;
222 }
223 
224 
225 /// Dereference.
226 template <CxxUtils::detail::RefCounted T>
227 inline
228 T& RefCountedPtr<T>::operator*()
229 {
230  return *m_ptr;
231 }
232 template <CxxUtils::detail::RefCounted T>
233 inline
234 const T& RefCountedPtr<T>::operator*() const
235 {
236  return *m_ptr;
237 }
238 
239 
240 /// Return the pointer and give up ownership.
241 template <CxxUtils::detail::RefCounted T>
242 inline
243 T* RefCountedPtr<T>::release()
244 {
245  T* p = m_ptr;
246  m_ptr = nullptr;
247  return p;
248 }
249 
250 
251 } // namespace CxxUtils