/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkAutoPointer_h #define itkAutoPointer_h #include "itkMacro.h" #include namespace itk { /** \class AutoPointer * \brief Implements an Automatic Pointer to an object. * * AutoPointer is intended to facilitate the construction of * objects on the fly for those objects that are not to be shared. * An AutoPointer destroys its object when it goes out of scope. * Ownership of the object is transferred from one AutoPointer * to another AutoPointer when the assignment operator is used. * An AutoPointer can release ownership of the object it holds. * * This class follows the design of the std::unique_ptr (auto_ptr being * deprecated in C++11) class. The main * reason for not using the std * version is to avoid templated methods, which greatly increase the * difficulty of wrapping for Tcl, Python and Java. * * \ingroup ITKSystemObjects * \ingroup DataAccess * \ingroup ITKCommon */ template class AutoPointer { public: /** Extract information from template parameter. */ using ObjectType = TObjectType; using Self = AutoPointer; /** Constructor. */ AutoPointer() : m_Pointer(nullptr) {} /** Copy constructor. */ explicit AutoPointer(AutoPointer & p) { m_IsOwner = p.IsOwner(); // Ownership can only be taken from // another owner m_Pointer = p.ReleaseOwnership(); // release ownership if appropriate } /** Constructor to pointer p. */ explicit AutoPointer(ObjectType * p, bool takeOwnership) : m_Pointer(p) , m_IsOwner(takeOwnership) {} /** Destructor. */ ~AutoPointer() { this->Reset(); } /** Overload operator ->. */ ObjectType * operator->() const { return m_Pointer; } /** Clear the AutoPointer. If it had a pointer the object is deleted and the pointer is set to null. */ void Reset() { if (m_IsOwner) { delete m_Pointer; } m_Pointer = nullptr; m_IsOwner = false; } /** Explicitly set the ownership */ void TakeOwnership() { m_IsOwner = true; } /** Explicitly set the ownership */ void TakeOwnership(ObjectType * objectptr) { if (m_IsOwner) { delete m_Pointer; // remove the current one } m_Pointer = objectptr; m_IsOwner = true; } /** Explicitly reject ownership */ void TakeNoOwnership(ObjectType * objectptr) { if (m_IsOwner) { delete m_Pointer; // remove the current one } m_Pointer = objectptr; m_IsOwner = false; } /** Query for the ownership */ bool IsOwner() const { return m_IsOwner; } /** Release the pointer hold by the current AutoPointer * and return the raw pointer so it can be hold by * another AutoPointer. This operation is intended to * be used for facilitating polymorphism. * * Example: if class Cow derives from Mammal, * AutoPointer onecow = new Cow; * AutoPointer onemammal = onecow.ReleaseOwnership(); * * Note that the AutoPointer still points to the object after the * ReleaseOwnership operation, but it doesn't own the object any * more. */ ObjectType * ReleaseOwnership() { m_IsOwner = false; return m_Pointer; } /** Access function to pointer. */ ObjectType * GetPointer() const { return m_Pointer; } /** Comparison of pointers. Equal comparison. */ bool operator==(const AutoPointer & r) const { return (void *)m_Pointer == (void *)r.m_Pointer; } ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(Self); /** Comparison of pointers. Less than comparison. */ bool operator<(const AutoPointer & r) const { return (void *)m_Pointer < (void *)r.m_Pointer; } /** Comparison of pointers. Greater than comparison. */ bool operator>(const AutoPointer & r) const { return (void *)m_Pointer > (void *)r.m_Pointer; } /** Comparison of pointers. Less than or equal to comparison. */ bool operator<=(const AutoPointer & r) const { return (void *)m_Pointer <= (void *)r.m_Pointer; } /** Comparison of pointers. Greater than or equal to comparison. */ bool operator>=(const AutoPointer & r) const { return (void *)m_Pointer >= (void *)r.m_Pointer; } /** Overload operator assignment. */ AutoPointer & operator=(AutoPointer & r) { AutoPointer(r).Swap(*this); return *this; } /** Casting operator to boolean. This is used in conditional statements to check the content of the pointer against null */ operator bool() const { return (m_Pointer != nullptr); } /** Function to print object pointed to. */ /* ObjectType *Print (std::ostream& os) const { // This prints the object pointed to by the pointer m_Pointer->Print(os); os << "Owner: " << m_IsOwner << std::endl; return m_Pointer; } */ private: /** Exchange the content of two AutoPointers */ void Swap(AutoPointer & r) noexcept { ObjectType * temp = m_Pointer; m_Pointer = r.m_Pointer; r.m_Pointer = temp; } /** The pointer to the object referred to by this smart pointer. */ ObjectType * m_Pointer; bool m_IsOwner{ false }; }; template std::ostream & operator<<(std::ostream & os, const AutoPointer p) { p.Print(os); os << "Owner: " << p.IsOwner() << std::endl; return os; } /** This templated function is intended to facilitate the transfer between AutoPointers of Derived class to Base class */ template void TransferAutoPointer(TAutoPointerBase & pa, TAutoPointerDerived & pb) { // give a chance to natural polymorphism pa.TakeNoOwnership(pb.GetPointer()); if (pb.IsOwner()) { pa.TakeOwnership(); // pa Take Ownership pb.ReleaseOwnership(); // pb Release Ownership and clears } } } // end namespace itk #endif