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-2021 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>
35 template<class... Args>
37 {
38  return refPtr<T>(new T(std::forward<Args>(args)...));
39 }
40 
41 
42 template<class T>
43 template<class U, class... Args>
45 {
46  return refPtr<T>(new U(std::forward<Args>(args)...));
47 }
48 
49 
50 template<class T>
52 {
53  return "refPtr<" + word(typeid(T).name()) + '>';
54 }
55 
56 
57 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
58 
59 template<class T>
60 inline constexpr Foam::refPtr<T>::refPtr() noexcept
61 :
62  ptr_(nullptr),
63  type_(PTR)
64 {}
65 
66 
67 template<class T>
68 inline constexpr Foam::refPtr<T>::refPtr(std::nullptr_t) noexcept
69 :
70  ptr_(nullptr),
71  type_(PTR)
72 {}
73 
74 
75 template<class T>
76 inline constexpr Foam::refPtr<T>::refPtr(T* p) noexcept
77 :
78  ptr_(p),
79  type_(PTR)
80 {}
81 
82 
83 template<class T>
84 inline Foam::refPtr<T>::refPtr(autoPtr<T>&& rhs) noexcept
85 :
86  refPtr<T>(rhs.release())
87 {}
88 
89 
90 template<class T>
91 inline Foam::refPtr<T>::refPtr(std::unique_ptr<T>&& rhs) noexcept
92 :
93  refPtr<T>(rhs.release())
94 {}
95 
96 
97 template<class T>
98 inline constexpr Foam::refPtr<T>::refPtr(const T& obj) noexcept
99 :
100  ptr_(const_cast<T*>(&obj)),
101  type_(CREF)
102 {}
103 
104 
105 template<class T>
106 inline Foam::refPtr<T>::refPtr(refPtr<T>&& rhs) noexcept
107 :
108  ptr_(rhs.ptr_),
109  type_(rhs.type_)
110 {
111  rhs.ptr_ = nullptr;
112  rhs.type_ = PTR;
113 }
114 
115 
116 template<class T>
118 :
119  ptr_(rhs.ptr_),
120  type_(rhs.type_)
121 {
122  if (type_ == PTR)
123  {
124  if (ptr_)
125  {
126  rhs.type_ = REF; // (shallow copy)
127  }
128  else
129  {
131  << "Attempted copy of a deallocated "
132  << this->typeName()
133  << abort(FatalError);
134  }
135  }
136 }
137 
138 
139 template<class T>
140 inline Foam::refPtr<T>::refPtr(const refPtr<T>& rhs, bool reuse)
141 :
142  ptr_(rhs.ptr_),
143  type_(rhs.type_)
144 {
145  if (type_ == PTR)
146  {
147  if (ptr_)
148  {
149  if (reuse)
150  {
151  rhs.ptr_ = nullptr;
152  // Note: rhs.type_ already set as PTR
153  }
154  else
155  {
156  rhs.type_ = REF; // (shallow copy)
157  }
158  }
159  else
160  {
162  << "Attempted copy of a deallocated "
163  << this->typeName()
164  << abort(FatalError);
165  }
166  }
167 }
168 
169 
170 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
171 
172 template<class T>
174 {
175  clear();
176 }
177 
178 
179 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
180 
181 template<class T>
182 inline bool Foam::refPtr<T>::movable() const noexcept
183 {
184  return (type_ == PTR && ptr_);
185 }
186 
187 
188 template<class T>
189 inline const T& Foam::refPtr<T>::cref() const
190 {
191  if (type_ == PTR && !ptr_)
192  {
194  << this->typeName() << " deallocated"
195  << abort(FatalError);
196  }
197 
198  return *ptr_; // const reference
199 }
200 
201 
202 template<class T>
203 inline T& Foam::refPtr<T>::ref() const
204 {
205  if (is_const())
206  {
208  << "Attempted non-const reference to const object: "
209  << this->typeName()
210  << abort(FatalError);
211  }
212  else if (type_ == PTR && !ptr_)
213  {
215  << this->typeName() << " deallocated"
216  << abort(FatalError);
217  }
218 
219  return *ptr_; // non-const reference
220 }
221 
222 
223 template<class T>
225 {
226  return const_cast<T&>(cref());
227 }
228 
229 
230 template<class T>
232 {
233  refPtr<T> dup;
234 
235  if (ptr_)
236  {
237  dup.ptr_ = ptr_;
238  dup.type_ = (is_const() ? CREF : REF);
239  }
240 
241  return dup;
242 }
243 
244 
245 template<class T>
246 inline T* Foam::refPtr<T>::release() noexcept
247 {
248  if (type_ == PTR)
249  {
250  T* p = ptr_;
251  ptr_ = nullptr;
252  return p;
253  }
254 
255  return nullptr;
256 }
257 
258 
259 template<class T>
260 inline T* Foam::refPtr<T>::ptr() const
261 {
262  if (!ptr_)
263  {
265  << this->typeName() << " deallocated"
266  << abort(FatalError);
267  }
268 
269  if (type_ == PTR)
270  {
271  // Release pointer
272  T* p = ptr_;
273  ptr_ = nullptr;
274 
275  return p;
276  }
277 
278  return ptr_->clone().ptr();
279 }
280 
281 
282 template<class T>
283 inline void Foam::refPtr<T>::clear() const noexcept
284 {
285  if (type_ == PTR && ptr_)
286  {
287  delete ptr_;
288  ptr_ = nullptr;
289  }
290 }
291 
292 
293 template<class T>
294 inline void Foam::refPtr<T>::reset(T* p) noexcept
295 {
296  clear();
297  ptr_ = p;
298  type_ = PTR;
299 }
300 
301 
302 template<class T>
303 inline void Foam::refPtr<T>::reset(refPtr<T>&& other) noexcept
304 {
305  if (&other == this)
306  {
307  return; // Self-assignment is a no-op
308  }
309 
310  clear();
311  ptr_ = other.ptr_;
312  type_ = other.type_;
313 
314  other.ptr_ = nullptr;
315  other.type_ = PTR;
316 }
317 
318 
319 template<class T>
320 inline void Foam::refPtr<T>::cref(const refPtr<T>& other) noexcept
321 {
322  if (&other == this)
323  {
324  return; // Self-assignment is a no-op
325  }
326 
327  clear();
328  ptr_ = other.ptr_;
329  type_ = (ptr_ ? CREF : PTR);
330 }
331 
332 
333 template<class T>
334 inline void Foam::refPtr<T>::cref(const T& obj) noexcept
335 {
336  clear();
337  ptr_ = const_cast<T*>(&obj);
338  type_ = CREF;
339 }
340 
341 
342 template<class T>
343 inline void Foam::refPtr<T>::cref(const T* p) noexcept
344 {
345  clear();
346  ptr_ = const_cast<T*>(p);
347  type_ = (ptr_ ? CREF : PTR);
348 }
349 
350 
351 template<class T>
352 inline void Foam::refPtr<T>::ref(T& obj) noexcept
353 {
354  clear();
355  ptr_ = &obj;
356  type_ = REF;
357 }
358 
359 
360 template<class T>
361 inline void Foam::refPtr<T>::ref(T* p) noexcept
362 {
363  clear();
364  ptr_ = p;
365  type_ = (ptr_ ? REF : PTR);
366 }
367 
368 
369 template<class T>
370 inline void Foam::refPtr<T>::swap(refPtr<T>& other) noexcept
371 {
372  // Swap is just copy/assign for pointer and enum types
373  // Self-swap is effectively ignored
374  T* p = ptr_;
375  ptr_ = other.ptr_;
376  other.ptr_ = p;
377 
378  refType t = type_;
379  type_ = other.type_;
380  other.type_ = t;
381 }
382 
383 
384 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
385 
386 template<class T>
387 inline const T& Foam::refPtr<T>::operator*() const
388 {
389  if (!ptr_)
390  {
392  << this->typeName() << " deallocated"
393  << abort(FatalError);
394  }
395  return *ptr_;
396 }
397 
398 
399 template<class T>
401 {
402  if (is_const())
403  {
405  << "Attempt to cast const object to non-const: "
406  << this->typeName()
407  << abort(FatalError);
408  }
409  else if (!ptr_)
410  {
412  << this->typeName() << " deallocated"
413  << abort(FatalError);
414  }
415 
416  return *ptr_;
417 }
418 
419 
420 template<class T>
421 inline const T* Foam::refPtr<T>::operator->() const
422 {
423  if (!ptr_)
424  {
426  << this->typeName() << " deallocated"
427  << abort(FatalError);
428  }
429 
430  return ptr_;
431 }
432 
433 
434 template<class T>
436 {
437  if (is_const())
438  {
440  << "Attempt to cast const object to non-const: "
441  << this->typeName()
442  << abort(FatalError);
443  }
444  else if (!ptr_)
445  {
447  << this->typeName() << " deallocated"
448  << abort(FatalError);
449  }
450 
451  return ptr_;
452 }
453 
454 
455 template<class T>
456 inline void Foam::refPtr<T>::operator=(const refPtr<T>& other)
457 {
458  if (&other == this)
459  {
460  return; // Self-assignment is a no-op
461  }
462 
463  clear();
464 
465  if (other.type_ == PTR)
466  {
467  ptr_ = other.ptr_;
468  type_ = PTR;
469  other.ptr_ = nullptr;
470 
471  if (!ptr_)
472  {
474  << "Attempted assignment of a deallocated "
475  << this->typeName()
476  << abort(FatalError);
477  }
478  }
479  else
480  {
482  << "Attempted assignment of an object reference of type "
483  << typeid(T).name()
484  << abort(FatalError);
485  }
486 }
487 
488 
489 template<class T>
490 inline void Foam::refPtr<T>::operator=(refPtr<T>&& other) noexcept
491 {
492  if (&other == this)
493  {
494  return; // Self-assignment is a no-op
495  }
496 
497  clear();
498  ptr_ = other.ptr_;
499  type_ = other.type_;
500 
501  other.ptr_ = nullptr;
502  other.type_ = PTR;
503 }
504 
505 
506 template<class T>
508 {
509  if (!p)
510  {
512  << "Attempted copy of a deallocated "
513  << this->typeName()
514  << abort(FatalError);
515  }
516 
517  reset(p);
518 }
519 
520 
521 template<class T>
522 inline void Foam::refPtr<T>::operator=(std::nullptr_t) noexcept
523 {
524  reset(nullptr);
525 }
526 
527 
528 template<class T>
530 {
531  if (type_ == PTR)
532  {
533  return tmp<T>(ptr());
534  }
535  else
536  {
537  return tmp<T>(cref());
538  }
539 }
540 
541 
542 // ************************************************************************* //
Foam::refPtr::New
static refPtr< T > New(Args &&... args)
Construct refPtr of T with forwarding arguments.
Foam::refPtr::release
T * release() noexcept
Definition: refPtrI.H:246
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::refPtr::swap
void swap(refPtr< T > &other) noexcept
Swaps the managed object with other.
Definition: refPtrI.H:370
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
Foam::refPtr::shallowClone
refPtr< T > shallowClone() const noexcept
Definition: refPtrI.H:231
Foam::refPtr::clear
void clear() const noexcept
Definition: refPtrI.H:283
Foam::refPtr::reset
void reset(refPtr< T > &&other) noexcept
Clear existing and transfer ownership.
Definition: refPtrI.H:303
error.H
Foam::refPtr::cref
const T & cref() const
Definition: refPtrI.H:189
Foam::refPtr::constCast
T & constCast() const
Definition: refPtrI.H:224
Foam::refPtr::movable
bool movable() const noexcept
True if this is a non-null managed pointer.
Definition: refPtrI.H:182
Foam::FatalError
error FatalError
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
T
const volScalarField & T
Definition: createFieldRefs.H:2
Foam::refPtr::operator*
const T & operator*() const
Return const reference to the object.
Definition: refPtrI.H:387
reset
meshPtr reset(new Foam::fvMesh(Foam::IOobject(regionName, runTime.timeName(), runTime, Foam::IOobject::MUST_READ), false))
Foam::refPtr::ptr
T * ptr() const
Return managed pointer for reuse, or clone() the object reference.
Definition: refPtrI.H:260
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
U
U
Definition: pEqn.H:72
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
clear
patchWriters clear()
Foam::refPtr::~refPtr
~refPtr()
Destructor: deletes managed pointer.
Definition: refPtrI.H:173
Foam::refPtr::refPtr
constexpr refPtr() noexcept
Construct with no managed pointer.
Definition: refPtrI.H:60
Foam::refPtr::NewFrom
static refPtr< T > NewFrom(Args &&... args)
Construct refPtr from derived type with forwarding arguments.
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::refPtr::operator=
void operator=(const refPtr< T > &other)
Transfer ownership of the managed pointer.
Definition: refPtrI.H:456
Foam::refPtr::ref
T & ref() const
Definition: refPtrI.H:203
args
Foam::argList args(argc, argv)
Foam::refPtr::operator->
const T * operator->() const
Dereferences (const) pointer to the managed object.
Definition: refPtrI.H:421
Foam::refPtr::typeName
static word typeName()
The type-name, constructed from type-name of T.
Definition: refPtrI.H:51
Foam::refPtr
A class for managing references or pointers (no reference counting)
Definition: PtrList.H:60