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-2020 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 // * * * * * * * * * * * * * Private Member Operators * * * * * * * * * * * //
33 
34 template<class T>
35 inline void Foam::tmp<T>::incrCount()
36 {
37  ptr_->operator++();
38 
39  if (ptr_->count() > 1)
40  {
42  << "Attempt to create more than 2 tmp's referring to"
43  " the same object of type "
44  << tmp<T>::typeName()
45  << abort(FatalError);
46  }
47 }
48 
49 
50 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
51 
52 template<class T>
53 template<class... Args>
55 {
56  return tmp<T>(new T(std::forward<Args>(args)...));
57 }
58 
59 
60 template<class T>
61 template<class U, class... Args>
63 {
64  return tmp<T>(new U(std::forward<Args>(args)...));
65 }
66 
67 
68 template<class T>
70 {
71  return "tmp<" + word(typeid(T).name()) + '>';
72 }
73 
74 
75 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
76 
77 template<class T>
78 inline constexpr Foam::tmp<T>::tmp() noexcept
79 :
80  ptr_(nullptr),
81  type_(PTR)
82 {}
83 
84 
85 template<class T>
86 inline constexpr Foam::tmp<T>::tmp(std::nullptr_t) noexcept
87 :
88  ptr_(nullptr),
89  type_(PTR)
90 {}
91 
92 
93 template<class T>
95 :
96  ptr_(p),
97  type_(PTR)
98 {
99  if (p && !p->unique())
100  {
102  << "Attempted construction of a "
103  << this->typeName()
104  << " from non-unique pointer"
105  << abort(FatalError);
106  }
107 }
108 
109 
110 template<class T>
111 inline constexpr Foam::tmp<T>::tmp(const T& obj) noexcept
112 :
113  ptr_(const_cast<T*>(&obj)),
114  type_(CREF)
115 {}
116 
117 
118 template<class T>
119 inline Foam::tmp<T>::tmp(tmp<T>&& rhs) noexcept
120 :
121  ptr_(rhs.ptr_),
122  type_(rhs.type_)
123 {
124  rhs.ptr_ = nullptr;
125  rhs.type_ = PTR;
126 }
127 
128 
129 template<class T>
130 inline Foam::tmp<T>::tmp(const tmp<T>&& rhs) noexcept
131 :
132  ptr_(rhs.ptr_),
133  type_(rhs.type_)
134 {
135  rhs.ptr_ = nullptr;
136  rhs.type_ = PTR;
137 }
138 
139 
140 template<class T>
141 inline Foam::tmp<T>::tmp(const tmp<T>& rhs)
142 :
143  ptr_(rhs.ptr_),
144  type_(rhs.type_)
145 {
146  if (type_ == PTR)
147  {
148  if (ptr_)
149  {
150  this->incrCount();
151  }
152  else
153  {
155  << "Attempted copy of a deallocated "
156  << this->typeName()
157  << abort(FatalError);
158  }
159  }
160 }
161 
162 
163 template<class T>
164 inline Foam::tmp<T>::tmp(const tmp<T>& rhs, bool reuse)
165 :
166  ptr_(rhs.ptr_),
167  type_(rhs.type_)
168 {
169  if (type_ == PTR)
170  {
171  if (ptr_)
172  {
173  if (reuse)
174  {
175  rhs.ptr_ = nullptr;
176  // Note: rhs.type_ already set as PTR
177  }
178  else
179  {
180  this->incrCount();
181  }
182  }
183  else
184  {
186  << "Attempted copy of a deallocated "
187  << this->typeName()
188  << abort(FatalError);
189  }
190  }
191 }
192 
193 
194 template<class T>
196 {
197  clear();
198 }
199 
200 
201 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
202 
203 template<class T>
204 inline bool Foam::tmp<T>::movable() const noexcept
205 {
206  return (type_ == PTR && ptr_ && ptr_->unique());
207 }
208 
209 
210 template<class T>
211 inline const T& Foam::tmp<T>::cref() const
212 {
213  if (type_ == PTR)
214  {
215  if (!ptr_)
216  {
218  << this->typeName() << " deallocated"
219  << abort(FatalError);
220  }
221  }
222 
223  return *ptr_; // const reference
224 }
225 
226 
227 template<class T>
228 inline T& Foam::tmp<T>::ref() const
229 {
230  if (type_ == PTR)
231  {
232  if (!ptr_)
233  {
235  << this->typeName() << " deallocated"
236  << abort(FatalError);
237  }
238  }
239  else if (type_ == CREF)
240  {
242  << "Attempted non-const reference to const object from a "
243  << this->typeName()
244  << abort(FatalError);
245  }
246 
247  return *ptr_; // non-const reference
248 }
249 
250 
251 template<class T>
252 inline T& Foam::tmp<T>::constCast() const
253 {
254  return const_cast<T&>(cref());
255 }
256 
257 
258 template<class T>
259 inline T* Foam::tmp<T>::ptr() const
260 {
261  if (!ptr_)
262  {
264  << this->typeName() << " deallocated"
265  << abort(FatalError);
266  }
267 
268  if (type_ == PTR)
269  {
270  if (!ptr_->unique())
271  {
273  << "Attempt to acquire pointer to object referred to"
274  << " by multiple temporaries of type "
275  << this->typeName()
276  << abort(FatalError);
277  }
278 
279  // Release pointer
280  T* p = ptr_;
281  ptr_ = nullptr;
282 
283  return p;
284  }
285 
286  return ptr_->clone().ptr();
287 }
288 
289 
290 template<class T>
291 inline void Foam::tmp<T>::clear() const noexcept
292 {
293  if (type_ == PTR && ptr_)
294  {
295  if (ptr_->unique())
296  {
297  delete ptr_;
298  }
299  else
300  {
301  ptr_->operator--();
302  }
303  ptr_ = nullptr;
304  }
305 }
306 
307 
308 template<class T>
309 inline void Foam::tmp<T>::reset(T* p) noexcept
310 {
311  clear();
312  ptr_ = p;
313  type_ = PTR;
314 }
315 
316 
317 template<class T>
318 inline void Foam::tmp<T>::reset(tmp<T>&& other) noexcept
319 {
320  if (&other == this)
321  {
322  return; // Self-assignment is a no-op
323  }
324 
325  clear();
326  ptr_ = other.ptr_;
327  type_ = other.type_;
328 
329  other.ptr_ = nullptr;
330  other.type_ = PTR;
331 }
332 
333 
334 template<class T>
335 inline void Foam::tmp<T>::cref(const T& obj) noexcept
336 {
337  clear();
338  ptr_ = const_cast<T*>(&obj);
339  type_ = CREF;
340 }
341 
342 
343 template<class T>
344 inline void Foam::tmp<T>::ref(T& obj) noexcept
345 {
346  clear();
347  ptr_ = &obj;
348  type_ = REF;
349 }
350 
351 
352 template<class T>
353 inline void Foam::tmp<T>::swap(tmp<T>& other) noexcept
354 {
355  // Swap is just copy/assign for pointer and enum types
356  // Self-swap is effectively ignored
357  T* p = ptr_;
358  ptr_ = other.ptr_;
359  other.ptr_ = p;
360 
361  refType t = type_;
362  type_ = other.type_;
363  other.type_ = t;
364 }
365 
366 
367 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
368 
369 template<class T>
370 inline const T* Foam::tmp<T>::operator->() const
371 {
372  if (type_ == PTR)
373  {
374  if (!ptr_)
375  {
377  << this->typeName() << " deallocated"
378  << abort(FatalError);
379  }
380  }
381 
382  return ptr_;
383 }
384 
385 
386 template<class T>
388 {
389  if (type_ == PTR)
390  {
391  if (!ptr_)
392  {
394  << this->typeName() << " deallocated"
395  << abort(FatalError);
396  }
397  }
398  else if (type_ == CREF)
399  {
401  << "Attempt to cast const object to non-const for a "
402  << this->typeName()
403  << abort(FatalError);
404  }
405 
406  return ptr_;
407 }
408 
409 
410 template<class T>
411 inline void Foam::tmp<T>::operator=(const tmp<T>& other)
412 {
413  if (&other == this)
414  {
415  return; // Self-assignment is a no-op
416  }
417 
418  clear();
419 
420  if (other.type_ == PTR)
421  {
422  ptr_ = other.ptr_;
423  type_ = PTR;
424  other.ptr_ = nullptr;
425 
426  if (!ptr_)
427  {
429  << "Attempted assignment of a deallocated "
430  << this->typeName()
431  << abort(FatalError);
432  }
433  }
434  else
435  {
437  << "Attempted assignment of an object reference of type "
438  << typeid(T).name()
439  << abort(FatalError);
440  }
441 }
442 
443 
444 template<class T>
445 inline void Foam::tmp<T>::operator=(tmp<T>&& other) noexcept
446 {
447  if (&other == this)
448  {
449  return; // Self-assignment is a no-op
450  }
451 
452  clear();
453  ptr_ = other.ptr_;
454  type_ = other.type_;
455 
456  other.ptr_ = nullptr;
457  other.type_ = PTR;
458 }
459 
460 
461 template<class T>
463 {
464  if (!p)
465  {
467  << "Attempted copy of a deallocated "
468  << this->typeName()
469  << abort(FatalError);
470  }
471  else if (!p->unique())
472  {
474  << "Attempted assignment of a "
475  << this->typeName()
476  << " to non-unique pointer"
477  << abort(FatalError);
478  }
479 
480  reset(p);
481 }
482 
483 
484 template<class T>
485 inline void Foam::tmp<T>::operator=(std::nullptr_t) noexcept
486 {
487  reset(nullptr);
488 }
489 
490 
491 // ************************************************************************* //
Foam::tmp::operator=
void operator=(const tmp< T > &other)
Transfer ownership of the managed pointer.
Definition: tmpI.H:411
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::tmp::constCast
T & constCast() const
Definition: tmpI.H:252
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::tmp::clear
void clear() const noexcept
Definition: tmpI.H:291
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
Foam::tmp::NewFrom
static tmp< T > NewFrom(Args &&... args)
Construct tmp from derived type with forwarding arguments.
Foam::tmp::typeName
static word typeName()
The type-name, constructed from type-name of T.
Definition: tmpI.H:69
Foam::tmp::ref
T & ref() const
Definition: tmpI.H:228
Foam::tmp::operator->
const T * operator->() const
Dereferences (const) pointer to the managed object.
Definition: tmpI.H:370
error.H
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
Foam::FatalError
error FatalError
Foam::tmp::ptr
T * ptr() const
Return managed pointer for reuse, or clone() the object reference.
Definition: tmpI.H:259
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
T
const volScalarField & T
Definition: createFieldRefs.H:2
U
U
Definition: pEqn.H:72
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:381
clear
patchWriters clear()
Foam::tmp::swap
void swap(tmp< T > &other) noexcept
Swaps the managed object with other.
Definition: tmpI.H:353
Foam::tmp::New
static tmp< T > New(Args &&... args)
Construct tmp of T with forwarding arguments.
Foam::tmp::tmp
constexpr tmp() noexcept
Default construct, no managed pointer.
Definition: tmpI.H:78
Foam::tmp::reset
void reset(T *p=nullptr) noexcept
Delete managed temporary object and set to new given pointer.
Definition: tmpI.H:309
args
Foam::argList args(argc, argv)
Foam::tmp::~tmp
~tmp()
Destructor: deletes managed pointer when the ref-count is 0.
Definition: tmpI.H:195
Foam::tmp::cref
const T & cref() const
Definition: tmpI.H:211
Foam::tmp::movable
bool movable() const noexcept
True if this is a non-null managed pointer with a unique ref-count.
Definition: tmpI.H:204