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-2023 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 template<class T>
68 inline constexpr Foam::refPtr<T>::refPtr(const T& obj) noexcept
69 :
70  ptr_(const_cast<T*>(&obj)),
71  type_(CREF)
72 {}
73 
74 
75 template<class T>
77 :
78  ptr_(rhs.ptr_),
79  type_(rhs.type_)
80 {
81  rhs.ptr_ = nullptr;
82  rhs.type_ = PTR;
83 }
84 
85 
86 template<class T>
87 inline Foam::refPtr<T>::refPtr(const refPtr<T>& rhs)
88 :
89  ptr_(rhs.ptr_),
90  type_(rhs.type_)
91 {
92  if (is_pointer())
93  {
94  if (ptr_)
95  {
96  rhs.type_ = REF; // (shallow copy)
97  }
98  else
99  {
101  << "Attempted copy/move of a deallocated "
102  << this->typeName()
104  }
105  }
106 }
107 
108 
109 template<class T>
110 inline Foam::refPtr<T>::refPtr(const refPtr<T>& rhs, bool reuse)
111 :
112  ptr_(rhs.ptr_),
113  type_(rhs.type_)
114 {
115  if (is_pointer())
116  {
117  if (ptr_)
118  {
119  if (reuse)
120  {
121  rhs.ptr_ = nullptr;
122  rhs.type_ = PTR;
123  }
124  else
125  {
126  rhs.type_ = REF; // (shallow copy)
127  }
128  }
129  else
130  {
132  << "Attempted copy/move of a deallocated "
133  << this->typeName()
135  }
136  }
137 }
138 
139 
140 template<class T>
141 inline Foam::refPtr<T>::refPtr(std::unique_ptr<T>&& rhs) noexcept
142 :
143  refPtr<T>(rhs.release())
144 {}
145 
146 
147 template<class T>
149 :
150  refPtr<T>(rhs.release())
151 {}
152 
153 
154 template<class T>
155 inline Foam::refPtr<T>::refPtr(const tmp<T>& rhs, bool reuse)
156 :
158 {
159  reset(const_cast<tmp<T>&>(rhs), reuse);
160 }
161 
162 
163 template<class T>
164 inline Foam::refPtr<T>::refPtr(const tmp<T>& rhs)
165 :
167 {
168  reset(const_cast<tmp<T>&>(rhs), false);
169 }
170 
171 
172 template<class T>
173 inline Foam::refPtr<T>::refPtr(tmp<T>&& rhs)
174 :
175  refPtr<T>()
176 {
177  reset(const_cast<tmp<T>&>(rhs), true);
178 }
179 
180 
181 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
182 
183 template<class T>
185 {
186  clear();
187 }
188 
189 
190 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
191 
192 template<class T>
194 {
195  return (type_ == CREF);
196 }
197 
198 
199 template<class T>
200 inline bool Foam::refPtr<T>::is_pointer() const noexcept
201 {
202  //OR: return (type_ == PTR);
203  return (type_ < REF_Types);
204 }
205 
206 
207 template<class T>
208 inline bool Foam::refPtr<T>::is_reference() const noexcept
209 {
210  //OR: return (type_ == CREF || type_ == REF);
211  return (type_ > REF_Types);
212 }
213 
214 
215 template<class T>
217 {
218  return (ptr_ && is_pointer());
219 }
220 
221 
222 template<class T>
223 inline const T& Foam::refPtr<T>::cref() const
224 {
225  if (!ptr_ && is_pointer())
226  {
228  << this->typeName() << " deallocated"
229  << abort(FatalError);
230  }
231 
232  return *ptr_; // const reference
233 }
234 
235 
236 template<class T>
237 inline T& Foam::refPtr<T>::ref() const
238 {
239  if (is_const())
240  {
242  << "Attempted non-const reference to const object: "
243  << this->typeName()
244  << abort(FatalError);
245  }
246  else if (!ptr_ && is_pointer())
247  {
249  << this->typeName() << " deallocated"
250  << abort(FatalError);
251  }
252 
253  return *ptr_; // non-const reference
254 }
255 
256 
257 template<class T>
259 {
260  refPtr<T> dup;
261 
262  if (ptr_)
263  {
264  dup.ptr_ = ptr_;
265  dup.type_ = (is_const() ? CREF : REF);
266  }
267 
268  return dup;
269 }
270 
271 
272 template<class T>
274 {
275  if (is_pointer())
276  {
277  T* p = ptr_;
278  ptr_ = nullptr;
279  return p;
280  }
281 
282  return nullptr;
283 }
284 
285 
286 template<class T>
287 inline T* Foam::refPtr<T>::ptr() const
288 {
289  if (!ptr_)
290  {
292  << this->typeName() << " deallocated"
293  << abort(FatalError);
294  }
295 
296  if (is_pointer())
297  {
298  // Release pointer
299  T* p = ptr_;
300  ptr_ = nullptr;
301 
302  return p;
303  }
304 
305  return ptr_->clone().ptr();
306 }
307 
308 
309 template<class T>
310 inline void Foam::refPtr<T>::clear() const noexcept
311 {
312  if (is_pointer())
313  {
314  delete ptr_;
315  ptr_ = nullptr;
316  }
317 }
318 
319 
320 template<class T>
321 inline void Foam::refPtr<T>::reset(T* p) noexcept
322 {
323  clear();
324  ptr_ = p;
325  type_ = PTR;
326 }
327 
328 
329 template<class T>
330 inline void Foam::refPtr<T>::reset(refPtr<T>&& other) noexcept
331 {
332  // Could also make Fatal with FULLDEBUG
333  if (&other == this)
334  {
335  return; // No self-assignment
336  }
337 
338  clear();
339  ptr_ = other.ptr_;
340  type_ = other.type_;
342  other.ptr_ = nullptr;
343  other.type_ = PTR;
344 }
345 
346 
347 template<class T>
348 inline void Foam::refPtr<T>::reset(tmp<T>& other, bool reuse)
349 {
350  if (other.get())
351  {
352  if (reuse && other.is_pointer())
353  {
354  // Acquire pointer.
355  // Fatal if pointer is not unique (avoids potential leaks)
356  reset(other.ptr());
357  }
358  else if (other.is_const())
359  {
360  cref(other.get());
361  }
362  else
363  {
364  ref(other.get());
365  }
366  }
367  else
368  {
369  clear();
370  }
371 }
372 
373 
374 template<class T>
375 inline void Foam::refPtr<T>::cref(const refPtr<T>& other) noexcept
376 {
377  // Could also make Fatal with FULLDEBUG
378  if (&other == this)
379  {
380  return; // No self-assignment
381  }
382 
383  clear();
384  ptr_ = other.ptr_;
385  type_ = (ptr_ ? CREF : PTR);
386 }
387 
388 
389 template<class T>
390 inline void Foam::refPtr<T>::cref(const T& obj) noexcept
391 {
392  clear();
393  ptr_ = const_cast<T*>(&obj);
394  type_ = CREF;
395 }
396 
397 
398 template<class T>
399 inline void Foam::refPtr<T>::cref(const T* p) noexcept
400 {
401  clear();
402  ptr_ = const_cast<T*>(p);
403  type_ = (ptr_ ? CREF : PTR);
404 }
405 
406 
407 template<class T>
408 inline void Foam::refPtr<T>::ref(T& obj) noexcept
409 {
410  clear();
411  ptr_ = &obj;
412  type_ = REF;
413 }
414 
415 
416 template<class T>
417 inline void Foam::refPtr<T>::ref(T* p) noexcept
418 {
419  clear();
420  ptr_ = p;
421  type_ = (ptr_ ? REF : PTR);
422 }
423 
424 
425 template<class T>
426 inline void Foam::refPtr<T>::swap(refPtr<T>& other) noexcept
427 {
428  // Swap is just copy/assign for pointer and enum types
429  // Self-swap is effectively ignored
430  T* p = ptr_;
431  ptr_ = other.ptr_;
432  other.ptr_ = p;
433 
434  refType t = type_;
435  type_ = other.type_;
436  other.type_ = t;
437 }
438 
439 
440 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
441 
442 template<class T>
443 inline const T& Foam::refPtr<T>::operator*() const
444 {
445  if (!ptr_)
446  {
448  << this->typeName() << " deallocated"
450  }
451  return *ptr_;
452 }
453 
454 
455 template<class T>
457 {
458  if (is_const())
459  {
461  << "Attempt to cast const object to non-const: "
462  << this->typeName()
463  << abort(FatalError);
464  }
465  else if (!ptr_)
466  {
468  << this->typeName() << " deallocated"
469  << abort(FatalError);
470  }
471 
472  return *ptr_;
473 }
474 
475 
476 template<class T>
477 inline const T* Foam::refPtr<T>::operator->() const
478 {
479  if (!ptr_)
480  {
482  << this->typeName() << " deallocated"
483  << abort(FatalError);
484  }
485 
486  return ptr_;
487 }
488 
489 
490 template<class T>
492 {
493  if (is_const())
494  {
496  << "Attempt to cast const object to non-const: "
497  << this->typeName()
498  << abort(FatalError);
499  }
500  else if (!ptr_)
501  {
503  << this->typeName() << " deallocated"
504  << abort(FatalError);
505  }
506 
507  return ptr_;
508 }
509 
510 
511 template<class T>
512 inline void Foam::refPtr<T>::operator=(const refPtr<T>& other)
513 {
514  // Could also make Fatal with FULLDEBUG
515  if (&other == this)
516  {
517  return; // No self-assignment
518  }
519 
520  clear();
521 
522  if (other.is_pointer())
523  {
524  ptr_ = other.ptr_;
525  type_ = PTR;
526 
527  other.ptr_ = nullptr;
528  other.type_ = PTR;
529 
530  if (!ptr_)
531  {
533  << "Attempted assignment of a deallocated "
534  << this->typeName()
535  << abort(FatalError);
536  }
537  }
538  else
539  {
541  << "Attempted assignment of an object reference of type "
542  << typeid(T).name()
543  << abort(FatalError);
544  }
545 }
546 
547 
548 template<class T>
549 inline void Foam::refPtr<T>::operator=(tmp<T>&& other)
550 {
551  reset(other, true); // reuse
552 }
553 
554 
555 template<class T>
557 {
558  if (is_pointer())
559  {
560  return tmp<T>(ptr());
561  }
562  else
563  {
564  return tmp<T>(cref());
565  }
566 }
567 
568 
569 // ************************************************************************* //
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:216
T * ptr() const
Return managed pointer for reuse, or clone() the object reference.
Definition: refPtrI.H:280
const T * operator->() const
Dereferences (const) pointer to the managed object.
Definition: refPtrI.H:470
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:505
T * get() noexcept
Return pointer without nullptr checking.
Definition: tmp.H:290
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:436
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:230
const volScalarField & T
void clear() const noexcept
If object pointer points to valid object: delete object and set pointer to nullptr.
Definition: refPtrI.H:303
bool is_const() const noexcept
If the stored/referenced content is const.
Definition: refPtrI.H:186
T * release() noexcept
Release ownership and return the pointer. A no-op for reference objects (returns nullptr).
Definition: refPtrI.H:266
bool is_pointer() const noexcept
True if this is a managed pointer (not a reference)
Definition: tmpI.H:207
bool movable() const noexcept
True if this is a non-null managed pointer.
Definition: refPtrI.H:209
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
bool is_reference() const noexcept
True if this is a reference (not a pointer)
Definition: refPtrI.H:201
refPtr< T > shallowClone() const noexcept
Return a shallow copy as a wrapped reference, preserving the const/non-const status.
Definition: refPtrI.H:251
T * ptr() const
Return managed pointer for reuse, or clone() the object reference.
Definition: tmpI.H:265
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:419
bool is_const() const noexcept
If the stored/referenced content is const.
Definition: tmpI.H:200
~refPtr() noexcept
Destructor: deletes managed pointer.
Definition: refPtrI.H:177
bool is_pointer() const noexcept
True if this is a managed pointer (not a reference)
Definition: refPtrI.H:193
void reset(T *p=nullptr) noexcept
Delete managed pointer and set to new given pointer.
Definition: refPtrI.H:314