refPtrI.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2016-2017 OpenFOAM Foundation
9  Copyright (C) 2018-2022 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "error.H"
30 #include <typeinfo>
31 
32 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
33 
34 template<class T>
36 {
37  return Foam::word("refPtr<" + std::string(typeid(T).name()) + '>', false);
38 }
39 
40 
41 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
42 
43 template<class T>
44 inline constexpr Foam::refPtr<T>::refPtr() noexcept
45 :
46  ptr_(nullptr),
47  type_(PTR)
48 {}
49 
50 
51 template<class T>
52 inline constexpr Foam::refPtr<T>::refPtr(std::nullptr_t) noexcept
53 :
54  ptr_(nullptr),
55  type_(PTR)
56 {}
57 
58 
59 template<class T>
60 inline constexpr Foam::refPtr<T>::refPtr(T* p) noexcept
61 :
62  ptr_(p),
63  type_(PTR)
64 {}
65 
66 
67 
68 template<class T>
69 inline constexpr Foam::refPtr<T>::refPtr(const T& obj) noexcept
70 :
71  ptr_(const_cast<T*>(&obj)),
72  type_(CREF)
73 {}
74 
75 
76 template<class T>
78 :
79  ptr_(rhs.ptr_),
80  type_(rhs.type_)
81 {
82  rhs.ptr_ = nullptr;
83  rhs.type_ = PTR;
84 }
85 
86 
87 template<class T>
88 inline Foam::refPtr<T>::refPtr(const refPtr<T>& rhs)
89 :
90  ptr_(rhs.ptr_),
91  type_(rhs.type_)
92 {
93  if (is_pointer())
94  {
95  if (ptr_)
96  {
97  rhs.type_ = REF; // (shallow copy)
98  }
99  else
100  {
102  << "Attempted copy/move of a deallocated "
103  << this->typeName()
105  }
106  }
107 }
108 
109 
110 template<class T>
111 inline Foam::refPtr<T>::refPtr(const refPtr<T>& rhs, bool reuse)
112 :
113  ptr_(rhs.ptr_),
114  type_(rhs.type_)
115 {
116  if (is_pointer())
117  {
118  if (ptr_)
119  {
120  if (reuse)
121  {
122  rhs.ptr_ = nullptr;
123  rhs.type_ = PTR;
124  }
125  else
126  {
127  rhs.type_ = REF; // (shallow copy)
128  }
129  }
130  else
131  {
133  << "Attempted copy/move of a deallocated "
134  << this->typeName()
136  }
137  }
138 }
139 
140 
141 template<class T>
142 inline Foam::refPtr<T>::refPtr(std::unique_ptr<T>&& rhs) noexcept
143 :
144  refPtr<T>(rhs.release())
145 {}
146 
147 
148 template<class T>
150 :
151  refPtr<T>(rhs.release())
152 {}
153 
154 
155 template<class T>
156 inline Foam::refPtr<T>::refPtr(const tmp<T>& rhs, bool reuse)
157 :
159 {
160  reset(const_cast<tmp<T>&>(rhs), reuse);
161 }
162 
163 
164 template<class T>
165 inline Foam::refPtr<T>::refPtr(const tmp<T>& rhs)
166 :
168 {
169  reset(const_cast<tmp<T>&>(rhs), false);
170 }
171 
172 
173 template<class T>
174 inline Foam::refPtr<T>::refPtr(tmp<T>&& rhs)
175 :
176  refPtr<T>()
177 {
178  reset(const_cast<tmp<T>&>(rhs), true);
179 }
180 
181 
182 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
183 
184 template<class T>
186 {
187  clear();
188 }
189 
190 
191 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
192 
193 template<class T>
195 {
196  return (is_pointer() && ptr_);
197 }
198 
199 
200 template<class T>
201 inline const T& Foam::refPtr<T>::cref() const
202 {
203  if (is_pointer() && !ptr_)
204  {
206  << this->typeName() << " deallocated"
207  << abort(FatalError);
208  }
209 
210  return *ptr_; // const reference
211 }
212 
213 
214 template<class T>
215 inline T& Foam::refPtr<T>::ref() const
216 {
217  if (is_const())
218  {
220  << "Attempted non-const reference to const object: "
221  << this->typeName()
222  << abort(FatalError);
223  }
224  else if (is_pointer() && !ptr_)
225  {
227  << this->typeName() << " deallocated"
228  << abort(FatalError);
229  }
230 
231  return *ptr_; // non-const reference
232 }
233 
234 
235 template<class T>
237 {
238  refPtr<T> dup;
239 
240  if (ptr_)
241  {
242  dup.ptr_ = ptr_;
243  dup.type_ = (is_const() ? CREF : REF);
244  }
245 
246  return dup;
247 }
248 
249 
250 template<class T>
252 {
253  if (is_pointer())
254  {
255  T* p = ptr_;
256  ptr_ = nullptr;
257  return p;
258  }
259 
260  return nullptr;
261 }
262 
263 
264 template<class T>
265 inline T* Foam::refPtr<T>::ptr() const
266 {
267  if (!ptr_)
268  {
270  << this->typeName() << " deallocated"
271  << abort(FatalError);
272  }
273 
274  if (is_pointer())
275  {
276  // Release pointer
277  T* p = ptr_;
278  ptr_ = nullptr;
279 
280  return p;
281  }
282 
283  return ptr_->clone().ptr();
284 }
285 
286 
287 template<class T>
288 inline void Foam::refPtr<T>::clear() const noexcept
289 {
290  if (is_pointer())
291  {
292  delete ptr_;
293  ptr_ = nullptr;
294  }
295 }
296 
297 
298 template<class T>
299 inline void Foam::refPtr<T>::reset(T* p) noexcept
300 {
301  clear();
302  ptr_ = p;
303  type_ = PTR;
304 }
305 
306 
307 template<class T>
308 inline void Foam::refPtr<T>::reset(refPtr<T>&& other) noexcept
309 {
310  // Could also make Fatal with FULLDEBUG
311  if (&other == this)
312  {
313  return; // No self-assignment
314  }
315 
316  clear();
317  ptr_ = other.ptr_;
318  type_ = other.type_;
320  other.ptr_ = nullptr;
321  other.type_ = PTR;
322 }
323 
324 
325 template<class T>
326 inline void Foam::refPtr<T>::reset(tmp<T>& other, bool reuse)
327 {
328  if (other.get())
329  {
330  if (reuse && other.is_pointer())
331  {
332  // Acquire pointer.
333  // Fatal if pointer is not unique (avoids potential leaks)
334  reset(other.ptr());
335  }
336  else if (other.is_const())
337  {
338  cref(other.get());
339  }
340  else
341  {
342  ref(other.get());
343  }
344  }
345  else
346  {
347  clear();
348  }
349 }
350 
351 
352 template<class T>
353 inline void Foam::refPtr<T>::cref(const refPtr<T>& other) noexcept
354 {
355  // Could also make Fatal with FULLDEBUG
356  if (&other == this)
357  {
358  return; // No self-assignment
359  }
360 
361  clear();
362  ptr_ = other.ptr_;
363  type_ = (ptr_ ? CREF : PTR);
364 }
365 
366 
367 template<class T>
368 inline void Foam::refPtr<T>::cref(const T& obj) noexcept
369 {
370  clear();
371  ptr_ = const_cast<T*>(&obj);
372  type_ = CREF;
373 }
374 
375 
376 template<class T>
377 inline void Foam::refPtr<T>::cref(const T* p) noexcept
378 {
379  clear();
380  ptr_ = const_cast<T*>(p);
381  type_ = (ptr_ ? CREF : PTR);
382 }
383 
384 
385 template<class T>
386 inline void Foam::refPtr<T>::ref(T& obj) noexcept
387 {
388  clear();
389  ptr_ = &obj;
390  type_ = REF;
391 }
392 
393 
394 template<class T>
395 inline void Foam::refPtr<T>::ref(T* p) noexcept
396 {
397  clear();
398  ptr_ = p;
399  type_ = (ptr_ ? REF : PTR);
400 }
401 
402 
403 template<class T>
404 inline void Foam::refPtr<T>::swap(refPtr<T>& other) noexcept
405 {
406  // Swap is just copy/assign for pointer and enum types
407  // Self-swap is effectively ignored
408  T* p = ptr_;
409  ptr_ = other.ptr_;
410  other.ptr_ = p;
411 
412  refType t = type_;
413  type_ = other.type_;
414  other.type_ = t;
415 }
416 
417 
418 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
419 
420 template<class T>
421 inline const T& Foam::refPtr<T>::operator*() const
422 {
423  if (!ptr_)
424  {
426  << this->typeName() << " deallocated"
428  }
429  return *ptr_;
430 }
431 
432 
433 template<class T>
435 {
436  if (is_const())
437  {
439  << "Attempt to cast const object to non-const: "
440  << this->typeName()
441  << abort(FatalError);
442  }
443  else if (!ptr_)
444  {
446  << this->typeName() << " deallocated"
447  << abort(FatalError);
448  }
449 
450  return *ptr_;
451 }
452 
453 
454 template<class T>
455 inline const T* Foam::refPtr<T>::operator->() const
456 {
457  if (!ptr_)
458  {
460  << this->typeName() << " deallocated"
461  << abort(FatalError);
462  }
463 
464  return ptr_;
465 }
466 
467 
468 template<class T>
470 {
471  if (is_const())
472  {
474  << "Attempt to cast const object to non-const: "
475  << this->typeName()
476  << abort(FatalError);
477  }
478  else if (!ptr_)
479  {
481  << this->typeName() << " deallocated"
482  << abort(FatalError);
483  }
484 
485  return ptr_;
486 }
487 
488 
489 template<class T>
490 inline void Foam::refPtr<T>::operator=(const refPtr<T>& other)
491 {
492  // Could also make Fatal with FULLDEBUG
493  if (&other == this)
494  {
495  return; // No self-assignment
496  }
497 
498  clear();
499 
500  if (other.is_pointer())
501  {
502  ptr_ = other.ptr_;
503  type_ = PTR;
504 
505  other.ptr_ = nullptr;
506  other.type_ = PTR;
507 
508  if (!ptr_)
509  {
511  << "Attempted assignment of a deallocated "
512  << this->typeName()
513  << abort(FatalError);
514  }
515  }
516  else
517  {
519  << "Attempted assignment of an object reference of type "
520  << typeid(T).name()
521  << abort(FatalError);
522  }
523 }
524 
525 
526 template<class T>
527 inline void Foam::refPtr<T>::operator=(tmp<T>&& other)
528 {
529  reset(other, true); // reuse
530 }
531 
532 
533 template<class T>
535 {
536  if (is_pointer())
537  {
538  return tmp<T>(ptr());
539  }
540  else
541  {
542  return tmp<T>(cref());
543  }
544 }
545 
546 
547 // ************************************************************************* //
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
const T & cref() const
Return const reference to the object or to the contents of a (non-null) managed pointer.
Definition: refPtrI.H:194
T * ptr() const
Return managed pointer for reuse, or clone() the object reference.
Definition: refPtrI.H:258
const T * operator->() const
Dereferences (const) pointer to the managed object.
Definition: refPtrI.H:448
A class for managing references or pointers (no reference counting)
Definition: HashPtrTable.H:49
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
void operator=(const refPtr< T > &other)
Transfer ownership of managed pointer.
Definition: refPtrI.H:483
T * get() noexcept
Return pointer without nullptr checking.
Definition: tmp.H:265
A class for handling words, derived from Foam::string.
Definition: word.H:63
const T & operator*() const
Return const reference to the object.
Definition: refPtrI.H:414
constexpr refPtr() noexcept
Construct with no managed pointer.
Definition: refPtrI.H:37
static word typeName()
The type-name, constructed from type-name of T.
Definition: refPtrI.H:28
patchWriters clear()
errorManip< error > abort(error &err)
Definition: errorManip.H:139
const direction noexcept
Definition: Scalar.H:258
rDeltaT ref()
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition: refPtrI.H:208
const volScalarField & T
void clear() const noexcept
If object pointer points to valid object: delete object and set pointer to nullptr.
Definition: refPtrI.H:281
T * release() noexcept
Release ownership and return the pointer. A no-op for reference objects (returns nullptr).
Definition: refPtrI.H:244
bool is_pointer() const noexcept
True if this is a managed pointer (not a reference)
Definition: tmp.H:247
bool movable() const noexcept
True if this is a non-null managed pointer.
Definition: refPtrI.H:187
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
refPtr< T > shallowClone() const noexcept
Return a shallow copy as a wrapped reference, preserving the const/non-const status.
Definition: refPtrI.H:229
T * ptr() const
Return managed pointer for reuse, or clone() the object reference.
Definition: tmpI.H:231
volScalarField & p
A class for managing temporary objects.
Definition: HashPtrTable.H:50
void swap(refPtr< T > &other) noexcept
Swaps the managed object with other.
Definition: refPtrI.H:397
bool is_const() const noexcept
If the stored/referenced content is const.
Definition: tmp.H:242
~refPtr() noexcept
Destructor: deletes managed pointer.
Definition: refPtrI.H:178
void reset(T *p=nullptr) noexcept
Delete managed pointer and set to new given pointer.
Definition: refPtrI.H:292