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 Foam::tmp<T>::tmp(bool immovable, T* p)
95 :
96  tmp<T>(p)
97 {
98  if (ptr_ && immovable) type_ = CACHE_PTR;
99 }
100 
101 
102 template<class T>
103 inline constexpr Foam::tmp<T>::tmp(const T& obj) noexcept
104 :
105  ptr_(const_cast<T*>(&obj)),
106  type_(CREF)
107 {}
108 
109 
110 template<class T>
111 inline Foam::tmp<T>::tmp(tmp<T>&& rhs) noexcept
112 :
113  ptr_(rhs.ptr_),
114  type_(rhs.type_)
115 {
116  rhs.ptr_ = nullptr;
117  rhs.type_ = PTR;
118 }
119 
120 
121 template<class T>
122 inline Foam::tmp<T>::tmp(const tmp<T>&& rhs) noexcept
123 :
124  ptr_(rhs.ptr_),
125  type_(rhs.type_)
126 {
127  rhs.ptr_ = nullptr;
128  rhs.type_ = PTR;
129 }
130 
131 
132 template<class T>
133 inline Foam::tmp<T>::tmp(const tmp<T>& rhs)
134 :
135  ptr_(rhs.ptr_),
136  type_(rhs.type_)
137 {
138  if (is_pointer())
139  {
140  if (ptr_)
141  {
142  ptr_->refCount::operator++();
143  this->checkUseCount();
144  }
145  else
146  {
148  << "Attempted copy/move of a deallocated "
149  << this->typeName()
151  }
152  }
153 }
154 
155 
156 template<class T>
157 inline Foam::tmp<T>::tmp(const tmp<T>& rhs, bool reuse)
158 :
159  ptr_(rhs.ptr_),
160  type_(rhs.type_)
161 {
162  if (is_pointer())
163  {
164  if (ptr_)
165  {
166  if (reuse)
167  {
168  rhs.ptr_ = nullptr;
169  rhs.type_ = PTR;
170  }
171  else
172  {
173  ptr_->refCount::operator++();
174  this->checkUseCount();
175  }
176  }
177  else
178  {
180  << "Attempted copy/move of a deallocated "
181  << this->typeName()
183  }
184  }
185 }
186 
187 
188 template<class T>
189 inline Foam::tmp<T>::tmp(autoPtr<T>&& rhs) noexcept
190 :
191  tmp<T>(rhs.release())
192 {}
193 
194 
195 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
196 
197 template<class T>
199 {
200  clear();
201 }
202 
203 
204 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
205 
206 template<class T>
207 inline bool Foam::tmp<T>::is_const() const noexcept
208 {
209  return (type_ == CREF);
210 }
211 
212 
213 template<class T>
214 inline bool Foam::tmp<T>::is_pointer() const noexcept
215 {
216  //OR: return (type_ == PTR || type_ == CACHE_PTR);
217  return (type_ < REF_Types);
218 }
219 
220 
221 template<class T>
222 inline bool Foam::tmp<T>::is_reference() const noexcept
223 {
224  //OR: return (type_ == CREF || type_ == REF);
225  return (type_ > REF_Types);
226 }
227 
228 
229 template<class T>
230 inline bool Foam::tmp<T>::movable() const noexcept
231 {
232  return (ptr_ && type_ == PTR && ptr_->refCount::unique());
233 }
234 
235 
236 template<class T>
237 inline const T& Foam::tmp<T>::cref() const
238 {
239  if (!ptr_ && is_pointer())
240  {
242  << this->typeName() << " deallocated"
243  << abort(FatalError);
244  }
245 
246  return *ptr_; // const reference
247 }
248 
249 
250 template<class T>
251 inline T& Foam::tmp<T>::ref() const
252 {
253  if (is_const())
254  {
256  << "Attempted non-const reference to const object: "
257  << this->typeName()
258  << abort(FatalError);
259  }
260  else if (!ptr_ && is_pointer())
261  {
263  << this->typeName() << " deallocated"
264  << abort(FatalError);
265  }
266 
267  return *ptr_; // non-const reference
268 }
269 
270 
271 template<class T>
272 inline T* Foam::tmp<T>::ptr() const
273 {
274  if (!ptr_)
275  {
277  << this->typeName() << " deallocated"
278  << abort(FatalError);
279  }
280 
281  if (type_ == PTR)
282  {
283  if (!ptr_->refCount::unique())
284  {
286  << "Attempt to acquire pointer to object referred to"
287  << " by multiple temporaries of type "
288  << this->typeName()
289  << abort(FatalError);
290  }
291 
292  // Release pointer
293  T* p = ptr_;
294  ptr_ = nullptr;
295 
296  return p;
297  }
299  // CACHE_PTR (immovable) is cloned, as per a reference
300  return ptr_->clone().ptr();
301 }
302 
303 
304 template<class T>
305 inline void Foam::tmp<T>::clear() const noexcept
306 {
307  if (ptr_ && is_pointer())
308  {
309  if (ptr_->refCount::unique())
310  {
311  delete ptr_;
312  }
313  else
314  {
315  ptr_->refCount::operator--();
316  }
317  ptr_ = nullptr;
318  }
319 }
320 
321 
322 template<class T>
323 inline void Foam::tmp<T>::reset(T* p) noexcept
324 {
325  clear();
326  ptr_ = p;
327  type_ = PTR;
328 }
329 
330 
331 template<class T>
332 inline void Foam::tmp<T>::reset(bool immovable, T* p) noexcept
333 {
334  reset(p);
335  if (ptr_ && immovable) type_ = CACHE_PTR;
336 }
337 
338 
339 template<class T>
340 inline void Foam::tmp<T>::reset(tmp<T>&& other) noexcept
341 {
342  // Could also make Fatal with FULLDEBUG
343  if (&other == this)
344  {
345  return; // No self-assignment
346  }
347 
348  clear();
349  ptr_ = other.ptr_;
350  type_ = other.type_;
352  other.ptr_ = nullptr;
353  other.type_ = PTR;
354 }
355 
356 
357 template<class T>
358 inline void Foam::tmp<T>::cref(const tmp<T>& other) noexcept
359 {
360  // Could also make Fatal with FULLDEBUG
361  if (&other == this)
362  {
363  return; // No self-assignment
364  }
365 
366  clear();
367  ptr_ = other.ptr_;
368  type_ = (ptr_ ? CREF : PTR);
369 }
370 
371 
372 template<class T>
373 inline void Foam::tmp<T>::cref(const T& obj) noexcept
374 {
375  clear();
376  ptr_ = const_cast<T*>(&obj);
377  type_ = CREF;
378 }
379 
380 
381 template<class T>
382 inline void Foam::tmp<T>::cref(const T* p) noexcept
383 {
384  clear();
385  ptr_ = const_cast<T*>(p);
386  type_ = (ptr_ ? CREF : PTR);
387 }
388 
389 
390 template<class T>
391 inline void Foam::tmp<T>::ref(T& obj) noexcept
392 {
393  clear();
394  ptr_ = &obj;
395  type_ = REF;
396 }
397 
398 
399 template<class T>
400 inline void Foam::tmp<T>::ref(T* p) noexcept
401 {
402  clear();
403  ptr_ = p;
404  type_ = (ptr_ ? REF : PTR);
405 }
406 
407 
408 template<class T>
409 inline void Foam::tmp<T>::swap(tmp<T>& other) noexcept
410 {
411  // Swap is just copy/assign for pointer and enum types
412  // Self-swap is effectively ignored
413  T* p = ptr_;
414  ptr_ = other.ptr_;
415  other.ptr_ = p;
416 
417  refType t = type_;
418  type_ = other.type_;
419  other.type_ = t;
420 }
421 
422 
423 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
424 
425 template<class T>
426 inline const T* Foam::tmp<T>::operator->() const
427 {
428  if (!ptr_ && is_pointer())
429  {
431  << this->typeName() << " deallocated"
432  << abort(FatalError);
433  }
434 
435  return ptr_;
436 }
437 
438 
439 template<class T>
440 inline T* Foam::tmp<T>::operator->()
441 {
442  if (is_const())
443  {
445  << "Attempt to cast const object to non-const: "
446  << this->typeName()
447  << abort(FatalError);
448  }
449  else if (!ptr_ && is_pointer())
450  {
452  << this->typeName() << " deallocated"
453  << abort(FatalError);
454  }
455 
456  return ptr_;
457 }
458 
459 
460 template<class T>
461 inline void Foam::tmp<T>::operator=(const tmp<T>& other)
462 {
463  // Could also make Fatal with FULLDEBUG
464  if (&other == this)
465  {
466  return; // No self-assignment
467  }
468 
469  clear();
470 
471  if (other.is_pointer())
472  {
473  ptr_ = other.ptr_;
474  type_ = other.type_;
475 
476  other.ptr_ = nullptr;
477  other.type_ = PTR;
478 
479  if (!ptr_)
480  {
482  << "Attempted assignment of a deallocated "
483  << this->typeName()
484  << abort(FatalError);
485  }
486  }
487  else
488  {
490  << "Attempted assignment of an object reference of type "
491  << typeid(T).name()
492  << abort(FatalError);
493  }
494 }
495 
496 
497 template<class T>
498 inline void Foam::tmp<T>::operator=(tmp<T>&& other) noexcept
499 {
500  // Could also make Fatal with FULLDEBUG
501  if (&other == this)
502  {
503  return; // No self-assignment
504  }
505 
506  clear();
507  ptr_ = other.ptr_;
508  type_ = other.type_;
510  other.ptr_ = nullptr;
511  other.type_ = PTR;
512 }
513 
514 
515 template<class T>
516 inline void Foam::tmp<T>::operator=(T* p)
517 {
518  if (!p)
519  {
521  << "Attempted copy of a deallocated "
522  << this->typeName()
523  << abort(FatalError);
524  }
525  else if (!p->refCount::unique())
526  {
528  << "Attempted assignment of a "
529  << this->typeName()
530  << " to non-unique pointer"
531  << abort(FatalError);
532  }
533 
534  reset(p);
535 }
536 
537 
538 // ************************************************************************* //
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:578
bool movable() const noexcept
True if this is a non-null managed pointer with a unique ref-count.
Definition: tmpI.H:223
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition: tmpI.H:244
~tmp() noexcept
Destructor: deletes managed pointer when the ref-count is 0.
Definition: tmpI.H:191
const T & cref() const
Return const reference to the object or to the contents of a (non-null) managed pointer.
Definition: tmpI.H:230
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
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:419
void swap(tmp< T > &other) noexcept
Swaps the managed object with other.
Definition: tmpI.H:402
bool is_reference() const noexcept
True if this is a reference (not a pointer)
Definition: tmpI.H:215
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:454
bool is_pointer() const noexcept
True if this is a managed pointer (not a reference)
Definition: tmpI.H:207
void clear() const noexcept
If object pointer points to valid object: delete object and set pointer to nullptr.
Definition: tmpI.H:298
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
bool is_const() const noexcept
If the stored/referenced content is const.
Definition: tmpI.H:200
void reset(tmp< T > &&other) noexcept
Clear existing and transfer ownership.
Definition: tmpI.H:333