Как я могу объявить указатель шаблона, не зная тип?
Это то, что я хотел бы сделать:
ExampleTemplate* pointer_to_template;
cin >> number;
switch (number) {
case 1:
pointer_to_template = new ExampleTemplate<int>();
break;
case 2:
pointer_to_template = new ExampleTemplate<double>();
break;
}
pointer_to_template->doStuff();
Это не скомпилируется, потому что тип шаблона должен быть указан при объявлении указателя. (ExampleTemplate* pointer_to_template
должно быть ExampleTemplate<int>* pointer_to_template
.) К сожалению, я не знаю тип шаблона, пока он не будет объявлен в блоке коммутатора. Какая самая лучшая работа для этой ситуации?
Ответы
Ответ 1
Вы не можете. ExampleTemplate<int>
и ExampleTemplate<double>
- два разных, не связанных между собой типа. Если у вас всегда есть переключатель по нескольким параметрам, используйте boost::variant
вместо этого.
typedef boost::variant<Example<int>, Example<double>> ExampleVariant;
ExampleVariant v;
switch (number) {
case 1: v = Example<int>(); break;
case 2: v = Example<double>(); break;
}
// here you need a visitor, see Boost.Variant docs for an example
Другой способ - использовать обычный базовый класс с виртуальным открытым интерфейсом, но я бы предпочел variant
.
struct BaseExample {
virtual void do_stuff() = 0;
virtual ~BaseExample() {}
};
template <typename T>
struct Example : BaseExample { ... };
// ..
BaseExample *obj;
Ответ 2
Вы можете сделать что-то подобное, если ваш шаблонный класс получен из обычного класса:
#include<iostream>
#include<sstream>
using namespace std;
class ExampleBase{
public:
virtual ~ExampleBase() {}
virtual string Get() = 0;
};
template<typename T>
class ExampleTemplate : public ExampleBase{
private:
T data;
public:
ExampleTemplate(T t) : data(t){}
string Get(){
stringstream s; s << data;
return s.str();
}
};
int main(){
ExampleBase *base;
int number;
cout << "> " << flush; cin >> number;
switch(number){
case 1:
base = new ExampleTemplate<int>(42);
break;
case 2:
base = new ExampleTemplate<double>(3.14);
break;
default:
return 1;
}
cout << base->Get() << endl;
delete base;
return 0;
}
Ответ 3
То, что вы пытаетесь сделать, невозможно. Это потому, что ваш класс ExampleTemplate
не существует сам по себе, существует только тогда, когда вы связываете его с типом.
Вы можете получить это поведение, используя наследование:
- Определите
GeneralExampleTemplate
(а не шаблонный класс).
- Сделать
ExampleTemplate<T>
наследовать от GeneralExampleTemplate
.
- Таким образом вы можете создать указатель
GeneralExampleTemplate
и назначить его (например) ExampleTemplate<int>
.