/*========================================================================= Program: Visualization Toolkit Module: vtkSmartPointer.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /** * @class vtkSmartPointer * @brief Hold a reference to a vtkObjectBase instance. * * vtkSmartPointer is a class template that provides automatic casting * for objects held by the vtkSmartPointerBase superclass. */ #ifndef vtkSmartPointer_h #define vtkSmartPointer_h #include "vtkSmartPointerBase.h" #include "vtkMeta.h" // for IsComplete #include "vtkNew.h" // for vtkNew.h #include // for is_base_of #include // for std::move template class vtkSmartPointer : public vtkSmartPointerBase { // These static asserts only fire when the function calling CheckTypes is // used. Thus, this smart pointer class may still be used as a member variable // with a forward declared T, so long as T is defined by the time the calling // function is used. template static void CheckTypes() noexcept { static_assert(vtk::detail::IsComplete::value, "vtkSmartPointer's T type has not been defined. Missing " "include?"); static_assert(vtk::detail::IsComplete::value, "Cannot store an object with undefined type in " "vtkSmartPointer. Missing include?"); static_assert(std::is_base_of::value, "Argument type is not compatible with vtkSmartPointer's " "T type."); static_assert(std::is_base_of::value, "vtkSmartPointer can only be used with subclasses of " "vtkObjectBase."); } public: /** * Initialize smart pointer to nullptr. */ vtkSmartPointer() noexcept : vtkSmartPointerBase() {} /** * Initialize smart pointer with a new reference to the same object * referenced by given smart pointer. * @{ */ // Need both overloads because the copy-constructor must be non-templated: vtkSmartPointer(const vtkSmartPointer& r) : vtkSmartPointerBase(r) { } template vtkSmartPointer(const vtkSmartPointer& r) : vtkSmartPointerBase(r) { vtkSmartPointer::CheckTypes(); } /* @} **/ /** * Move the contents of @a r into @a this. * @{ */ // Need both overloads because the move-constructor must be non-templated: vtkSmartPointer(vtkSmartPointer&& r) noexcept : vtkSmartPointerBase(std::move(r)) {} template vtkSmartPointer(vtkSmartPointer&& r) noexcept : vtkSmartPointerBase(std::move(r)) { vtkSmartPointer::CheckTypes(); } /**@}*/ /** * Initialize smart pointer to given object. * @{ */ vtkSmartPointer(T* r) : vtkSmartPointerBase(r) { vtkSmartPointer::CheckTypes(); } template vtkSmartPointer(const vtkNew& r) : vtkSmartPointerBase(r.Object) { // Create a new reference on copy vtkSmartPointer::CheckTypes(); } //@} /** * Move the pointer from the vtkNew smart pointer to the new vtkSmartPointer, * stealing its reference and resetting the vtkNew object to nullptr. */ template vtkSmartPointer(vtkNew&& r) noexcept : vtkSmartPointerBase(r.Object, vtkSmartPointerBase::NoReference{}) { // Steal the reference on move vtkSmartPointer::CheckTypes(); r.Object = nullptr; } //@{ /** * Assign object to reference. This removes any reference to an old * object. */ // Need this since the compiler won't recognize template functions as // assignment operators. vtkSmartPointer& operator=(const vtkSmartPointer& r) { this->vtkSmartPointerBase::operator=(r.GetPointer()); return *this; } template vtkSmartPointer& operator=(const vtkSmartPointer& r) { vtkSmartPointer::CheckTypes(); this->vtkSmartPointerBase::operator=(r.GetPointer()); return *this; } //@} /** * Assign object to reference. This removes any reference to an old * object. */ template vtkSmartPointer& operator=(const vtkNew& r) { vtkSmartPointer::CheckTypes(); this->vtkSmartPointerBase::operator=(r.Object); return *this; } /** * Assign object to reference. This adds a new reference to an old * object. */ template vtkSmartPointer& operator=(U* r) { vtkSmartPointer::CheckTypes(); this->vtkSmartPointerBase::operator=(r); return *this; } //@{ /** * Get the contained pointer. */ T* GetPointer() const noexcept { return static_cast(this->Object); } T* Get() const noexcept { return static_cast(this->Object); } //@} /** * Get the contained pointer. */ operator T*() const noexcept { return static_cast(this->Object); } /** * Dereference the pointer and return a reference to the contained * object. */ T& operator*() const noexcept { return *static_cast(this->Object); } /** * Provides normal pointer target member access using operator ->. */ T* operator->() const noexcept { return static_cast(this->Object); } /** * Transfer ownership of one reference to the given VTK object to * this smart pointer. This does not increment the reference count * of the object, but will decrement it later. The caller is * effectively passing ownership of one reference to the smart * pointer. This is useful for code like: * vtkSmartPointer foo; * foo.TakeReference(bar->NewFoo()); * The input argument may not be another smart pointer. */ void TakeReference(T* t) { *this = vtkSmartPointer(t, NoReference()); } /** * Create an instance of a VTK object. */ static vtkSmartPointer New() { return vtkSmartPointer(T::New(), NoReference()); } /** * Create a new instance of the given VTK object. */ static vtkSmartPointer NewInstance(T* t) { return vtkSmartPointer(t->NewInstance(), NoReference()); } /** * Transfer ownership of one reference to the given VTK object to a * new smart pointer. The returned smart pointer does not increment * the reference count of the object on construction but will * decrement it on destruction. The caller is effectively passing * ownership of one reference to the smart pointer. This is useful * for code like: * vtkSmartPointer foo = * vtkSmartPointer::Take(bar->NewFoo()); * The input argument may not be another smart pointer. */ static vtkSmartPointer Take(T* t) { return vtkSmartPointer(t, NoReference()); } // Work-around for HP and IBM overload resolution bug. Since // NullPointerOnly is a private type the only pointer value that can // be passed by user code is a null pointer. This operator will be // chosen by the compiler when comparing against null explicitly and // avoid the bogus ambiguous overload error. #if defined(__HP_aCC) || defined(__IBMCPP__) #define VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(op) \ bool operator op(NullPointerOnly*) const { return ::operator op(*this, 0); } private: class NullPointerOnly { }; public: VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(==) VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(!=) VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(<) VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(<=) VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(>) VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(>=) #undef VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND #endif protected: vtkSmartPointer(T* r, const NoReference& n) : vtkSmartPointerBase(r, n) { } private: // These are purposely not implemented to prevent callers from // trying to take references from other smart pointers. void TakeReference(const vtkSmartPointerBase&) = delete; static void Take(const vtkSmartPointerBase&) = delete; }; #define VTK_SMART_POINTER_DEFINE_OPERATOR(op) \ template \ inline bool operator op(const vtkSmartPointer& l, const vtkSmartPointer& r) \ { \ return (l.GetPointer() op r.GetPointer()); \ } \ template \ inline bool operator op(T* l, const vtkSmartPointer& r) \ { \ return (l op r.GetPointer()); \ } \ template \ inline bool operator op(const vtkSmartPointer& l, U* r) \ { \ return (l.GetPointer() op r); \ } \ template \ inline bool operator op(const vtkNew& l, const vtkSmartPointer& r) \ { \ return (l.GetPointer() op r.GetPointer()); \ } \ template \ inline bool operator op(const vtkSmartPointer& l, const vtkNew& r) \ { \ return (l.GetPointer() op r.GetPointer); \ } /** * Compare smart pointer values. */ VTK_SMART_POINTER_DEFINE_OPERATOR(==) VTK_SMART_POINTER_DEFINE_OPERATOR(!=) VTK_SMART_POINTER_DEFINE_OPERATOR(<) VTK_SMART_POINTER_DEFINE_OPERATOR(<=) VTK_SMART_POINTER_DEFINE_OPERATOR(>) VTK_SMART_POINTER_DEFINE_OPERATOR(>=) #undef VTK_SMART_POINTER_DEFINE_OPERATOR namespace vtk { /// Construct a vtkSmartPointer containing @a obj. A new reference is added /// to @a obj. template vtkSmartPointer MakeSmartPointer(T* obj) { return vtkSmartPointer{ obj }; } /// Construct a vtkSmartPointer containing @a obj. @a obj's reference count /// is not changed. template vtkSmartPointer TakeSmartPointer(T* obj) { return vtkSmartPointer::Take(obj); } } // end namespace vtk /** * Streaming operator to print smart pointer like regular pointers. */ template inline ostream& operator<<(ostream& os, const vtkSmartPointer& p) { return os << static_cast(p); } #endif // VTK-HeaderTest-Exclude: vtkSmartPointer.h