I have a factory function in factory.h which returns an std::shared_ptr
to a base class in foo.h. factory.h uses
So std::shared_ptr
is three things wrapped up in one small neat package.
First, it is a pointer to some data, with overrides to give you access to it that make using it much like using a raw C pointer.
The second part is a reference counter. It keeps track of the equivalent of an std::atomic
that all std::shared_ptr
copies off the first increment/decrement as they come into / go out of scope.
The third part is a destruction function -- or a pointer to said destruction function, to be more exact.
When you copy a std::shared_ptr
from another, it uses the reference counter/destruction function/pointer to data of the source std::shared_ptr
. So it does not need to write a destruction function, nor does it need to know what the destruction function does!
When you create a std::shared_ptr
without copying it, it must create the destruction function. The default destruction function is one that calls the destructor of Foo
: which requires the full declaration of Foo
!
std::shared_ptr
will call the destruction function even if the pointer is nullptr
, so even in the empty case it need write that destruction function.
So the short story is: anywhere you create a std::shared_ptr
not by copying or moving from another std::shared_ptr
, you must either supply a manual destruction function, or you must have Foo::~Foo
visible (ie, the full declaration of Foo
).
The cases where you called a function that returned a std::shared_ptr
copied them from inside the body of the function: within that body, wherever those std::shared_ptr
eventually came from, one of the two requirements above where met.
The case where you simply create it on nullptr
it must write and store the destruction function, and that requires full access to the class.
If you really need to std::shared_ptr
without access to foo
, try std::shared_ptr
, which should pass in a do-nothing destruction function.