I have a factory function in factory.h which returns an std::shared_ptr
to a base class in foo.h. factory.h uses
I'm afraid your question is exactly backwards. :-)
In the second example, where you're calling create_foo_A() and create_foo_B(), you're essentially promising the compiler that these functions, when linked into a program, will return pointers to instances of classes derived from foo. The compiler doesn't need to know or care what makes up a foo; at this point, it's up to those functions to decide what a foo really is.
But in your first example, the line:
std::shared_ptr ptr(nullptr);
constructs a shared pointer to a foo, and the program is expecting to find a destructor for the the shared pointer to call. Since you haven't defined foo, only declared it's a class, the compiler doesn't know what the class looks like (it's an incomplete type) and complains about not having that destructor.