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...
};