[smart_ptr] shared_ptr<T> T destructor required even if a deleter function is provided

Hello, I have compiled the example Preventing delete px.get()and every thing is OK until we use the reset function because shared_ptr<X> request that the destructor of X must be public even if a deleter function is provided. I'm wondering if this is a BUG on the smart pointer library Next follows the trace: ../../../boost/checked_delete.hpp: In function `void boost::checked_delete(T*) [ with T = X]': ../../../boost/detail/shared_count.hpp:91: instantiated from `boost::detail::s hared_count::shared_count(Y*) [with Y = X]' ../../../boost/shared_ptr.hpp:173: instantiated from `boost::shared_ptr< <temp late-parameter-1-1> >::shared_ptr(Y*) [with Y = X, T = X]' ../../../boost/shared_ptr.hpp:394: instantiated from `void boost::shared_ptr< <template-parameter-1-1> >::reset(Y*) [with Y = X, T = X]' test_shared_ptr.cpp:37: instantiated from here test_shared_ptr.cpp:13: error: `X::~X()' is private ../../../boost/checked_delete.hpp:34: error: within this context And here it is the source code #include <boost/shared_ptr.hpp> using namespace boost; class X { private: ~X(){}; class deleter; friend class deleter; class deleter { public: void operator()(X * p) { delete p; } }; public: static shared_ptr<X> create() { shared_ptr<X> px(new X, X::deleter()); return px; } }; int main () { shared_ptr<X> ptr = X::create(); ptr.reset(X::create().get()); return 0; } ______________________ Vicente Juan Botet Escribá

vicente.botet:
Hello,
I have compiled the example Preventing delete px.get()and every thing is OK until we use the reset function because shared_ptr<X> request that the destructor of X must be public even if a deleter function is provided. I'm wondering if this is a BUG on the smart pointer library
...
int main () { shared_ptr<X> ptr = X::create(); ptr.reset(X::create().get()); return 0; }
shared_ptr is doing the right thing. The line ptr.reset(X::create().get()); is a bug in your code (taking ownership of a pointer already managed by shared_ptr), and it is correct for it to not compile.

----- Original Message ----- From: "Peter Dimov" <pdimov@pdimov.com> To: <boost@lists.boost.org> Sent: Sunday, September 28, 2008 7:10 PM Subject: Re: [boost] [smart_ptr] shared_ptr<T> T destructor required even ifadeleter function is provided
vicente.botet:
Hello,
I have compiled the example Preventing delete px.get()and every thing is OK until we use the reset function because shared_ptr<X> request that the destructor of X must be public even if a deleter function is provided. I'm wondering if this is a BUG on the smart pointer library
...
int main () { shared_ptr<X> ptr = X::create(); ptr.reset(X::create().get()); return 0; }
shared_ptr is doing the right thing. The line
ptr.reset(X::create().get());
is a bug in your code (taking ownership of a pointer already managed by shared_ptr), and it is correct for it to not compile.
Hello Peter, what about the following in which we don't transfer ownership. (Note that now X::create() return X*) int main () { shared_ptr<X> ptr(X::create(), X::deleter()); ptr.reset(X::create()); return 0; } Well, this was only to say that fact that shared_ptr don't have a deleter template parameter at the class level, has as consequence that we check on compile time that the delete function is public, and as consequence that the destructor must be public. When the class has a factory and a deleter this is not the case. So either my code has yet bug, either there is a bug on shared_ptr class or you must add a constraint on the shared_ptr parameter documentation (T::~T must be public) #include <boost/shared_ptr.hpp> using namespace boost; class X { private: ~X(){}; public: class deleter; friend class deleter; static X* create() { return new X; } class deleter { public: void operator()(X * p) { delete p; } }; }; I think that the problem is in the shared_count and sp_counted_impl_p which do not have a deleter parameter, and so they use delete. But maybe I'm missing something. Best, Vicente

vicente.botet:
Hello Peter,
what about the following in which we don't transfer ownership. (Note that now X::create() return X*)
int main () { shared_ptr<X> ptr(X::create(), X::deleter()); ptr.reset(X::create());
This is the equivalent of doing shared_ptr<X> ptr( X::create() ); which you're explicitly trying to prevent. The equivalent of
shared_ptr<X> ptr(X::create(), X::deleter());
is ptr.reset( X::create(), X::deleter() );
return 0; }

----- Original Message ----- From: "Peter Dimov" <pdimov@pdimov.com> To: <boost@lists.boost.org> Sent: Monday, September 29, 2008 12:44 PM Subject: Re: [boost] [smart_ptr] shared_ptr<T> T destructor requiredevenifadeleter function is provided
vicente.botet:
Hello Peter,
what about the following in which we don't transfer ownership. (Note that now X::create() return X*)
int main () { shared_ptr<X> ptr(X::create(), X::deleter()); ptr.reset(X::create());
This is the equivalent of doing
shared_ptr<X> ptr( X::create() );
which you're explicitly trying to prevent. The equivalent of
shared_ptr<X> ptr(X::create(), X::deleter());
is
ptr.reset( X::create(), X::deleter() );
return 0; }
Peter , thanks for pointing me to template<class Y, class D> void reset(Y * p, D d); I was not aware that deleter is associated to the pointer instance and not to the shared_ptr. I see now. I suppose that you have already discused about a template version of shared_ptr and that you have good raisons no not include them for the standard. Please could you point me to the rational? Has a wrapper class that takes the deleter and allocators as template parameter has a sence? template <typename T, typename Deleter, typename Allocator> struct shared_ptr_wrapper : private shared_ptr<T> { ... void reset(T * p) { this->shared_ptr::reset(p, Deleter()) } ... } Sorry for the noice and thanks again, Vicente
participants (2)
-
Peter Dimov
-
vicente.botet