我有一个带有整数参数的模板类,但我只知道运行时的模板参数。是否有最佳实践在运行时创建模板类?
我提出的解决方案是创建模板类的抽象基类,它提供接口并有一个适配器类,它创建模板类并将其存储在基类型的指针中类。
class MyInterface {
virtual void doSomething(...) = 0;
}
template <int T>
class MyTemplateClass : public MyInterface {
void doSomething(...) { ... };
}
class TemplateAdapter {
MyInterface* template_class;
Template(int n) {
switch(n) {
case 1:
template_class = new MyTemplateClass<1>();
break;
case 2:
template_class = new MyTemplateClass<2>();
break;
case 3:
template_class = new MyTemplateClass<3>();
break;
[...]
}
}
void doSomething() {
template_class->doSomething();
}
}
现在虽然这确实有效并产生了正确的结果,但它非常慢。使用适配器的速度几乎是使用模板类的两倍。很明显,它必须有点慢,但这比我预期的要慢得多。
这种性能损失从何而来?您是否知道如何动态创建具有更好性能的模板类?
非常感谢任何帮助! 谢谢, 佩德罗
答案 0 :(得分:0)
此设计不允许编译器内联任何内容(如果在编译时已知实际类型,则可以删除虚拟调用),并且需要对实际实例化的类执行运行时决策。
答案 1 :(得分:0)
C ++中的模板只存在编译时,任何动态生成模板的尝试都会因此而失败。
可以通过删除运行时开关并使适配器成为模板来优化您的代码:
template<int i>
class TemplateAdapter {
MyTemplateClass<i> template_class;
}
但这消除了任何适配器需求。
答案 2 :(得分:0)
其他答案已经解释了模板是编译时而不是运行时功能。但是,您的问题询问为什么在您的解决方法中会出现如此显着的性能损失。如果您经常创建适配器类,则new关键字是从堆中为子对象分配内存,而堆分配则非常慢。
答案 3 :(得分:0)
您是否需要MyInterface引入的依赖项反转?如果没有,为什么不创建一个非多态和非模板化的类型,它与你的适配器做同样的事情,但包含所需功能的完整实现......?它将基于构造时传递的整数参数决定做什么,而不创建新对象或调用虚函数...