A wrong program in boost-user mail list:
Totally, For enable_shared_from_this to work, the static type of the pointer passed to the shared_ptr constructor must inherit from enable_shared_from_this.
shared_ptr's constructor in line 168 calls 'boost::detail::sp_enable_shared_from_this( pn, p, p );'.
'boost::shared_ptr<IDerived> c(new Derived());' is dispatched to 'sp_enable_shared_from_this' in line 86. pay attension to the second parameter, it can accept all types that inherit 'enable_shared_from_this<T>', so does 'Derived*'.
While, 'boost::shared_ptr<IDerived> c((IDerived*)new Derived());' is dispatched to 'sp_enable_shared_from_this' in line 111, bacause the static type IDerived* has nothing to do with 'enable_shared_from_this<T>' and can not be implicitly converted to 'enable_shared_from_this<T>'.
Then check out the difference between the two 'sp_enable_shared_from_this'. It is obvious that the second usage shall cause a BOOST_ASSERT failed in 'enable_shared_from_this::shared_from_this', so an exception is raised.
However, I think the root reason is not the language nor boost, but the design of class IDerived. Its root and root1 seem a little bit irrational because there is not direct relationship between IDerived and Base(IBase).
#include <iostream>
#include <memory>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
// Inheritance Layout
//
// boost::enable_shared_from_this<T>
// ^
// |
// Base --------> IBase
// ^
// |
// Derived -----> IDerived
class IBase
{
public:
virtual ~IBase(){}
virtual void hello(void) = 0;
};
class Base : public IBase, public boost::enable_shared_from_this<Base>
{
public:
~Base(void){}
void hello(void)
{
std::cout << "Hello" << std::endl;
}
};
class IDerived
{
public:
virtual boost::shared_ptr<Base> root(void) = 0;
virtual boost::shared_ptr<IBase> root2(void) = 0;
};
class Derived : public IDerived, public Base
{
public:
~Derived(void){}
virtual boost::shared_ptr<Base> root(void)
{
return shared_from_this();
}
virtual boost::shared_ptr<IBase> root2(void)
{
return shared_from_this();
}
};
int main(int argc, char* argv[])
{
boost::shared_ptr<IDerived> c(new Derived());
boost::shared_ptr<IBase> d = c->root2();
boost::shared_ptr<Base> e = c->root();
std::cout << c.use_count() << std::endl;
boost::shared_ptr<IDerived> l ((IDerived*)new Derived);
boost::shared_ptr<Base> n = l->root();//here throws an exception
boost::shared_ptr<IBase> m = l->root2();//also here
std::cout << m.use_count() << std::endl;
return 0;
}
Totally, For enable_shared_from_this to work, the static type of the pointer passed to the shared_ptr constructor must inherit from enable_shared_from_this.
shared_ptr's constructor in line 168 calls 'boost::detail::sp_enable_shared_from_this( pn, p, p );'.
'boost::shared_ptr<IDerived> c(new Derived());' is dispatched to 'sp_enable_shared_from_this' in line 86. pay attension to the second parameter, it can accept all types that inherit 'enable_shared_from_this<T>', so does 'Derived*'.
While, 'boost::shared_ptr<IDerived> c((IDerived*)new Derived());' is dispatched to 'sp_enable_shared_from_this' in line 111, bacause the static type IDerived* has nothing to do with 'enable_shared_from_this<T>' and can not be implicitly converted to 'enable_shared_from_this<T>'.
Then check out the difference between the two 'sp_enable_shared_from_this'. It is obvious that the second usage shall cause a BOOST_ASSERT failed in 'enable_shared_from_this::shared_from_this', so an exception is raised.
However, I think the root reason is not the language nor boost, but the design of class IDerived. Its root and root1 seem a little bit irrational because there is not direct relationship between IDerived and Base(IBase).