tmpI.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) 2011-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("tmp<" + std::string(typeid(T).name()) + '>', false);
38 }
39 
40 
41 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
42 
43 template<class T>
44 inline void Foam::tmp<T>::checkUseCount() const
45 {
46  if (ptr_ && ptr_->refCount::use_count() > 1)
47  {
49  << "Attempt to create more than "
50  << (ptr_->refCount::use_count() + 1)
51  << " tmp's referring to the same object of type tmp<"
52  << typeid(T).name() << '>'
53  << abort(FatalError);
54  }
55 }
56 
57 
58 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
59 
60 template<class T>
61 inline constexpr Foam::tmp<T>::tmp() noexcept
62 :
63  ptr_(nullptr),
64  type_(PTR)
65 {}
66 
67 
68 template<class T>
69 inline constexpr Foam::tmp<T>::tmp(std::nullptr_t) noexcept
70 :
71  ptr_(nullptr),
72  type_(PTR)
73 {}
74 
75 
76 template<class T>
77 inline Foam::tmp<T>::tmp(T* p)
78 :
79  ptr_(p),
80  type_(PTR)
81 {
82  if (ptr_ && !ptr_->refCount::unique())
83  {
85  << "Attempted construction of a "
86  << this->typeName()
87  << " from non-unique pointer"
88  << abort(FatalError);
89  }
90 }
91 
92 
93 template<class T>
94 inline constexpr Foam::tmp<T>::tmp(const T& obj) noexcept
95 :
96  ptr_(const_cast<T*>(&obj)),
97  type_(CREF)
98 {}
99 
100 
101 template<class T>
102 inline Foam::tmp<T>::tmp(tmp<T>&& rhs) noexcept
103 :
104  ptr_(rhs.ptr_),
105  type_(rhs.type_)
106 {
107  rhs.ptr_ = nullptr;
108  rhs.type_ = PTR;
109 }
110 
111 
112 template<class T>
113 inline Foam::tmp<T>::tmp(const tmp<T>&& rhs) noexcept
114 :
115  ptr_(rhs.ptr_),
116  type_(rhs.type_)
117 {
118  rhs.ptr_ = nullptr;
119  rhs.type_ = PTR;
120 }
121 
122 
123 template<class T>
124 inline Foam::tmp<T>::tmp(const tmp<T>& rhs)
125 :
126  ptr_(rhs.ptr_),
127  type_(rhs.type_)
128 {
129  if (is_pointer())
130  {
131  if (ptr_)
132  {
133  ptr_->refCount::operator++();
134  this->checkUseCount();
135  }
136  else
137  {
139  << "Attempted copy/move of a deallocated "
140  << this->typeName()
142  }
143  }
144 }
145 
146 
147 template<class T>
148 inline Foam::tmp<T>::tmp(const tmp<T>& rhs, bool reuse)
149 :
150  ptr_(rhs.ptr_),
151  type_(rhs.type_)
152 {
153  if (is_pointer())
154  {
155  if (ptr_)
156  {
157  if (reuse)
158  {
159  rhs.ptr_ = nullptr;
160  rhs.type_ = PTR;
161  }
162  else
163  {
164  ptr_->refCount::operator++();
165  this->checkUseCount();
166  }
167  }
168  else
169  {
171  << "Attempted copy/move of a deallocated "
172  << this->typeName()
174  }
175  }
176 }
177 
178 
179 template<class T>
180 inline Foam::tmp<T>::tmp(autoPtr<T>&& rhs) noexcept
181 :
182  tmp<T>(rhs.release())
183 {}
184 
185 
186 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
187 
188 template<class T>
190 {
191  clear();
192 }
193 
194 
195 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
196 
197 template<class T>
198 inline bool Foam::tmp<T>::is_const() const noexcept
199 {
200  return (type_ == CREF);
201 }
202 
203 
204 template<class T>
205 inline bool Foam::tmp<T>::is_pointer() const noexcept
206 {
207  //OR: return (type_ == PTR || type_ == CACHE_PTR);
208  return (type_ < REF_Types);
209 }
210 
211 
212 template<class T>
213 inline bool Foam::tmp<T>::is_reference() const noexcept
214 {
215  //OR: return (type_ == CREF || type_ == REF);
216  return (type_ > REF_Types);
217 }
218 
219 
220 template<class T>
221 inline bool Foam::tmp<T>::movable() const noexcept
222 {
223  return (ptr_ && type_ == PTR && ptr_->refCount::unique());
224 }
225 
226 
227 template<class T>
228 inline const T& Foam::tmp<T>::cref() const
229 {
230  if (!ptr_ && is_pointer())
231  {
233  << this->typeName() << " deallocated"
234  << abort(FatalError);
235  }
236 
237  return *ptr_; // const reference
238 }
239 
240 
241 template<class T>
242 inline T& Foam::tmp<T>::ref() const
243 {
244  if (is_const())
245  {
247  << "Attempted non-const reference to const object: "
248  << this->typeName()
249  << abort(FatalError);
250  }
251  else if (!ptr_ && is_pointer())
252  {
254  << this->typeName() << " deallocated"
255  << abort(FatalError);
256  }
257 
258  return *ptr_; // non-const reference
259 }
260 
261 
262 template<class T>
263 inline T* Foam::tmp<T>::ptr() const
264 {
265  if (!ptr_)
266  {
268  << this->typeName() << " deallocated"
269  << abort(FatalError);
270  }
271 
272  if (type_ == PTR)
273  {
274  if (!ptr_->refCount::unique())
275  {
277  << "Attempt to acquire pointer to object referred to"
278  << " by multiple temporaries of type "
279  << this->typeName()
280  << abort(FatalError);
281  }
282 
283  // Release pointer
284  T* p = ptr_;
285  ptr_ = nullptr;
286 
287  return p;
288  }
290  // CACHE_PTR (immovable) is cloned, as per a reference
291  return ptr_->clone().ptr();
292 }
293 
294 
295 template<class T>
296 inline void Foam::tmp<T>::clear() const noexcept
297 {
298  if (ptr_ && is_pointer())
299  {
300  if (ptr_->refCount::unique())
301  {
302  delete ptr_;
303  }
304  else
305  {
306  ptr_->refCount::operator--();
307  }
308  ptr_ = nullptr;
309  }
310 }
311 
312 
313 template<class T>
314 inline void Foam::tmp<T>::protect(bool on) noexcept
315 {
316  if (on)
317  {
318  // ON: from PTR -> CACHE_PTR, but not nullptr
319  if (ptr_ && type_ == PTR)
320  {
321  type_ = CACHE_PTR;
322  }
323  }
324  else
325  {
326  // OFF: from CACHE_PTR -> PTR
327  if (type_ == CACHE_PTR)
328  {
329  type_ = PTR;
330  }
331  }
332 }
333 
334 
335 template<class T>
336 inline void Foam::tmp<T>::reset(T* p) noexcept
337 {
338  clear();
339  ptr_ = p;
340  type_ = PTR;
341 }
342 
343 
344 template<class T>
345 inline void Foam::tmp<T>::reset(tmp<T>&& other) noexcept
346 {
347  // Could also make Fatal with FULLDEBUG
348  if (&other == this)
349  {
350  return; // No self-assignment
351  }
352 
353  clear();
354  ptr_ = other.ptr_;
355  type_ = other.type_;
356 
357  other.ptr_ = nullptr;
358  other.type_ = PTR;
359 }
360 
361 
362 template<class T>
363 template<class... Args>
364 inline T& Foam::tmp<T>::emplace(Args&&... args)
365 {
366  clear(); // delete old entry
367  ptr_ = new T(std::forward<Args>(args)...);
368  type_ = PTR;
369  return *ptr_;
370 }
371 
372 
373 template<class T>
374 inline void Foam::tmp<T>::cref(const tmp<T>& other) noexcept
375 {
376  // Could also make Fatal with FULLDEBUG
377  if (&other == this)
378  {
379  return; // No self-assignment
380  }
381 
382  clear();
383  ptr_ = other.ptr_;
384  type_ = (ptr_ ? CREF : PTR);
385 }
386 
387 
388 template<class T>
389 inline void Foam::tmp<T>::cref(const T& obj) noexcept
390 {
391  clear();
392  ptr_ = const_cast<T*>(&obj);
393  type_ = CREF;
394 }
395 
396 
397 template<class T>
398 inline void Foam::tmp<T>::cref(const T* p) noexcept
399 {
400  clear();
401  ptr_ = const_cast<T*>(p);
402  type_ = (ptr_ ? CREF : PTR);
403 }
404 
405 
406 template<class T>
407 inline void Foam::tmp<T>::ref(T& obj) noexcept
408 {
409  clear();
410  ptr_ = &obj;
411  type_ = REF;
412 }
413 
414 
415 template<class T>
416 inline void Foam::tmp<T>::ref(T* p) noexcept
417 {
418  clear();
419  ptr_ = p;
420  type_ = (ptr_ ? REF : PTR);
421 }
422 
423 
424 template<class T>
425 inline void Foam::tmp<T>::swap(tmp<T>& other) noexcept
426 {
427  // Swap is just copy/assign for pointer and enum types
428  // Self-swap is effectively ignored
429  T* p = ptr_;
430  ptr_ = other.ptr_;
431  other.ptr_ = p;
432 
433  refType t = type_;
434  type_ = other.type_;
435  other.type_ = t;
436 }
437 
438 
439 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
440 
441 template<class T>
442 inline const T* Foam::tmp<T>::operator->() const
443 {
444  if (!ptr_ && is_pointer())
445  {
447  << this->typeName() << " deallocated"
448  << abort(FatalError);
449  }
450 
451  return ptr_;
452 }
453 
454 
455 template<class T>
456 inline T* Foam::tmp<T>::operator->()
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_ && is_pointer())
466  {
468  << this->typeName() << " deallocated"
469  << abort(FatalError);
470  }
471 
472  return ptr_;
473 }
474 
475 
476 template<class T>
477 inline void Foam::tmp<T>::operator=(const tmp<T>& other)
478 {
479  // Could also make Fatal with FULLDEBUG
480  if (&other == this)
481  {
482  return; // No self-assignment
483  }
484 
485  clear();
486 
487  if (other.is_pointer())
488  {
489  ptr_ = other.ptr_;
490  type_ = other.type_;
491 
492  other.ptr_ = nullptr;
493  other.type_ = PTR;
494 
495  if (!ptr_)
496  {
498  << "Attempted assignment of a deallocated "
499  << this->typeName()
500  << abort(FatalError);
501  }
502  }
503  else
504  {
506  << "Attempted assignment of an object reference of type "
507  << typeid(T).name()
508  << abort(FatalError);
509  }
510 }
511 
512 
513 template<class T>
514 inline void Foam::tmp<T>::operator=(tmp<T>&& other) noexcept
515 {
516  // Could also make Fatal with FULLDEBUG
517  if (&other == this)
518  {
519  return; // No self-assignment
520  }
521 
522  clear();
523  ptr_ = other.ptr_;
524  type_ = other.type_;
526  other.ptr_ = nullptr;
527  other.type_ = PTR;
528 }
529 
530 
531 template<class T>
532 inline void Foam::tmp<T>::operator=(T* p)
533 {
534  if (!p)
535  {
537  << "Attempted copy of a deallocated "
538  << this->typeName()
539  << abort(FatalError);
540  }
541  else if (!p->refCount::unique())
542  {
544  << "Attempted assignment of a "
545  << this->typeName()
546  << " to non-unique pointer"
547  << abort(FatalError);
548  }
549 
550  reset(p);
551 }
552 
553 
554 // ************************************************************************* //
static word typeName()
The type-name, constructed from type-name of T.
Definition: tmpI.H:28
constexpr tmp() noexcept
Construct with no managed pointer.
Definition: tmpI.H:54
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
bool movable() const noexcept
True if this is a non-null managed pointer with a unique ref-count.
Definition: tmpI.H:214
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition: tmpI.H:235
~tmp() noexcept
Destructor: deletes managed pointer when the ref-count is 0.
Definition: tmpI.H:182
const T & cref() const
Return const reference to the object or to the contents of a (non-null) managed pointer.
Definition: tmpI.H:221
void protect(bool on) noexcept
Use specified protection against moving for the managed pointer. No-op for references.
Definition: tmpI.H:307
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
A class for handling words, derived from Foam::string.
Definition: word.H:63
patchWriters clear()
errorManip< error > abort(error &err)
Definition: errorManip.H:139
const T * operator->() const
Dereferences (const) pointer to the managed object.
Definition: tmpI.H:435
void swap(tmp< T > &other) noexcept
Swaps the managed object with other.
Definition: tmpI.H:418
bool is_reference() const noexcept
True if this is a reference (not a pointer)
Definition: tmpI.H:206
const direction noexcept
Definition: Scalar.H:258
const volScalarField & T
void operator=(const tmp< T > &other)
Transfer ownership of the managed pointer.
Definition: tmpI.H:470
bool is_pointer() const noexcept
True if this is a managed pointer (not a reference)
Definition: tmpI.H:198
void clear() const noexcept
If object pointer points to valid object: delete object and set pointer to nullptr.
Definition: tmpI.H:289
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
T & emplace(Args &&... args)
Reset with emplace construction. Return reference to the new content.
Definition: tmpI.H:357
Foam::argList args(argc, argv)
bool is_const() const noexcept
If the stored/referenced content is const.
Definition: tmpI.H:191
void reset(tmp< T > &&other) noexcept
Clear existing and transfer ownership.
Definition: tmpI.H:338