casting a shared_ptr from void with custom deleter

I'm trying to do something like this: boost::shared_ptr<const Foo> fooPtr( boost::static_pointer_cast<const Foo>(typeErasedFoo), CustomDeleter<const Foo>() ); where typeErasedFoo is of type: boost::shared_ptr<const void> The first statement compiles if I remove the custom deleter, but if I leave it in, I get errors saying: cannot convert parameter 2 from 'CustomDeleter<T>' to 'boost::detail::sp_enable_if_convertible_impl<true>::type' Is there any way to do what I'm trying to do? I no longer need typeErasedFoo after the cast if that helps.

Kenny Riddile:
I'm trying to do something like this:
boost::shared_ptr<const Foo> fooPtr( boost::static_pointer_cast<const Foo>(typeErasedFoo), CustomDeleter<const Foo>() );
where typeErasedFoo is of type:
boost::shared_ptr<const void>
What does CustomDeleter do? There is no constructor that takes another shared_ptr and a deleter. You can either associate a raw pointer with a deleter: shared_ptr( Y* p, D d ); or you can make a copy of another shared_ptr: shared_ptr( shared_ptr<Y> const& r ); Since the two shared_ptr instances now refer to the same object, it is not possible for one of them to use deleter A and for the other to use a deleter B. There only exists a single deleter, which is shared between the two. Depending on what you're trying to do, http://www.boost.org/doc/libs/1_38_0/libs/smart_ptr/sp_techniques.html#anoth... may give you some ideas though.

On Fri, Mar 20, 2009 at 7:03 AM, Peter Dimov <pdimov@pdimov.com> wrote:
Kenny Riddile:
I'm trying to do something like this:
boost::shared_ptr<const Foo> fooPtr( boost::static_pointer_cast<const Foo>(typeErasedFoo), CustomDeleter<const Foo>() );
where typeErasedFoo is of type:
boost::shared_ptr<const void>
Just to clarify Peter's point, deletion policy decisions should be made at initialization time, not as a part of a type conversion. So, your original object construction, which you don't show, should set your custom deleter when you create the pointer that receives your "new Foo". A custom deleter is a part of the underlying "value" of the smart pointer, and as such are preserved across casts, so there shouldn't be a need for the kind of call you're trying to do. The code below demonstrates what I mean: #include <iostream> #include <boost/shared_ptr.hpp> struct Foo{}; struct FooDeleter{ void operator()( Foo* f ) { std::cout << "Goodbye, cruel world!"; delete f; } }; int main() { boost::shared_ptr<Foo> pFoo; { boost::shared_ptr<void> pVoid; { boost::shared_ptr<Foo> pTmp( new Foo, FooDeleter() ); pVoid = pTmp; } pFoo = boost::static_pointer_cast<Foo>( pVoid ); } // emits "Goodbye, cruel world!" when pFoo is destructed. } Naturally, you don't have to use a shared_ptr<Foo> when you first allocate the Foo object, it's perfectly valid for the pTmp variable to be eliminated and simply declare: boost::shared_ptr<void> pVoid( new Foo, FooDeleter() ); HTH, Christopher

Christopher Currie wrote:
On Fri, Mar 20, 2009 at 7:03 AM, Peter Dimov <pdimov@pdimov.com> wrote:
Kenny Riddile:
I'm trying to do something like this:
boost::shared_ptr<const Foo> fooPtr( boost::static_pointer_cast<const Foo>(typeErasedFoo), CustomDeleter<const Foo>() );
where typeErasedFoo is of type:
boost::shared_ptr<const void>
Just to clarify Peter's point, deletion policy decisions should be made at initialization time, not as a part of a type conversion. So, your original object construction, which you don't show, should set your custom deleter when you create the pointer that receives your "new Foo".
A custom deleter is a part of the underlying "value" of the smart pointer, and as such are preserved across casts, so there shouldn't be a need for the kind of call you're trying to do. The code below demonstrates what I mean:
#include <iostream> #include <boost/shared_ptr.hpp>
struct Foo{};
struct FooDeleter{ void operator()( Foo* f ) { std::cout << "Goodbye, cruel world!"; delete f; } };
int main() {
boost::shared_ptr<Foo> pFoo;
{ boost::shared_ptr<void> pVoid;
{ boost::shared_ptr<Foo> pTmp( new Foo, FooDeleter() ); pVoid = pTmp; }
pFoo = boost::static_pointer_cast<Foo>( pVoid );
}
// emits "Goodbye, cruel world!" when pFoo is destructed. }
Naturally, you don't have to use a shared_ptr<Foo> when you first allocate the Foo object, it's perfectly valid for the pTmp variable to be eliminated and simply declare: boost::shared_ptr<void> pVoid( new Foo, FooDeleter() );
HTH, Christopher _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Ya, this all makes perfect sense and I was just being stupid due to lack of sleep. I've got it working now (with much simpler code). Thanks guys!
participants (3)
-
Christopher Currie
-
Kenny Riddile
-
Peter Dimov