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 template<class... Args>
376 inline T& Foam::refPtr<T>::emplace(Args&&... args)
377 {
378  clear(); // delete old entry
379  ptr_ = new T(std::forward<Args>(args)...);
380  type_ = PTR;
381  return *ptr_;
382 }
383 
384 
385 template<class T>
386 inline void Foam::refPtr<T>::cref(const refPtr<T>& other) noexcept
387 {
388  // Could also make Fatal with FULLDEBUG
389  if (&other == this)
390  {
391  return; // No self-assignment
392  }
393 
394  clear();
395  ptr_ = other.ptr_;
396  type_ = (ptr_ ? CREF : PTR);
397 }
398 
399 
400 template<class T>
401 inline void Foam::refPtr<T>::cref(const T& obj) noexcept
402 {
403  clear();
404  ptr_ = const_cast<T*>(&obj);
405  type_ = CREF;
406 }
407 
408 
409 template<class T>
410 inline void Foam::refPtr<T>::cref(const T* p) noexcept
411 {
412  clear();
413  ptr_ = const_cast<T*>(p);
414  type_ = (ptr_ ? CREF : PTR);
415 }
416 
417 
418 template<class T>
419 inline void Foam::refPtr<T>::ref(T& obj) noexcept
420 {
421  clear();
422  ptr_ = &obj;
423  type_ = REF;
424 }
425 
426 
427 template<class T>
428 inline void Foam::refPtr<T>::ref(T* p) noexcept
429 {
430  clear();
431  ptr_ = p;
432  type_ = (ptr_ ? REF : PTR);
433 }
434 
435 
436 template<class T>
437 inline void Foam::refPtr<T>::swap(refPtr<T>& other) noexcept
438 {
439  // Swap is just copy/assign for pointer and enum types
440  // Self-swap is effectively ignored
441  T* p = ptr_;
442  ptr_ = other.ptr_;
443  other.ptr_ = p;
444 
445  refType t = type_;
446  type_ = other.type_;
447  other.type_ = t;
448 }
449 
450 
451 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
452 
453 template<class T>
454 inline const T& Foam::refPtr<T>::operator*() const
455 {
456  if (!ptr_)
457  {
459  << this->typeName() << " deallocated"
461  }
462  return *ptr_;
463 }
464 
465 
466 template<class T>
468 {
469  if (is_const())
470  {
472  << "Attempt to cast const object to non-const: "
473  << this->typeName()
474  << abort(FatalError);
475  }
476  else if (!ptr_)
477  {
479  << this->typeName() << " deallocated"
480  << abort(FatalError);
481  }
482 
483  return *ptr_;
484 }
485 
486 
487 template<class T>
488 inline const T* Foam::refPtr<T>::operator->() const
489 {
490  if (!ptr_)
491  {
493  << this->typeName() << " deallocated"
494  << abort(FatalError);
495  }
496 
497  return ptr_;
498 }
499 
500 
501 template<class T>
503 {
504  if (is_const())
505  {
507  << "Attempt to cast const object to non-const: "
508  << this->typeName()
509  << abort(FatalError);
510  }
511  else if (!ptr_)
512  {
514  << this->typeName() << " deallocated"
515  << abort(FatalError);
516  }
517 
518  return ptr_;
519 }
520 
521 
522 template<class T>
523 inline void Foam::refPtr<T>::operator=(const refPtr<T>& other)
524 {
525  // Could also make Fatal with FULLDEBUG
526  if (&other == this)
527  {
528  return; // No self-assignment
529  }
530 
531  clear();
532 
533  if (other.is_pointer())
534  {
535  ptr_ = other.ptr_;
536  type_ = PTR;
537 
538  other.ptr_ = nullptr;
539  other.type_ = PTR;
540 
541  if (!ptr_)
542  {
544  << "Attempted assignment of a deallocated "
545  << this->typeName()
546  << abort(FatalError);
547  }
548  }
549  else
550  {
552  << "Attempted assignment of an object reference of type "
553  << typeid(T).name()
554  << abort(FatalError);
555  }
556 }
557 
558 
559 template<class T>
560 inline void Foam::refPtr<T>::operator=(tmp<T>&& other)
561 {
562  reset(other, true); // reuse
563 }
564 
565 
566 template<class T>
568 {
569  if (is_pointer())
570  {
571  return tmp<T>(ptr());
572  }
573  else
574  {
575  return tmp<T>(cref());
576  }
577 }
578 
579 
580 // ************************************************************************* //
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:598
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:481
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 expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
void operator=(const refPtr< T > &other)
Transfer ownership of managed pointer.
Definition: refPtrI.H:516
T * get() noexcept
Return pointer without nullptr checking.
Definition: tmp.H:268
A class for handling words, derived from Foam::string.
Definition: word.H:63
T & emplace(Args &&... args)
Reset with emplace construction. Return reference to the new content.
Definition: refPtrI.H:369
const T & operator*() const
Return const reference to the object.
Definition: refPtrI.H:447
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:198
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:256
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:430
Foam::argList args(argc, argv)
bool is_const() const noexcept
If the stored/referenced content is const.
Definition: tmpI.H:191
~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