I’ve recently been trying out shared_ptr and I’ve run across a bit of a weird case. What I want is a template member function which is capable of returning a shared_ptr of its derived type. I’m running visual studio 2010 which has access to some of the new c++0x standard, but I assume the boost shared_ptr behaves similarly.
This worked fine with bare pointers. I just returned a dynamic_cast<DerivedClass*>(this). I’m kind of stumped here, however, because even using enable_shared_from_this the object attempts to delete itself after the function is called (which is bad). I am probably approaching this wrong, but I’d like to work out how to simulate the bare pointer equivalent (which was working) of the following (this is the code I’m having trouble with).
//assume we have a virtual function as well.
class BaseClass : public std::enable_shared_from_this<BaseClass>
{
....
template<typename DerivedClass>
std::shared_ptr<DerivedClass> BaseClass::getThis(){
//I had some assert code here to ensure typeid matched
return std::dynamic_pointer_cast<DerivedClass>(shared_from_this());
}
}
edit: It seems the function works correctly, the problem was with how I was using it. It is bad, for example to do the following:
std::shared_ptr<DerivedClass> p = std::make_shared<DerivedClass>();
p->getType<DerivedClass>->someOtherFunctionOnlyInTheDerivedClass();
This is not a problem:
std::shared_ptr<BaseClass> p = std::make_shared<DerivedClass>();
p->getType<DerivedClass>->someOtherFunctionOnlyInTheDerivedClass();
I’m not entirely sure if it’s a problem with converting to the same type, or a reference counting issue. In any case, I was doing something dumb and it broke, avoiding the unnecessary getType call at that point seems to work fine in every other case I am using it. Maybe someone can explain precisely what causes the first example to break with the second example working. I’ll assign points to that answer.
To expand on Stuart’s answer and to (possibly) explain why you were crashing, my best guess is that you were calling
getTypeon a stack-alloc’d instance. It’s a major pitfall to usingenable_shared_from_this.The reason this occurs is because the reference count of
d2is zero when it’s on the stack. Callingshared_from_thisreturns ashared_ptrthat increments the reference count to one. Once this pointer goes out of scope, it decrements its count to zero, which then attempts to delete the instance, which, of course, is on the stack.The only way that I can think of protecting yourself from this, off the top of my head, is to make all constructors protected or private and provide static functions that dynamically allocate any instances, returning
shared_ptrs, of course.