如何为模板化的 class 创建 "factory function"?
How to create a "factory function" for a templated class?
如何为模板化 class 实现工厂函数?要么我的 google 搜索没有找到正确的东西,要么我误解了结果。例如:
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;
}
显然,这段代码都是错误的——我只是想展示我在理论上想做的事情。可以吗?我在 google - return 模板化 classes 的工厂函数中查找什么?我什至不知道从哪里开始。如果有人甚至可以指出我的方向 - 我真的只想要一个函数 returns 正确的模板实例化基于开关或 if/else 列表的结果。我认为从概念上讲这个想法并不难,但实现它是另一回事 - 或者我真的错过了一些东西。
感谢您的帮助。
模板函数的类型 T 必须在编译时确定。
所以你不能像你说的那样做。
但是 - 您可以使用以下模式来获得类似的结果:
#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();
return 0;
}
一些注意事项:
每个测试实例(其中 T 发生变化)都是不同的且不相关的 class。为了在它们之间建立联系,我添加了一个公共基础 class.
为了使用多态性,你必须使用引用语义。因此工厂returns一个指针(在本例中是std::unique_ptr
)。
您需要在所有测试对象 (SizeOfData
) 上调用的通用方法成为基类中的虚方法 class。
这个技巧其实和评论里提到的type erasure的成语有关
UPDATE:根据下面的评论,我用 std::make_unique
替换了使用 naked new
s。
你可以在这里看到更多信息,为什么它更好:Differences between std::make_unique and std::unique_ptr with new
如何为模板化 class 实现工厂函数?要么我的 google 搜索没有找到正确的东西,要么我误解了结果。例如:
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;
}
显然,这段代码都是错误的——我只是想展示我在理论上想做的事情。可以吗?我在 google - return 模板化 classes 的工厂函数中查找什么?我什至不知道从哪里开始。如果有人甚至可以指出我的方向 - 我真的只想要一个函数 returns 正确的模板实例化基于开关或 if/else 列表的结果。我认为从概念上讲这个想法并不难,但实现它是另一回事 - 或者我真的错过了一些东西。
感谢您的帮助。
模板函数的类型 T 必须在编译时确定。 所以你不能像你说的那样做。
但是 - 您可以使用以下模式来获得类似的结果:
#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();
return 0;
}
一些注意事项:
每个测试实例(其中 T 发生变化)都是不同的且不相关的 class。为了在它们之间建立联系,我添加了一个公共基础 class.
为了使用多态性,你必须使用引用语义。因此工厂returns一个指针(在本例中是
std::unique_ptr
)。您需要在所有测试对象 (
SizeOfData
) 上调用的通用方法成为基类中的虚方法 class。这个技巧其实和评论里提到的type erasure的成语有关
UPDATE:根据下面的评论,我用 std::make_unique
替换了使用 naked new
s。
你可以在这里看到更多信息,为什么它更好:Differences between std::make_unique and std::unique_ptr with new