
If I have: class Base { }; class Derived : public Base { }; And a container, e.g.: std::vector<boost::shared_ptr<Base> > objs; How do I downcast to a shared_ptr<Derived>? E.g.: boost::shared_ptr<Derived> d = (boost::shared_ptr<Derived>)objs[0]; I have a function that takes a shared_ptr<Derived> and all I have is a shared_ptr<Base>. I don't mind static_cast behavior, although dynamic_cast behavior would be ideal. Thanks, Jason

Research is showing this isn't possible. I'm sure there's a good reason for it... but I need to get this working. I came up with this hack that works but is scary. Assuming there is no virtual inheritance involve (this would have the same semantics as reinterpret_cast): template <typename Dest, typename Src> shared_ptr<Dest> shared_reinterpret_cast (const shared_ptr<Src> &src) { shared_ptr<Src> hack(src); shared_ptr<Dest> dest; assert(sizeof(hack) == sizeof(dest)); char buf[sizeof(dest)]; // swap dest and hack memcpy(buf, &dest, sizeof(dest)); memcpy(&dest, &hack, sizeof(dest)); memcpy(&hack, buf, sizeof(hack)); return dest; } It's really dirty, but will it work OK? The basic idea is to swap a new shared_ptr<Base> with an empty shared_ptr<Derived>, but bypass shared_ptr::swap()'s type checking. Jason On Tue, Dec 23, 2008 at 4:36 AM, Jason Cipriani <jason.cipriani@gmail.com> wrote:
If I have:
class Base { }; class Derived : public Base { };
And a container, e.g.:
std::vector<boost::shared_ptr<Base> > objs;
How do I downcast to a shared_ptr<Derived>? E.g.:
boost::shared_ptr<Derived> d = (boost::shared_ptr<Derived>)objs[0];
I have a function that takes a shared_ptr<Derived> and all I have is a shared_ptr<Base>. I don't mind static_cast behavior, although dynamic_cast behavior would be ideal.
Thanks, Jason

On Tue, Dec 23, 2008 at 4:54 AM, Jason Cipriani <jason.cipriani@gmail.com> wrote:
Research is showing this isn't possible. I'm sure there's a good reason for it... but I need to get this working. I came up with this hack that works but is scary. Assuming there is no virtual inheritance involve (this would have the same semantics as reinterpret_cast):
template <typename Dest, typename Src> shared_ptr<Dest> shared_reinterpret_cast (const shared_ptr<Src> &src) {
shared_ptr<Src> hack(src); shared_ptr<Dest> dest;
assert(sizeof(hack) == sizeof(dest)); char buf[sizeof(dest)];
// swap dest and hack memcpy(buf, &dest, sizeof(dest)); memcpy(&dest, &hack, sizeof(dest)); memcpy(&hack, buf, sizeof(hack));
return dest;
}
Scratch that, this seems safer: template <typename Dest, typename Src> shared_ptr<Dest> shared_reinterpret_cast (const shared_ptr<Src> &src) { shared_ptr<Src> hack(src); return *(shared_ptr<Dest> *)&hack; } The first attempt would cause problems if shared_ptr's implementation stored a pointer to itself, for some reason, or gave it's address to some other shared_ptr. Jason
It's really dirty, but will it work OK? The basic idea is to swap a new shared_ptr<Base> with an empty shared_ptr<Derived>, but bypass shared_ptr::swap()'s type checking.
Jason
On Tue, Dec 23, 2008 at 4:36 AM, Jason Cipriani <jason.cipriani@gmail.com> wrote:
If I have:
class Base { }; class Derived : public Base { };
And a container, e.g.:
std::vector<boost::shared_ptr<Base> > objs;
How do I downcast to a shared_ptr<Derived>? E.g.:
boost::shared_ptr<Derived> d = (boost::shared_ptr<Derived>)objs[0];
I have a function that takes a shared_ptr<Derived> and all I have is a shared_ptr<Base>. I don't mind static_cast behavior, although dynamic_cast behavior would be ideal.
Thanks, Jason

Hello, Quoting Jason Cipriani <jason.cipriani@gmail.com>:
How do I downcast to a shared_ptr<Derived>? E.g.:
Isn't dynamic_pointer_cast what you are looking for ? http://www.boost.org/doc/libs/1_37_0/libs/smart_ptr/shared_ptr.htm#functions I hope it helps, -- Vincent Jacques "S'il n'y a pas de solution, c'est qu'il n'y a pas de problème" Devise Shadock

2008/12/23 Jason Cipriani <jason.cipriani@gmail.com>:
If I have:
class Base { }; class Derived : public Base { };
And a container, e.g.:
std::vector<boost::shared_ptr<Base> > objs;
How do I downcast to a shared_ptr<Derived>? E.g.:
boost::shared_ptr<Derived> d = (boost::shared_ptr<Derived>)objs[0];
Look at boost::static_pointer_cast

Igor R wrote:
2008/12/23 Jason Cipriani <jason.cipriani@gmail.com>:
If I have:
class Base { }; class Derived : public Base { };
And a container, e.g.:
std::vector<boost::shared_ptr<Base> > objs;
How do I downcast to a shared_ptr<Derived>? E.g.:
boost::shared_ptr<Derived> d = (boost::shared_ptr<Derived>)objs[0];
Look at boost::static_pointer_cast
using class polymorphism boost::dynamic_pointer_cast is better. You can also iterate on our vector as if the elements are of type Derivated with a code like this : typedef std::vector<boost::shared_ptr<Base> > VectorBase; template < class SubClass> struct DownCaster : public std::unary_function< boost::shared_ptr< Base >, boost::shared_ptr< SubClass> > { boost::shared_ptr< SubClass> operator()( boost::shared_ptr< Base > obj ) const { return boost::dynamic_pointer_cast< SubClass >( obj ); } }; typedef typename boost::transform_iterator< DownCaster<Derived> , VectorBase::iterator > CastIterator; CastIterator start( objs.begin() ); boost::shared_ptr<Derived> d = *start; // is OK

2008/12/23 Vincent Agnus <vincent.agnus@ircad.fr>:
Igor R wrote:
2008/12/23 Jason Cipriani <jason.cipriani@gmail.com>:
If I have:
class Base { }; class Derived : public Base { };
And a container, e.g.:
std::vector<boost::shared_ptr<Base> > objs;
How do I downcast to a shared_ptr<Derived>? E.g.:
boost::shared_ptr<Derived> d = (boost::shared_ptr<Derived>)objs[0];
Look at boost::static_pointer_cast
using class polymorphism boost::dynamic_pointer_cast is better.
Thanks, this is exactly what I wanted. Jason
You can also iterate on our vector as if the elements are of type Derivated with a code like this :
typedef std::vector<boost::shared_ptr<Base> > VectorBase;
template < class SubClass> struct DownCaster : public std::unary_function< boost::shared_ptr< Base >, boost::shared_ptr< SubClass> > { boost::shared_ptr< SubClass> operator()( boost::shared_ptr< Base > obj ) const { return boost::dynamic_pointer_cast< SubClass >( obj ); } };
typedef typename boost::transform_iterator< DownCaster<Derived> , VectorBase::iterator > CastIterator;
CastIterator start( objs.begin() );
boost::shared_ptr<Derived> d = *start; // is OK
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (4)
-
Igor R
-
Jason Cipriani
-
Vincent Agnus
-
Vincent Jacques