mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
express: support casting between compatible PointerTo types
This makes it possible to implicitly convert a PT of a derived type to a (C)PT of a base type, without needing to first convert it to a regular pointer. This also applies to moves, which are now more efficient due to the lack of need for ref/unref pair even if the pointer type is not exactly the same.
This commit is contained in:
parent
409231d214
commit
23128e4695
@ -39,6 +39,41 @@ PointerTo(PointerTo<T> &&from) noexcept :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CPPPARSER
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE PointerTo<T>::
|
||||||
|
PointerTo(Y *ptr) noexcept :
|
||||||
|
PointerToBase<T>(ptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE PointerTo<T>::
|
||||||
|
PointerTo(const PointerTo<Y> &r) noexcept :
|
||||||
|
PointerToBase<T>(r.p())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE PointerTo<T>::
|
||||||
|
PointerTo(PointerTo<Y> &&r) noexcept :
|
||||||
|
PointerToBase<T>(std::move(r))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif // !CPPPARSER
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -49,6 +84,30 @@ operator = (PointerTo<T> &&from) noexcept {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CPPPARSER
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE PointerTo<T> &PointerTo<T>::
|
||||||
|
operator = (const PointerTo<Y> &r) noexcept {
|
||||||
|
this->reassign(r.p());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE PointerTo<T> &PointerTo<T>::
|
||||||
|
operator = (PointerTo<Y> &&r) noexcept {
|
||||||
|
this->reassign(std::move(r));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif // !CPPPARSER
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -172,6 +231,63 @@ ConstPointerTo(ConstPointerTo<T> &&from) noexcept :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CPPPARSER
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE ConstPointerTo<T>::
|
||||||
|
ConstPointerTo(const Y *ptr) noexcept :
|
||||||
|
PointerToBase<T>((Y *)ptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE ConstPointerTo<T>::
|
||||||
|
ConstPointerTo(const PointerTo<Y> &r) noexcept :
|
||||||
|
PointerToBase<T>(r.p())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE ConstPointerTo<T>::
|
||||||
|
ConstPointerTo(const ConstPointerTo<Y> &r) noexcept :
|
||||||
|
PointerToBase<T>((Y *)r.p())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE ConstPointerTo<T>::
|
||||||
|
ConstPointerTo(PointerTo<Y> &&r) noexcept :
|
||||||
|
PointerToBase<T>(std::move(r))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE ConstPointerTo<T>::
|
||||||
|
ConstPointerTo(ConstPointerTo<Y> &&r) noexcept :
|
||||||
|
PointerToBase<T>(std::move(r))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif // !CPPPARSER
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -192,6 +308,52 @@ operator = (ConstPointerTo<T> &&from) noexcept {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CPPPARSER
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE ConstPointerTo<T> &ConstPointerTo<T>::
|
||||||
|
operator = (const PointerTo<Y> &r) noexcept {
|
||||||
|
this->reassign(r.p());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE ConstPointerTo<T> &ConstPointerTo<T>::
|
||||||
|
operator = (const ConstPointerTo<Y> &r) noexcept {
|
||||||
|
this->reassign((Y *)r.p());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE ConstPointerTo<T> &ConstPointerTo<T>::
|
||||||
|
operator = (PointerTo<Y> &&r) noexcept {
|
||||||
|
this->reassign(std::move(r));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE ConstPointerTo<T> &ConstPointerTo<T>::
|
||||||
|
operator = (ConstPointerTo<Y> &&r) noexcept {
|
||||||
|
this->reassign(std::move(r));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif // !CPPPARSER
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -77,8 +77,21 @@ PUBLISHED:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
INLINE PointerTo(PointerTo<T> &&from) noexcept;
|
INLINE PointerTo(PointerTo<T> &&from) noexcept;
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE explicit PointerTo(Y *ptr) noexcept;
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE PointerTo(const PointerTo<Y> &r) noexcept;
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE PointerTo(PointerTo<Y> &&r) noexcept;
|
||||||
|
|
||||||
INLINE PointerTo<T> &operator = (PointerTo<T> &&from) noexcept;
|
INLINE PointerTo<T> &operator = (PointerTo<T> &&from) noexcept;
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE PointerTo<T> &operator = (const PointerTo<Y> &r) noexcept;
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE PointerTo<T> &operator = (PointerTo<Y> &&r) noexcept;
|
||||||
|
|
||||||
constexpr To &operator *() const noexcept;
|
constexpr To &operator *() const noexcept;
|
||||||
constexpr To *operator -> () const noexcept;
|
constexpr To *operator -> () const noexcept;
|
||||||
// MSVC.NET 2005 insists that we use T *, and not To *, here.
|
// MSVC.NET 2005 insists that we use T *, and not To *, here.
|
||||||
@ -141,9 +154,30 @@ PUBLISHED:
|
|||||||
public:
|
public:
|
||||||
INLINE ConstPointerTo(PointerTo<T> &&from) noexcept;
|
INLINE ConstPointerTo(PointerTo<T> &&from) noexcept;
|
||||||
INLINE ConstPointerTo(ConstPointerTo<T> &&from) noexcept;
|
INLINE ConstPointerTo(ConstPointerTo<T> &&from) noexcept;
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE explicit ConstPointerTo(const Y *ptr) noexcept;
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE ConstPointerTo(const PointerTo<Y> &r) noexcept;
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE ConstPointerTo(const ConstPointerTo<Y> &r) noexcept;
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE ConstPointerTo(PointerTo<Y> &&r) noexcept;
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE ConstPointerTo(ConstPointerTo<Y> &&r) noexcept;
|
||||||
|
|
||||||
INLINE ConstPointerTo<T> &operator = (PointerTo<T> &&from) noexcept;
|
INLINE ConstPointerTo<T> &operator = (PointerTo<T> &&from) noexcept;
|
||||||
INLINE ConstPointerTo<T> &operator = (ConstPointerTo<T> &&from) noexcept;
|
INLINE ConstPointerTo<T> &operator = (ConstPointerTo<T> &&from) noexcept;
|
||||||
|
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE ConstPointerTo<T> &operator = (const PointerTo<Y> &r) noexcept;
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE ConstPointerTo<T> &operator = (const ConstPointerTo<Y> &r) noexcept;
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE ConstPointerTo<T> &operator = (PointerTo<Y> &&r) noexcept;
|
||||||
|
template<class Y>
|
||||||
|
ALWAYS_INLINE ConstPointerTo<T> &operator = (ConstPointerTo<Y> &&r) noexcept;
|
||||||
|
|
||||||
constexpr const To &operator *() const noexcept;
|
constexpr const To &operator *() const noexcept;
|
||||||
constexpr const To *operator -> () const noexcept;
|
constexpr const To *operator -> () const noexcept;
|
||||||
constexpr operator const T *() const noexcept;
|
constexpr operator const T *() const noexcept;
|
||||||
|
@ -44,11 +44,24 @@ PointerToBase(const PointerToBase<T> ©) {
|
|||||||
*/
|
*/
|
||||||
template<class T>
|
template<class T>
|
||||||
INLINE PointerToBase<T>::
|
INLINE PointerToBase<T>::
|
||||||
~PointerToBase() {
|
PointerToBase(PointerToBase<T> &&from) noexcept {
|
||||||
if (_void_ptr != nullptr) {
|
_void_ptr = from._void_ptr;
|
||||||
unref_delete((To *)_void_ptr);
|
from._void_ptr = nullptr;
|
||||||
_void_ptr = nullptr;
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
template<class Y>
|
||||||
|
INLINE PointerToBase<T>::
|
||||||
|
PointerToBase(PointerToBase<Y> &&r) noexcept {
|
||||||
|
// If this next line gives an error, you are trying to convert a PointerTo
|
||||||
|
// from an incompatible type of another PointerTo.
|
||||||
|
To *ptr = (Y *)r._void_ptr;
|
||||||
|
|
||||||
|
this->_void_ptr = ptr;
|
||||||
|
r._void_ptr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,9 +69,11 @@ INLINE PointerToBase<T>::
|
|||||||
*/
|
*/
|
||||||
template<class T>
|
template<class T>
|
||||||
INLINE PointerToBase<T>::
|
INLINE PointerToBase<T>::
|
||||||
PointerToBase(PointerToBase<T> &&from) noexcept {
|
~PointerToBase() {
|
||||||
_void_ptr = from._void_ptr;
|
if (_void_ptr != nullptr) {
|
||||||
from._void_ptr = nullptr;
|
unref_delete((To *)_void_ptr);
|
||||||
|
_void_ptr = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,6 +99,31 @@ reassign(PointerToBase<T> &&from) noexcept {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like above, but casts from a compatible pointer type.
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
template<class Y>
|
||||||
|
INLINE void PointerToBase<T>::
|
||||||
|
reassign(PointerToBase<Y> &&from) noexcept {
|
||||||
|
// Protect against self-move-assignment.
|
||||||
|
if (from._void_ptr != this->_void_ptr) {
|
||||||
|
To *old_ptr = (To *)this->_void_ptr;
|
||||||
|
|
||||||
|
// If there is a compile error on this line, it means you tried to assign
|
||||||
|
// an incompatible type.
|
||||||
|
To *new_ptr = (Y *)from._void_ptr;
|
||||||
|
|
||||||
|
this->_void_ptr = new_ptr;
|
||||||
|
from._void_ptr = nullptr;
|
||||||
|
|
||||||
|
// Now delete the old pointer.
|
||||||
|
if (old_ptr != nullptr) {
|
||||||
|
unref_delete(old_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the main work of the PointerTo family. When the pointer is
|
* This is the main work of the PointerTo family. When the pointer is
|
||||||
* reassigned, decrement the old reference count and increment the new one.
|
* reassigned, decrement the old reference count and increment the new one.
|
||||||
|
@ -35,17 +35,25 @@ protected:
|
|||||||
INLINE PointerToBase(To *ptr);
|
INLINE PointerToBase(To *ptr);
|
||||||
INLINE PointerToBase(const PointerToBase<T> ©);
|
INLINE PointerToBase(const PointerToBase<T> ©);
|
||||||
INLINE PointerToBase(PointerToBase<T> &&from) noexcept;
|
INLINE PointerToBase(PointerToBase<T> &&from) noexcept;
|
||||||
|
template<class Y>
|
||||||
|
INLINE PointerToBase(PointerToBase<Y> &&r) noexcept;
|
||||||
|
|
||||||
INLINE ~PointerToBase();
|
INLINE ~PointerToBase();
|
||||||
|
|
||||||
INLINE void reassign(To *ptr);
|
INLINE void reassign(To *ptr);
|
||||||
INLINE void reassign(const PointerToBase<To> ©);
|
INLINE void reassign(const PointerToBase<To> ©);
|
||||||
INLINE void reassign(PointerToBase<To> &&from) noexcept;
|
INLINE void reassign(PointerToBase<To> &&from) noexcept;
|
||||||
|
template<class Y>
|
||||||
|
INLINE void reassign(PointerToBase<Y> &&from) noexcept;
|
||||||
|
|
||||||
INLINE void update_type(To *ptr);
|
INLINE void update_type(To *ptr);
|
||||||
|
|
||||||
// No assignment or retrieval functions are declared in PointerToBase,
|
// No assignment or retrieval functions are declared in PointerToBase,
|
||||||
// because we will have to specialize on const vs. non-const later.
|
// because we will have to specialize on const vs. non-const later.
|
||||||
|
|
||||||
|
// This is needed to be able to access the privates of other instantiations.
|
||||||
|
template<typename Y> friend class PointerToBase;
|
||||||
|
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
ALWAYS_INLINE void clear();
|
ALWAYS_INLINE void clear();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user