You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

312 lines
10 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkWeakPointer.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 vtkWeakPointer
* @brief a weak reference to a vtkObject.
*
* A weak reference to a vtkObject, which means that assigning
* a vtkObject to the vtkWeakPointer does not affect the reference count of the
* vtkObject. However, when the vtkObject is destroyed, the vtkWeakPointer gets
* initialized to nullptr, thus avoiding any dangling references.
*
* \code
* vtkTable *table = vtkTable::New();
* vtkWeakPointer<vtkTable> weakTable = table;
* \endcode
*
* Some time later the table may be deleted, but if it is tested for null then
* the weak pointer will not leave a dangling pointer.
*
* \code
* table->Delete();
* if (weakTable)
* {
* // Never executed as the weak table pointer will be null here
* cout << "Number of columns in table: " << weakTable->GetNumberOfColumns()
* << endl;
* }
* \endcode
*/
#ifndef vtkWeakPointer_h
#define vtkWeakPointer_h
#include "vtkWeakPointerBase.h"
#include "vtkMeta.h" // for IsComplete
#include "vtkNew.h" // for vtkNew
#include <type_traits> // for is_base_of
#include <utility> // for std::move
template <class T>
class vtkWeakPointer : public vtkWeakPointerBase
{
// 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 <typename U = T>
static void CheckTypes() noexcept
{
static_assert(vtk::detail::IsComplete<T>::value,
"vtkWeakPointer<T>'s T type has not been defined. Missing "
"include?");
static_assert(vtk::detail::IsComplete<U>::value,
"Cannot store an object with undefined type in "
"vtkWeakPointer. Missing include?");
static_assert(std::is_base_of<T, U>::value,
"Argument type is not compatible with vtkWeakPointer<T>'s "
"T type.");
static_assert(std::is_base_of<vtkObjectBase, T>::value,
"vtkWeakPointer can only be used with subclasses of "
"vtkObjectBase.");
}
public:
/**
* Initialize smart pointer to nullptr.
*/
vtkWeakPointer() noexcept : vtkWeakPointerBase() {}
/**
* Initialize smart pointer with the given smart pointer.
* @{
*/
vtkWeakPointer(const vtkWeakPointer& r)
: vtkWeakPointerBase(r)
{
}
template <class U>
vtkWeakPointer(const vtkWeakPointer<U>& r)
: vtkWeakPointerBase(r)
{
vtkWeakPointer::CheckTypes<U>();
}
/* @} **/
/**
* Move r's object into the new weak pointer, setting r to nullptr.
* @{
*/
vtkWeakPointer(vtkWeakPointer&& r) noexcept : vtkWeakPointerBase(std::move(r)) {}
template <class U>
vtkWeakPointer(vtkWeakPointer<U>&& r) noexcept : vtkWeakPointerBase(std::move(r))
{
vtkWeakPointer::CheckTypes<U>();
}
/* @} **/
/**
* Initialize smart pointer to given object.
* @{
*/
vtkWeakPointer(T* r)
: vtkWeakPointerBase(r)
{
vtkWeakPointer::CheckTypes();
}
template <typename U>
vtkWeakPointer(const vtkNew<U>& r)
: vtkWeakPointerBase(r.Object)
{ // Create a new reference on copy
vtkWeakPointer::CheckTypes<U>();
}
//@}
//@{
/**
* Assign object to reference.
*/
vtkWeakPointer& operator=(const vtkWeakPointer& r)
{
this->vtkWeakPointerBase::operator=(r);
return *this;
}
template <class U>
vtkWeakPointer& operator=(const vtkWeakPointer<U>& r)
{
vtkWeakPointer::CheckTypes<U>();
this->vtkWeakPointerBase::operator=(r);
return *this;
}
//@}
//@{
/**
* Move r's object into this weak pointer, setting r to nullptr.
*/
vtkWeakPointer& operator=(vtkWeakPointer&& r) noexcept
{
this->vtkWeakPointerBase::operator=(std::move(r));
return *this;
}
template <class U>
vtkWeakPointer& operator=(vtkWeakPointer<U>&& r) noexcept
{
vtkWeakPointer::CheckTypes<U>();
this->vtkWeakPointerBase::operator=(std::move(r));
return *this;
}
//@}
//@{
/**
* Assign object to reference.
*/
vtkWeakPointer& operator=(T* r)
{
vtkWeakPointer::CheckTypes();
this->vtkWeakPointerBase::operator=(r);
return *this;
}
template <typename U>
vtkWeakPointer& operator=(const vtkNew<U>& r)
{
vtkWeakPointer::CheckTypes<U>();
this->vtkWeakPointerBase::operator=(r.Object);
return *this;
}
//@}
//@{
/**
* Get the contained pointer.
*/
T* GetPointer() const noexcept { return static_cast<T*>(this->Object); }
T* Get() const noexcept { return static_cast<T*>(this->Object); }
operator T*() const noexcept { return static_cast<T*>(this->Object); }
/**
* Dereference the pointer and return a reference to the contained
* object.
*/
T& operator*() const noexcept { return *static_cast<T*>(this->Object); }
/**
* Provides normal pointer target member access using operator ->.
*/
T* operator->() const noexcept { return static_cast<T*>(this->Object); }
// 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_WEAK_POINTER_DEFINE_OPERATOR_WORKAROUND(op) \
bool operator op(NullPointerOnly*) const { return ::operator op(*this, 0); }
private:
class NullPointerOnly
{
};
public:
VTK_WEAK_POINTER_DEFINE_OPERATOR_WORKAROUND(==)
VTK_WEAK_POINTER_DEFINE_OPERATOR_WORKAROUND(!=)
VTK_WEAK_POINTER_DEFINE_OPERATOR_WORKAROUND(<)
VTK_WEAK_POINTER_DEFINE_OPERATOR_WORKAROUND(<=)
VTK_WEAK_POINTER_DEFINE_OPERATOR_WORKAROUND(>)
VTK_WEAK_POINTER_DEFINE_OPERATOR_WORKAROUND(>=)
#undef VTK_WEAK_POINTER_DEFINE_OPERATOR_WORKAROUND
#endif
protected:
vtkWeakPointer(T* r, const NoReference& n)
: vtkWeakPointerBase(r, n)
{
}
private:
// These are purposely not implemented to prevent callers from
// trying to take references from other smart pointers.
void TakeReference(const vtkWeakPointerBase&) = delete;
static void Take(const vtkWeakPointerBase&) = delete;
};
#define VTK_WEAK_POINTER_DEFINE_OPERATOR(op) \
template <class T, class U> \
inline bool operator op(const vtkWeakPointer<T>& l, const vtkWeakPointer<U>& r) \
{ \
return (l.GetPointer() op r.GetPointer()); \
} \
template <class T, class U> \
inline bool operator op(T* l, const vtkWeakPointer<U>& r) \
{ \
return (l op r.GetPointer()); \
} \
template <class T, class U> \
inline bool operator op(const vtkWeakPointer<T>& l, U* r) \
{ \
return (l.GetPointer() op r); \
} \
template <class T, class U> \
inline bool operator op(const vtkNew<T>& l, const vtkWeakPointer<U>& r) \
{ \
return (l.GetPointer() op r.GetPointer()); \
} \
template <class T, class U> \
inline bool operator op(const vtkWeakPointer<T>& l, const vtkNew<U>& r) \
{ \
return (l.GetPointer() op r.GetPointer); \
}
/**
* Compare smart pointer values.
*/
VTK_WEAK_POINTER_DEFINE_OPERATOR(==)
VTK_WEAK_POINTER_DEFINE_OPERATOR(!=)
VTK_WEAK_POINTER_DEFINE_OPERATOR(<)
VTK_WEAK_POINTER_DEFINE_OPERATOR(<=)
VTK_WEAK_POINTER_DEFINE_OPERATOR(>)
VTK_WEAK_POINTER_DEFINE_OPERATOR(>=)
#undef VTK_WEAK_POINTER_DEFINE_OPERATOR
namespace vtk
{
/// Construct a vtkWeakPointer<T> containing @a obj. @a obj's reference count
/// is not changed.
template <typename T>
vtkWeakPointer<T> TakeWeakPointer(T* obj)
{
return vtkWeakPointer<T>(obj);
}
} // end namespace vtk
/**
* Streaming operator to print smart pointer like regular pointers.
*/
template <class T>
inline ostream& operator<<(ostream& os, const vtkWeakPointer<T>& p)
{
return os << static_cast<const vtkWeakPointerBase&>(p);
}
#endif
// VTK-HeaderTest-Exclude: vtkWeakPointer.h