mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 08:44:19 -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;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
#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:
|
||||
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;
|
||||
|
||||
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;
|
||||
// MSVC.NET 2005 insists that we use T *, and not To *, here.
|
||||
@ -141,9 +154,30 @@ PUBLISHED:
|
||||
public:
|
||||
INLINE ConstPointerTo(PointerTo<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 = (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 operator const T *() const noexcept;
|
||||
|
@ -44,11 +44,24 @@ PointerToBase(const PointerToBase<T> ©) {
|
||||
*/
|
||||
template<class T>
|
||||
INLINE PointerToBase<T>::
|
||||
~PointerToBase() {
|
||||
if (_void_ptr != nullptr) {
|
||||
unref_delete((To *)_void_ptr);
|
||||
_void_ptr = nullptr;
|
||||
}
|
||||
PointerToBase(PointerToBase<T> &&from) noexcept {
|
||||
_void_ptr = from._void_ptr;
|
||||
from._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>
|
||||
INLINE PointerToBase<T>::
|
||||
PointerToBase(PointerToBase<T> &&from) noexcept {
|
||||
_void_ptr = from._void_ptr;
|
||||
from._void_ptr = nullptr;
|
||||
~PointerToBase() {
|
||||
if (_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
|
||||
* reassigned, decrement the old reference count and increment the new one.
|
||||
|
@ -35,17 +35,25 @@ protected:
|
||||
INLINE PointerToBase(To *ptr);
|
||||
INLINE PointerToBase(const PointerToBase<T> ©);
|
||||
INLINE PointerToBase(PointerToBase<T> &&from) noexcept;
|
||||
template<class Y>
|
||||
INLINE PointerToBase(PointerToBase<Y> &&r) noexcept;
|
||||
|
||||
INLINE ~PointerToBase();
|
||||
|
||||
INLINE void reassign(To *ptr);
|
||||
INLINE void reassign(const PointerToBase<To> ©);
|
||||
INLINE void reassign(PointerToBase<To> &&from) noexcept;
|
||||
template<class Y>
|
||||
INLINE void reassign(PointerToBase<Y> &&from) noexcept;
|
||||
|
||||
INLINE void update_type(To *ptr);
|
||||
|
||||
// No assignment or retrieval functions are declared in PointerToBase,
|
||||
// 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:
|
||||
ALWAYS_INLINE void clear();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user