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

Nat*_*han 18 c++ generics templates 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();
Run Code Online (Sandbox Code Playgroud)

这不会编译,因为在声明指针时必须指定模板类型.(ExampleTemplate* pointer_to_template应该是ExampleTemplate<int>* pointer_to_template.)不幸的是,我不知道模板的类型,直到它在switch块中声明.对于这种情况,最好的解决方法是什么?

Cat*_*lus 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
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用具有虚拟公共接口的普通基类,但我更喜欢variant.

struct BaseExample {
    virtual void do_stuff() = 0;
    virtual ~BaseExample() {}
};

template <typename T>
struct Example : BaseExample { ... };

// ..
BaseExample *obj;
Run Code Online (Sandbox Code Playgroud)

  • @ julio.alegria:不. (6认同)
  • @ julio.alegria:不,不是. (6认同)
  • 让我改写一句:"提升"?对于首发来说,这有点复杂 (4认同)
  • 这完全取决于有问题的新手.有些人会遇到一些麻烦,有些人会超出他们的深度.OP将决定对此进行跟进,或者提出问题,或者忽略这个答案以获得他/她更容易理解的内容.但是,在处理软件问题时,提供"正确的方法"来做这种事情并将新程序员介绍给好的库(并让他们考虑这些库)是很好的. (4认同)

Vla*_*lad 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;
}
Run Code Online (Sandbox Code Playgroud)


jul*_*ria 5

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

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

  1. 定义一个GeneralExampleTemplate(不是模板类).
  2. ExampleTemplate<T>继承GeneralExampleTemplate.
  3. 这样你就可以创建一个GeneralExampleTemplate指针并用(例如)分配它ExampleTemplate<int>.