I have a base class Base
defined in Base.h:
class Base
{ /* ... */ };
And a class template Child
that derives from Base
, defined in Child.h:
#include "Base.h"
template <class T>
class Child : public Base
{ /* ... */ };
Now I want to create some factory methods within the Base
class, which should return a std::shared_ptr
to the Child
class. To avoid circular dependencies I tried to use a forward declaration instead. So Base.h now looks like this:
class Child; // new forward declaration
class Base
{
/* ... */
// new factory method
static std::shared_ptr<Base> CreateChildInt(int i = 0)
{
return std::make_shared<Child<int>>(i);
}
};
However, the definition of CreateChildInt()
leads to the following compiler error:
"error C2947: expecting '>' to terminate template-argument-list, found '<'"
So is this even possible what I am trying to achieve?
If not, are there any workarounds / best practices for this approach?
EDIT:
The reason for why I want to put the factory method into the Base
class instead of Child
is the following. When I put the factory into Child
I would need to call the factory method like this:
std::shared_ptr<Base> p = Child<int>::CreateChildInt(3);
However, I would like to omit the template type <int>
in this call, thus:
std::shared_ptr<Base> p = Base::CreateChildInt(3);
Firstly, you declared a class, but Child
that you define is actually a template. The correct way to declare a class template is:
template <class T>
class Child;
However, a correct forward declaration alone won't help you. The implementation of CreateChildInt::CreateChildInt
must know the full definition of Child
because it creates an instance of it. You can't define Child
before Base
either, because inheritance also depends on the full definition, so you'd end up with a cicrular dependency.
Solution: Forward declare Child
, then define Base
but don't define Base::CreateChildInt
inline, then define Child
and finally define Base::CreateChildInt
.
PS. I find it dubious from OOP perspective that the implementation of the base class member function depends on the child class. I recommend that you consider re-designing your approach.