Reputation: 15
I have a class that I want to initialize this class using a factory function of the template type. It also needs to depend on a long-lasting dependency that I want to store as member variables and refer to in the factory functions. E.g.
template <class T>
class Foo {
public:
Foo() : member_(Create<T>()) {}
template <class T>
T Create();
private:
T member_;
SomeType* dependency_a_;
OtherType* dependency_b_;
};
template <>
TypeA Foo<TypeA>::Create<TypeA>() {
return TypeA(dependency_a_);
}
template <>
TypeB Foo<TypeB>::Create<TypeB>() {
return TypeB(dependency_b_);
}
In the current state, I'm getting the following error:
template_example.cc:17:19: error: declaration of 'T' shadows template parameter
template <class T>
^
template_example.cc:12:17: note: template parameter is declared here
template <class T>
^
template_example.cc:28:19: error: template specialization requires 'template<>'
TypeA Foo<TypeA>::Create<TypeA>() {
^ ~~~~~~~
template_example.cc:33:19: error: template specialization requires 'template<>'
TypeB Foo<TypeB>::Create<TypeB>() {
I don't have much experience with templates, so I'm not really sure what the template for Create
should look like (or even if it should have a template). I've tried a number of combinations of different things, and they all get compiler errors.
Any idea how to do what I want to do? The one thing I can think of is to pass all dependencies to Create
. Then it doesn't need to be a member function anymore. But then anyone who adds a new factory function needs to remember to add to the Create
signature. It wouldn't be the end of the world, but I'd like to know if there's a solution that doesn't require that.
Upvotes: 0
Views: 935
Reputation: 598134
There is no need to have a template on Create()
at all, since it is already on Foo
. Just have Create()
use Foo
's own T
template parameter as-is, just as you are with member_
, eg:
template <class T>
class Foo {
public:
Foo() : member_(Create()) {} // <T> not needed here!
T Create(); // no 'template' here!
private:
T member_;
SomeType* dependency_a_;
OtherType* dependency_b_;
};
template <class T>
T Foo<T>::Create() {
return T();
}
template <>
TypeA Foo<TypeA>::Create() {
return TypeA(dependency_a_);
}
template <>
TypeB Foo<TypeB>::Create() {
return TypeB(dependency_b_);
}
Upvotes: 2