Проще говоря: шаблоны помогают вам с полиморфизмом во время компиляции, но вам нужен полиморфизм во время выполнения. Однако их легко смешать.
Сначала вы создаете базовый класс:
struct MyBase {
~MyBase(){}
virtual int doStuff(int a) = 0;
};
Затем вы позволяете шаблонному классу наследовать от него:
template <typename T>
class MyClass : MyBase {
public:
MyClass<T>(const std::string &file);
~MyClass<T>;
private:
T m_func;
int doStuff(int a) override {
return m_func(a);
}
};
Теперь вы можете иметь указатель на MyBase
а внутри кейсов назначить конкретный тип. Я надеюсь, что вы поняли идею и дадите только приблизительный набросок:
std::shared_ptr<MyBase> foo; // or perhaps a unique_ptr
if (metric == "A") {
foo = ... create MyClass<A>
} else if (metric == "B") {
...
}
foo->doStuff(3);
Ради полноты ... ваш код не сработал, потому что в
if (metric == "A") {
MyClass<A> foo(filename);
}
время жизниfoo
ограничен областью действия if
, которое заканчивается на }
, и вы не можете получить к нему доступ снаружи.
PS : поскольку все метрики имеют одинаковую подписьЯ бы использовал другой подход, который не требует MyClass
в качестве шаблона. В любом случае, MyClass
быть шаблоном - это требование.
PPS : Может быть, это просто вопрос формулировки, но ...
так что я могу сделать, чтобы не создавать экземпляры для каждого типа?
Вы ничего не можете с этим поделать. Шаблоны создаются во время компиляции. Если вы хотите выбрать один экземпляр во время выполнения, вам нужно создать его экземпляр. В приведенном выше коде (после того, как вы заполните отверстия) будет создание экземпляров для каждой возможной метрики, но создается только один экземпляр.