tmpI.H 9.49 KB
Newer Older
Henry Weller's avatar
Henry Weller committed
1
/*---------------------------------------------------------------------------*\
2
3
4
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
OpenFOAM bot's avatar
OpenFOAM bot committed
5
    \\  /    A nd           | www.openfoam.com
OpenFOAM bot's avatar
OpenFOAM bot committed
6
7
     \\/     M anipulation  |
-------------------------------------------------------------------------------
OpenFOAM bot's avatar
OpenFOAM bot committed
8
9
    Copyright (C) 2011-2017 OpenFOAM Foundation
    Copyright (C) 2018-2019 OpenCFD Ltd.
10
11
12
13
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

14
15
16
17
    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
18
19
20
21
22
23
24

    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.

    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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// * * * * * * * * * * * * * Private Member Operators  * * * * * * * * * * * //

template<class T>
inline void Foam::tmp<T>::operator++()
{
    ptr_->operator++();

    if (ptr_->count() > 1)
    {
        FatalErrorInFunction
            << "Attempt to create more than 2 tmp's referring to"
               " the same object of type " << typeName()
            << abort(FatalError);
    }
}


49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //

template<class T>
template<class... Args>
inline Foam::tmp<T> Foam::tmp<T>::New(Args&&... args)
{
    return tmp<T>(new T(std::forward<Args>(args)...));
}


template<class T>
template<class U, class... Args>
inline Foam::tmp<T> Foam::tmp<T>::NewFrom(Args&&... args)
{
    return tmp<T>(new U(std::forward<Args>(args)...));
}


67
68
69
// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //

template<class T>
70
inline constexpr Foam::tmp<T>::tmp() noexcept
71
:
72
    ptr_(nullptr),
73
74
75
76
77
78
79
80
81
    type_(PTR)
{}


template<class T>
inline constexpr Foam::tmp<T>::tmp(std::nullptr_t) noexcept
:
    ptr_(nullptr),
    type_(PTR)
82
83
84
85
86
87
{}


template<class T>
inline Foam::tmp<T>::tmp(T* p)
:
88
    ptr_(p),
89
    type_(PTR)
90
{
91
    if (p && !p->unique())
92
93
94
95
96
97
98
    {
        FatalErrorInFunction
            << "Attempted construction of a " << typeName()
            << " from non-unique pointer"
            << abort(FatalError);
    }
}
99
100


101
template<class T>
102
inline Foam::tmp<T>::tmp(const T& obj) noexcept
103
:
104
105
    ptr_(const_cast<T*>(&obj)),
    type_(CREF)
106
107
108
{}


109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
template<class T>
inline Foam::tmp<T>::tmp(tmp<T>&& t) noexcept
:
    ptr_(t.ptr_),
    type_(t.type_)
{
    t.ptr_ = nullptr;
    t.type_ = PTR;
}


template<class T>
inline Foam::tmp<T>::tmp(const tmp<T>&& t) noexcept
:
    ptr_(t.ptr_),
    type_(t.type_)
{
    t.ptr_ = nullptr;
    t.type_ = PTR;
}


131
template<class T>
Mark Olesen's avatar
Mark Olesen committed
132
inline Foam::tmp<T>::tmp(const tmp<T>& t)
133
:
134
135
    ptr_(t.ptr_),
    type_(t.type_)
136
{
137
    if (isTmp())
138
139
140
    {
        if (ptr_)
        {
141
            operator++();
142
143
144
        }
        else
        {
145
            FatalErrorInFunction
146
                << "Attempted copy of a deallocated " << typeName()
147
148
149
150
151
152
                << abort(FatalError);
        }
    }
}


153
template<class T>
154
inline Foam::tmp<T>::tmp(const tmp<T>& t, bool reuse)
155
:
156
157
    ptr_(t.ptr_),
    type_(t.type_)
158
{
159
    if (isTmp())
160
    {
161
        if (ptr_)
162
        {
163
            if (reuse)
164
            {
165
                t.ptr_ = nullptr; // t.type_ already set as PTR
166
167
168
            }
            else
            {
169
                operator++();
170
171
            }
        }
172
173
174
175
176
177
        else
        {
            FatalErrorInFunction
                << "Attempted copy of a deallocated " << typeName()
                << abort(FatalError);
        }
178
179
180
181
    }
}


182
template<class T>
Mark Olesen's avatar
Mark Olesen committed
183
inline Foam::tmp<T>::~tmp()
184
{
185
    clear();
186
187
188
189
190
191
}


// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //

template<class T>
192
inline bool Foam::tmp<T>::isTmp() const noexcept
193
{
194
    return type_ == PTR;
195
196
197
}


198
template<class T>
199
inline bool Foam::tmp<T>::empty() const noexcept
200
{
201
    return (!ptr_ && isTmp());
202
203
204
}


205
template<class T>
206
inline bool Foam::tmp<T>::valid() const noexcept
207
{
208
209
210
211
212
    return (ptr_ || type_ == CREF);
}


template<class T>
213
inline bool Foam::tmp<T>::movable() const noexcept
214
215
{
    return (type_ == PTR && ptr_ && ptr_->unique());
216
217
218
}


219
220
221
222
223
224
225
template<class T>
inline Foam::word Foam::tmp<T>::typeName() const
{
    return "tmp<" + word(typeid(T).name()) + '>';
}


226
227
228
229
230
231
232
233
234
235
236
237
238
239
template<class T>
inline T* Foam::tmp<T>::get() noexcept
{
    return ptr_; // non-const pointer
}


template<class T>
inline const T* Foam::tmp<T>::get() const noexcept
{
    return ptr_; // const pointer
}


240
template<class T>
241
inline const T& Foam::tmp<T>::cref() const
242
{
243
    if (isTmp())
244
245
246
247
    {
        if (!ptr_)
        {
            FatalErrorInFunction
248
                << typeName() << " deallocated"
249
250
                << abort(FatalError);
        }
251
    }
252

253
254
255
256
257
258
259
260
261
262
    return *ptr_; // const reference
}


template<class T>
inline T& Foam::tmp<T>::ref() const
{
    if (isTmp())
    {
        if (!ptr_)
263
264
        {
            FatalErrorInFunction
265
                << typeName() << " deallocated"
266
267
                << abort(FatalError);
        }
268
269
270
271
272
273
274
275
    }
    else
    {
        FatalErrorInFunction
            << "Attempted non-const reference to const object from a "
            << typeName()
            << abort(FatalError);
    }
276

277
278
    return *ptr_; // non-const reference
}
279

280
281
282
283
284
285
286
287
288

template<class T>
inline T& Foam::tmp<T>::constCast() const
{
    if (isTmp() && !ptr_)
    {
        FatalErrorInFunction
            << typeName() << " deallocated"
            << abort(FatalError);
289
    }
290

291
    return const_cast<T&>(*ptr_);
292
293
294
295
}


template<class T>
296
inline T* Foam::tmp<T>::ptr() const
297
{
298
    if (isTmp())
299
    {
300
301
302
        if (!ptr_)
        {
            FatalErrorInFunction
303
                << typeName() << " deallocated"
304
305
                << abort(FatalError);
        }
306
307
308
309
310
311
312
313
314
315
316
317
        else if (!ptr_->unique())
        {
            FatalErrorInFunction
                << "Attempt to acquire pointer to object referred to"
                << " by multiple temporaries of type " << typeName()
                << abort(FatalError);
        }

        T* ptr = ptr_;
        ptr_ = nullptr;

        return ptr;
318
    }
319

320
    return ptr_->clone().ptr();
321
322
323
324
}


template<class T>
325
inline void Foam::tmp<T>::clear() const noexcept
326
{
327
    if (isTmp() && ptr_)
328
    {
329
330
331
332
333
334
335
336
        if (ptr_->unique())
        {
            delete ptr_;
        }
        else
        {
            ptr_->operator--();
        }
337
        ptr_ = nullptr;
338
339
340
341
    }
}


342
template<class T>
343
inline void Foam::tmp<T>::reset() noexcept
344
345
346
347
348
349
350
351
{
    clear();
    ptr_ = nullptr;
    type_ = PTR;
}


template<class T>
352
inline void Foam::tmp<T>::reset(T* p) noexcept
353
354
355
356
357
358
359
{
    clear();
    ptr_ = p;
    type_ = PTR;
}


360
361
362
363
364
365
366
367
368
template<class T>
inline void Foam::tmp<T>::cref(const T& obj) noexcept
{
    clear();
    ptr_ = const_cast<T*>(&obj);
    type_ = CREF;
}


369
370
371
template<class T>
inline void Foam::tmp<T>::swap(tmp<T>& other) noexcept
{
372
373
374
375
376
    if (&other == this)
    {
        return;  // Self-swap is a no-op
    }

377
378
379
380
381
382
383
384
385
386
387
    // Copy/assign for pointer types
    T* p = ptr_;
    ptr_ = other.ptr_;
    other.ptr_ = p;

    refType t = type_;
    type_ = other.type_;
    other.type_ = t;
}


388
389
390
// * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //

template<class T>
Mark Olesen's avatar
Mark Olesen committed
391
inline const T& Foam::tmp<T>::operator()() const
392
{
393
    return cref();
394
395
396
397
}


template<class T>
Mark Olesen's avatar
Mark Olesen committed
398
inline Foam::tmp<T>::operator const T&() const
399
{
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
    return cref();
}


template<class T>
inline const T* Foam::tmp<T>::operator->() const
{
    if (!ptr_ && isTmp())
    {
        FatalErrorInFunction
            << typeName() << " deallocated"
            << abort(FatalError);
    }

    return ptr_;
415
416
417
418
}


template<class T>
Mark Olesen's avatar
Mark Olesen committed
419
inline T* Foam::tmp<T>::operator->()
420
{
421
    if (isTmp())
422
    {
423
424
425
426
427
428
        if (!ptr_)
        {
            FatalErrorInFunction
                << typeName() << " deallocated"
                << abort(FatalError);
        }
429
430
431
    }
    else
    {
432
433
        FatalErrorInFunction
            << "Attempt to cast const object to non-const for a " << typeName()
434
            << abort(FatalError);
435
    }
436
437

    return ptr_;
438
439
440
441
}


template<class T>
442
inline void Foam::tmp<T>::operator=(T* p)
443
{
444
445
    clear();

446
    if (!p)
447
    {
448
449
450
        FatalErrorInFunction
            << "Attempted copy of a deallocated " << typeName()
            << abort(FatalError);
451
    }
452
    else if (!p->unique())
453
    {
454
        FatalErrorInFunction
455
456
            << "Attempted assignment of a " << typeName()
            << " to non-unique pointer"
457
458
            << abort(FatalError);
    }
459

460
    ptr_ = p;
461
    type_ = PTR;
462
463
464
465
466
467
}


template<class T>
inline void Foam::tmp<T>::operator=(const tmp<T>& t)
{
468
469
470
471
472
    if (&t == this)
    {
        return;  // Self-assignment is a no-op
    }

473
    clear();
474

475
    if (t.isTmp())
476
    {
477
478
479
        ptr_ = t.ptr_;
        type_ = PTR;
        t.ptr_ = nullptr;
480

481
        if (!ptr_)
482
        {
483
            FatalErrorInFunction
484
                << "Attempted assignment to a deallocated " << typeName()
485
486
487
488
489
                << abort(FatalError);
        }
    }
    else
    {
490
        FatalErrorInFunction
491
            << "Attempted assignment to a const reference to an object"
492
            << " of type " << typeid(T).name()
493
494
495
496
497
498
            << abort(FatalError);
    }
}


// ************************************************************************* //