调用在运行时创建的模板类的函数

时间:2014-04-24 09:32:05

标签: c++ class templates c++11 late-binding

关于C ++(11)模板类及其在运行时确定类型的实例化,我有一个棘手的问题:

以下情景: 用户使用配置文件(ROS参数)定义模板类的类型。这仅确定模板类的类型,而不是其他逻辑:

班级定义:

template<typename T>
class MyClass {
    //[...]
}

示例代码:

/* [Read parameter and write result to bool use_int] */

std::unique_ptr<MyClass> myclassptr {nullptr};
if(use_int) {
    myclassptr.reset(MyClass<int>);
} else {
    myclassptr.reset(MyClass<double>);
}

myclassptr->foobar();

/* [more code making use of myclassptr] */

所以这段代码(当然)没有编译,因为必须使用模板类型指定unique_ptr模板。但是,问题出现了,使用reset分配的所有对象的模板类型必须相同。

一个丑陋的解决方案是将代码myclassptr->foobar();和以下内容复制到if / else的每个分支中,这是我真的不喜欢的。

我希望看到类似的解决方案:

/* [Read parameter and write result to bool use_int] */

MyClass<use_int ? int : double> myclass;
myclass.foobar();

到目前为止我所读到的是这样的事情也是不可能的。

有人为此提供了一个很好的解决方案吗?

2 个答案:

答案 0 :(得分:3)

最简单的方法是:

class IClass{
  virtual ~IClass {}
  virtual void foobar()=0;
};
template<typename T>
class MyClass:public IClass {
public:
  void foobar() override {
    // code here
  }
};
std::unique_ptr<IClass> myclassptr {};
if(use_int) {
  myclassptr.reset(new MyClass<int>());
} else {
  myclassptr.reset(new MyClass<double>());
}
myclassptr->foobar();

boost::variant将是另一种解决方案,但通常用于不相关的类型。可以完成类型擦除,但是当您有不相关的类型时,通常会再次执行类型擦除。

在其他语言中,泛型看起来有点像template,但它实际上是一个抽象的接口,带有自动生成的类型转换和一些类型检查。 C ++ template是函数或类编译时工厂。默认情况下,这些工厂的两个输出在运行时是不相关的,如果需要,可以添加这样的关系。

答案 1 :(得分:1)

根据您的需要,您可以使MyClass成为包含int或double的变体类型,或者您可以使用类型擦除来隐藏接口背后的实现。 Boost.Variant库可以帮助实现前者。