如何为模板化的 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;
}

一些注意事项:

  1. 每个测试实例(其中 T 发生变化)都是不同的且不相关的 class。为了在它们之间建立联系,我添加了一个公共基础 class.

  2. 为了使用多态性,你必须使用引用语义。因此工厂returns一个指针(在本例中是std::unique_ptr)。

  3. 您需要在所有测试对象 (SizeOfData) 上调用的通用方法成为基类中的虚方法 class。

  4. 这个技巧其实和评论里提到的type erasure的成语有关

UPDATE:根据下面的评论,我用 std::make_unique 替换了使用 naked news。 你可以在这里看到更多信息,为什么它更好:Differences between std::make_unique and std::unique_ptr with new