/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2018-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. 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. 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 along with OpenFOAM. If not, see . \*---------------------------------------------------------------------------*/ #include "error.H" #include // * * * * * * * * * * * * * Private Member Operators * * * * * * * * * * * // template inline void Foam::tmp::incrCount() { ptr_->operator++(); if (ptr_->count() > 1) { FatalErrorInFunction << "Attempt to create more than 2 tmp's referring to" " the same object of type " << tmp::typeName() << abort(FatalError); } } // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // template template inline Foam::tmp Foam::tmp::New(Args&&... args) { return tmp(new T(std::forward(args)...)); } template template inline Foam::tmp Foam::tmp::NewFrom(Args&&... args) { return tmp(new U(std::forward(args)...)); } template inline Foam::word Foam::tmp::typeName() { return "tmp<" + word(typeid(T).name()) + '>'; } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // template inline constexpr Foam::tmp::tmp() noexcept : ptr_(nullptr), type_(PTR) {} template inline constexpr Foam::tmp::tmp(std::nullptr_t) noexcept : ptr_(nullptr), type_(PTR) {} template inline Foam::tmp::tmp(T* p) : ptr_(p), type_(PTR) { if (p && !p->unique()) { FatalErrorInFunction << "Attempted construction of a " << this->typeName() << " from non-unique pointer" << abort(FatalError); } } template inline constexpr Foam::tmp::tmp(const T& obj) noexcept : ptr_(const_cast(&obj)), type_(CREF) {} template inline Foam::tmp::tmp(tmp&& rhs) noexcept : ptr_(rhs.ptr_), type_(rhs.type_) { rhs.ptr_ = nullptr; rhs.type_ = PTR; } template inline Foam::tmp::tmp(const tmp&& rhs) noexcept : ptr_(rhs.ptr_), type_(rhs.type_) { rhs.ptr_ = nullptr; rhs.type_ = PTR; } template inline Foam::tmp::tmp(const tmp& rhs) : ptr_(rhs.ptr_), type_(rhs.type_) { if (type_ == PTR) { if (ptr_) { this->incrCount(); } else { FatalErrorInFunction << "Attempted copy of a deallocated " << this->typeName() << abort(FatalError); } } } template inline Foam::tmp::tmp(const tmp& rhs, bool reuse) : ptr_(rhs.ptr_), type_(rhs.type_) { if (type_ == PTR) { if (ptr_) { if (reuse) { rhs.ptr_ = nullptr; // Note: rhs.type_ already set as PTR } else { this->incrCount(); } } else { FatalErrorInFunction << "Attempted copy of a deallocated " << this->typeName() << abort(FatalError); } } } // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // template inline Foam::tmp::~tmp() { clear(); } // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template inline bool Foam::tmp::movable() const noexcept { return (type_ == PTR && ptr_ && ptr_->unique()); } template inline const T& Foam::tmp::cref() const { if (type_ == PTR && !ptr_) { FatalErrorInFunction << this->typeName() << " deallocated" << abort(FatalError); } return *ptr_; // const reference } template inline T& Foam::tmp::ref() const { if (is_const()) { FatalErrorInFunction << "Attempted non-const reference to const object: " << this->typeName() << abort(FatalError); } else if (type_ == PTR && !ptr_) { FatalErrorInFunction << this->typeName() << " deallocated" << abort(FatalError); } return *ptr_; // non-const reference } template inline T& Foam::tmp::constCast() const { return const_cast(cref()); } template inline T* Foam::tmp::ptr() const { if (!ptr_) { FatalErrorInFunction << this->typeName() << " deallocated" << abort(FatalError); } if (type_ == PTR) { if (!ptr_->unique()) { FatalErrorInFunction << "Attempt to acquire pointer to object referred to" << " by multiple temporaries of type " << this->typeName() << abort(FatalError); } // Release pointer T* p = ptr_; ptr_ = nullptr; return p; } return ptr_->clone().ptr(); } template inline void Foam::tmp::clear() const noexcept { if (type_ == PTR && ptr_) { if (ptr_->unique()) { delete ptr_; } else { ptr_->operator--(); } ptr_ = nullptr; } } template inline void Foam::tmp::reset(T* p) noexcept { clear(); ptr_ = p; type_ = PTR; } template inline void Foam::tmp::reset(tmp&& other) noexcept { if (&other == this) { return; // Self-assignment is a no-op } clear(); ptr_ = other.ptr_; type_ = other.type_; other.ptr_ = nullptr; other.type_ = PTR; } template inline void Foam::tmp::cref(const tmp& other) noexcept { if (&other == this) { return; // Self-assignment is a no-op } clear(); ptr_ = other.ptr_; type_ = (ptr_ ? CREF : PTR); } template inline void Foam::tmp::cref(const T& obj) noexcept { clear(); ptr_ = const_cast(&obj); type_ = CREF; } template inline void Foam::tmp::cref(const T* p) noexcept { clear(); ptr_ = const_cast(p); type_ = (ptr_ ? CREF : PTR); } template inline void Foam::tmp::ref(T& obj) noexcept { clear(); ptr_ = &obj; type_ = REF; } template inline void Foam::tmp::ref(T* p) noexcept { clear(); ptr_ = p; type_ = (ptr_ ? REF : PTR); } template inline void Foam::tmp::swap(tmp& other) noexcept { // Swap is just copy/assign for pointer and enum types // Self-swap is effectively ignored T* p = ptr_; ptr_ = other.ptr_; other.ptr_ = p; refType t = type_; type_ = other.type_; other.type_ = t; } // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // template inline const T* Foam::tmp::operator->() const { if (type_ == PTR && !ptr_) { FatalErrorInFunction << this->typeName() << " deallocated" << abort(FatalError); } return ptr_; } template inline T* Foam::tmp::operator->() { if (is_const()) { FatalErrorInFunction << "Attempt to cast const object to non-const: " << this->typeName() << abort(FatalError); } else if (type_ == PTR && !ptr_) { FatalErrorInFunction << this->typeName() << " deallocated" << abort(FatalError); } return ptr_; } template inline void Foam::tmp::operator=(const tmp& other) { if (&other == this) { return; // Self-assignment is a no-op } clear(); if (other.type_ == PTR) { ptr_ = other.ptr_; type_ = PTR; other.ptr_ = nullptr; if (!ptr_) { FatalErrorInFunction << "Attempted assignment of a deallocated " << this->typeName() << abort(FatalError); } } else { FatalErrorInFunction << "Attempted assignment of an object reference of type " << typeid(T).name() << abort(FatalError); } } template inline void Foam::tmp::operator=(tmp&& other) noexcept { if (&other == this) { return; // Self-assignment is a no-op } clear(); ptr_ = other.ptr_; type_ = other.type_; other.ptr_ = nullptr; other.type_ = PTR; } template inline void Foam::tmp::operator=(T* p) { if (!p) { FatalErrorInFunction << "Attempted copy of a deallocated " << this->typeName() << abort(FatalError); } else if (!p->unique()) { FatalErrorInFunction << "Attempted assignment of a " << this->typeName() << " to non-unique pointer" << abort(FatalError); } reset(p); } template inline void Foam::tmp::operator=(std::nullptr_t) noexcept { reset(nullptr); } // ************************************************************************* //