简体   繁体   English

如何为模板化的 class 创建“工厂函数”?

[英]How to create a "factory function" for a templated class?

How would someone go about implementing a factory function for a templated class?有人 go 如何为模板化的 class 实施工厂 function? 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?我在 google 中查找什么 - 返回模板类的工厂函数? 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.如果有人甚至可以指出我的方向——我真的只想要一个 function,它会根据开关或 if/else 列表的结果返回正确的模板实例化。 I think conceptually the idea isn't hard, but implementing it is another thing - or I am really missing something.我认为从概念上讲这个想法并不难,但实施它是另一回事 - 或者我真的错过了一些东西。

Thanks for any help.谢谢你的帮助。

The type T of a templated function has to be determined in compile time.模板化 function 的类型 T 必须在编译时确定。 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();
    return 0;
}

Some notes:一些注意事项:

  1. 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. Test 的每个实例(其中 T 发生变化)都是一个不相关的 class。为了在它们之间创建连接,我添加了一个公共基础 class。

  2. In order to use polymorphism, you must use refernce semantics.为了使用多态性,您必须使用引用语义。 Therefore the factory returns a pointer (in this case a std::unique_ptr ).因此,工厂返回一个指针(在本例中为std::unique_ptr )。

  3. The common method you need to invoke on all your Test objects ( SizeOfData ) became a virtual method in the base class.您需要在所有测试对象 ( SizeOfData ) 上调用的通用方法成为基类 class 中的虚拟方法。

  4. This technique is actually related to the idiom of type erasure mentioned in the comments.这个技巧其实和评论里提到的type erasure这个习语有关。

UPDATE : based on the comment below, I replaced using naked new s with std::make_unique .更新:根据下面的评论,我用std::make_unique替换了 using naked new You can see more info why it is better here: Differences between std::make_unique and std::unique_ptr with new你可以在这里看到更多信息为什么它更好: Differences between std::make_unique and std::unique_ptr with new

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM