实例化 C++ 模板 class 不带参数/取决于 if 语句中的类型

Instantiate C++ template class without parameter / depending on type in if-statement

我用 C++ 编写了不同的函数对象 A、B 和 C,我想根据用户输入用其中一个函数对象实例化一个模板 class。但是似乎没有办法在 if 语句中只实例化其中一种类型,是吗?

如果我尝试在 if 语句中使用模板实例化一个 class,g++ 编译器会给我一个 "use of undeclared identifier 'bkt'" 错误。如果我事先实例化它,class 在离开 if 语句时会自行销毁。

这是我的代码:

class A {
public: void operator()(int a) {}
}; 

class B {
public: void operator()(int a) {}
}; 

class C {
public: void operator()(int a) {}
}; 

template <typename T>
class MyClass {
public:
  MyClass<T>(const std::string &file);
  ~MyClass<T>;

private:
  T m_func;

int doStuff(int a) {
  return m_func(a);
 }
};

int main() {

std::string filename = std::string(argv[1]);
std::getline(std::cin, metric);

if (metric == "A") {
  MyClass<A> foo(filename);
}
else if (metric == "B") {
  MyClass<B> foo(filename);
}
else {
  MyClass<C> foo(filename);
}

int a = 1;
foo.doStuff(int a); // undeclared identifier "foo"

getchar();
return 0;
}

我知道,我必须以某种方式声明 foo 变量,但我希望编译器可以接受它,因为 if 语句的一种情况无论如何都会发生。显然不是,那么我该怎么做才能不实例化每个单一类型?

简单来说:模板可以帮助您实现编译时多态性,但您想要的是运行时多态性。但是,将它们混合起来很简单。

首先你创建一个基地class:

struct MyBase {
    ~MyBase(){}
    virtual int doStuff(int a) = 0;
};

然后让模板class继承它:

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 的指针,并在 if-case 中指定具体类型。我希望你明白这个想法并且只会给出一个粗略的草图:

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:也许只是措辞问题,但是...

so what can I do in order to not instantiate every single type?

你对此无能为力。模板在编译时实例化。如果你想在运行时选择一个实例化,你需要让它们实例化。在上面的代码中(一旦你填补了漏洞),每个可能的指标都会有一个实例化,但它只会创建一个实例。