boost::scoped_ptr documentation contains an example of a technique referred as Handle/Body Idiom. It is described there in the following words:
The scoped_ptr_example_test.cpp sample program includes a header file,
scoped_ptr_example.hpp, which uses a scoped_ptr<> to an incomplete type
to hide the implementation.
However, at the same time, in the documentation for checked_delete it is stated:
A particularly troublesome case is when a smart pointer’s destructor, such as
boost::scoped_ptr::~scoped_ptr, is instantiated with an incomplete type.
This can often lead to silent, hard to track failures.
The supplied function and class templates can be used to prevent these problems, as they
require a complete type, and cause a compilation error otherwise.
scoped_ptr indeed uses checked_delete in its implementation. To me it looks like the two passages contradict one another. Also, I fail to compile my code that tries to employ the proposed trick with the following message:
checked_delete.hpp:32: error: invalid application of 'sizeof' to
incomplete type 'MyClass'
So is, indeed, the documentation of scoped_ptr erronous or do I just miss something?
They don’t contradict each other. Because
scoped_ptris a template, and because there is no explicit instantiation in the code, each method is instantiated on demand. That means that the type must be complete by the time that~scoped_ptr<>is instantiated, which in this case is in the .cpp file after the held type is complete (look forexample::~example(){}close to the end of the file, which is where~scoped_ptr<>is instantiated)This is actually an interesting use case for a user defined destructor that looks exactly the same as the compiler generated would, but allows you to control where / when the destruction happens to enable the PIMPL pattern with some smart pointers. If the destructor was not declared and defined, then the destructor would be implicitly defined by the compiler where needed, and the type would be incomplete, causing UB.