如何在不知道类型的情况下声明模板指针?

时间:2011-11-21 00:10:01

标签: c++ templates generics pointers

这就是我想做的事情:

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。)不幸的是,在切换块中声明模板之前,我不知道模板的类型。对于这种情况,最好的解决方法是什么?

3 个答案:

答案 0 :(得分:17)

你不能。 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;

答案 1 :(得分:6)

您可以通过让模板类派生自常规类来执行类似的操作:

#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;
}

答案 2 :(得分:5)

你想要做的是不可能的。这是因为您的ExampleTemplate类本身不存在,只有在您将其与类型相关时才存在。

您可以使用继承获得该行为:

  1. 定义GeneralExampleTemplate(不是模板类)。
  2. ExampleTemplate<T>继承自GeneralExampleTemplate
  3. 通过这种方式,您可以创建GeneralExampleTemplate指针并为其指定(例如)ExampleTemplate<int>