Dynamic and reinterpret casting of SharedPtr
Posted: Mon Oct 12, 2009 7:32 pm
Hi,
Just when I was working with Ogre::SharedPtr<T> I found that it would be very useful if SharedPtr's could be dynamically cast'ed.
For e.g.:
There is two major barriers with the current code and that is SharedPtr<Derived> cannot access SharedPtr<BaseClass> protected members, because they're considered as two separate classes according the compiler and the second problem is that dynamic casting is not done to convert the BaseClass pointer to DerivedClass pointer.
Making certain changes to the SharedPtr class, I believe can make this possible. And this is not a huge change. And what I'm proposing is not a new thing. It's something done in boost::shared_ptr. Here are the list of changes I was thinking would make that possible
1. Make a private 'dummy' structure in SharedPtr to indicate that a dynamic cast request is being made when constructing
2. Make a private constructor that would accept an instance of the 'dummy' structure and that constructor that do the dynamic_cast operation.
3. Make template<typename Y> SharedPtr a friend class so that any type of SharedPtr instance can access the protected members.
The change is shown below...
I'm not entirely sure if this piece of code is portable. But I believe it will be useful and maybe more tweaks can be done to make this code better. The same can be done to perform reinterpret_cast.
Just when I was working with Ogre::SharedPtr<T> I found that it would be very useful if SharedPtr's could be dynamically cast'ed.
For e.g.:
Code: Select all
Ogre::SharedPtr<BaseClass> ptr(new DerivedClass);
//... later in another function
Ogre::SharedPtr<Derived> derived_ptr = Ogre::SharedPtr::DynamicCast<Derived>(ptr);
Making certain changes to the SharedPtr class, I believe can make this possible. And this is not a huge change. And what I'm proposing is not a new thing. It's something done in boost::shared_ptr. Here are the list of changes I was thinking would make that possible
1. Make a private 'dummy' structure in SharedPtr to indicate that a dynamic cast request is being made when constructing
2. Make a private constructor that would accept an instance of the 'dummy' structure and that constructor that do the dynamic_cast operation.
3. Make template<typename Y> SharedPtr a friend class so that any type of SharedPtr instance can access the protected members.
The change is shown below...
Code: Select all
template <typename T>
class SharedPtr
{
private:
// Declaring that 'any' type of SharedPtr is friend of any other type
template<typename Y> friend class SharedPtr;
// The dummy structure that is used to make the call to the constructor that will do dynamic casting
struct DynamicCastRequest{};
// The constructor that will do dynamic casting of the pointer stored in the other SharedPtr type.
template<typename Y>SharedPtr(const SharedPtr<Y>& r, const DynamicCastRequest& d)
: pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE)
{
// lock & copy other mutex pointer
OGRE_SET_AUTO_SHARED_MUTEX_NULL
OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
// This is now possible because SharedPtr<Y> is a friend class of SharedPtr<T> and viceversa
pRep = dynamic_cast<T*>(r.pRep);
if(pRep)
{
pUseCount = r.pUseCount;
}
useFreeMethod = r.useFreeMethod;
if(pUseCount)
{
++(*pUseCount);
}
}
public:
// .... rest of the class code...
template<typename Y>
static SharedPtr<T> DynamicCast(const SharedPtr<Y>& r)
{
return SharedPtr<T>(r, DynamicCastRequest());
}
// ... remaining class code...
};