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