Pimpl with smart pointers in a class with a template constructor: weird incomplete type issue?

This is the destructor of boost::shared_ptr that requires the object to be complete when using boost::checked_deleter deleter. Because you put the range constructor Bar::Bar(I begin, I end) in the header file the compiler must generate code that destroys already constructed members if your constructor throws, hence it is trying to instantiate boost::scoped_ptr::~scoped_ptr(void) when instantiating this template constructor It is less than useful to use smart pointers with pimpl. Since you normally need to provide a destructor anyway, you could as well put delete pimpl in that destructor and be done with that.

This is the destructor of boost::shared_ptr that requires the object to be complete when using boost::checked_deleter deleter. Because you put the range constructor Bar::Bar(I begin, I end) in the header file the compiler must generate code that destroys already constructed members if your constructor throws, hence it is trying to instantiate boost::scoped_ptr::~scoped_ptr(void) when instantiating this template constructor. It is less than useful to use smart pointers with pimpl.

Since you normally need to provide a destructor anyway, you could as well put delete pimpl in that destructor and be done with that.

Okay, I see what I was missing. The question is a toy simplification of a real world issue that happened to me today. The actual pointer class used is boost::shared_ptr, thus I can't have a bare pointer here.

I will investigate using a custom deleter. Thanks. – Alexandre C.

Feb 7 at 13:28 1 I disagree with the less than useful. Because of the use of a scoped_ptr the issue is highlighted by the compiler if you forget to write the destructor, also the destructor body is extremely simple (empty...). On the other hand, using a raw pointer you would not be notified and would have to make the call.

Also, using shared_ptr, thanks to the embedded deleter, actually relieves you from the burden of writing a destructor at all. – Matthieu M. Feb 7 at 13:59 @Matthieu: It is a matter of taste, I prefer simple and powerful code, no unnecessary includes just for the comfort of it.

– Maxim Yegorushkin Feb 7 at 14:13 I understand, I personally use a custom implementation of smart pointer Pimpl class, which wraps up a customer deleter (like Boost) to provide copying / destruction "for free". It's on the heavy side (though only takes a hundred lines of code or so), but not forcing the developer to write the Big Three while still cutting down on dependencies seems like a win-win. – Matthieu M.

Feb 7 at 14:23.

The obvious problem is that Foo::Impl is incomplete at the point where the destructor of Foo is generated. Compilers usually emit a warning there, and boost::checked_delete, which is used internally by Boost smart pointers, statically asserts that the class Foo::Impl is complete and triggers an error if it is not the case. And implement an empty Foo::~Foo in the implementation file, where Foo::Impl is complete.

This is an advantage of smart pointers over bare pointers, because we can't fail to implement the destructor. So far, so good. I will try this with a recent gcc as soon as I get home.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions