How would someone go about implementing a factory function for a templated class? Either my google searches aren't looking for the right thing, or I am misunderstanding the results. As an example:
template<typename T>
class Test
{
public:
T data;
void SizeOfData() { std::cout << "Data Size:" << sizeof(data) << "\n"; }
};
----this what I am trying to figure out how to do------
template <typename T>
Test<T> FactoryFunction(const std::string& type)
{
if(type == "int")
return Test<int>;
if(type == "long")
return Test<long long>;
}
----------------------------------------
int main()
{
auto a = FactoryFunction(std::string("int"));
auto b = FactoryFunction(std::string("long"));
a.SizeOfData();
b.SizeOfData();
a.data = 1;
b.data = 2;
}
Obviously, this code is all wrong - I am just trying to show what I want to do in theory. Can it be done? What do I look up in google - Factory functions to return templated classes? I am not even sure where to start. If someone could even point me in a direction - I really just want a function the returns the correct template instantiation based on the results of a switch or if/else list. I think conceptually the idea isn't hard, but implementing it is another thing - or I am really missing something.
Thanks for any help.
CodePudding user response:
The type T of a templated function has to be determined in compile time. Therefore you cannot do it the way you mentioned.
However - you can use the following pattern to achieve a similar result:
#include <assert.h>
class TestBase
{
public:
virtual void SizeOfData() = 0;
};
template<typename T>
class Test : public TestBase
{
public:
T data;
virtual void SizeOfData() override { std::cout << "Data Size:" << sizeof(data) << "\n"; }
};
std::unique_ptr<TestBase> FactoryFunction(const std::string& type)
{
if (type == "int")
return std::make_unique<Test<int>>();
if (type == "long")
return std::make_unique<Test<long long>>();
return nullptr;
}
int main()
{
auto a = FactoryFunction(std::string("int"));
assert(a);
auto b = FactoryFunction(std::string("long"));
assert(b);
a->SizeOfData();
b->SizeOfData();
}
Some notes:
Each instance of Test (where T changes) is a differnt an unrelated class. In order to create a connection between them, I added a common base class.
In order to use polymorphism, you must use refernce semantics. Therefore the factory returns a pointer (in this case a
std::unique_ptr
).The common method you need to invoke on all your Test objects (
SizeOfData
) became a virtual method in the base class.This technique is actually related to the idiom of type erasure mentioned in the comments.
UPDATE: based on the comment below, I replaced using naked new
s with std::make_unique
.
You can see more info why it is better here: Differences between std::make_unique and std::unique_ptr with new