我有一个模板类 Filter
,它采用另一个模板类的实例 Model
作为它的参数。我现在想要一个 vector
不同模型(即 Model
具有不同模板参数),并能够运行 Filter
在他们每个人之上。为此,我得出 Model
来自非模板 class AbstractModel
,这让我可以将这些不同的模型放入一个 vector
中.一切都很好,但是有一个问题:调用模板类的方法需要静态知道模板参数。但我没有静态知道它们。
这是代码
#include <vector>
#include <cstdlib>
class AbstractFilterData {};
class AbstractModel {};
template<int N>
class Args {};
template<int N>
class FilterData : public AbstractFilterData
{ int a; };
template<int N>
struct Model : public AbstractModel
{
static const int n=N;
virtual void compute(Args<N>& args) const = 0;
};
struct ModelA : public Model<3>
{
virtual void compute(Args<3>& args) const {}
};
struct ModelB : public Model<5>
{
virtual void compute(Args<5>& args) const {}
};
template<int N, int P>
struct Filter
{
static void predict(FilterData<N>& data, const Model<N>& model)
{
Args<N> args;
model.compute(args);
}
};
int main()
{
// For statically-defined model this works OK
FilterData<ModelA::n> data;
ModelA modA;
Filter<ModelA::n,2>::predict(data, modA);
// Let's make a bunch of different models and put them into a vector
std::vector<AbstractModel*> models;
models.push_back(new ModelA);
models.push_back(new ModelB);
// Associated data for these models
std::vector<AbstractFilterData*> fdata;
fdata.push_back(new FilterData<ModelA::n>);
fdata.push_back(new FilterData<ModelB::n>);
for(size_t i=0; i<models.size(); ++i)
{
// Now I'd like to run Filter::predict() on
// each of the models in the vector... but how?
Filter<models[i]->n,2>::predict(*fdata[i], *models[i]);
// This breaks on models[i]->n being not a constant-expression, of course
}
}
我可以考虑对可能的值进行循环 k
模型的模板参数,试图做 dynamic_cast(models[i],Model<k>*)
, 调用 Filter<k,2>::predict()
然后,但这看起来很丑陋。另外,因为我不知道 k
的上限,我不得不猜测,因为制作 INT_MAX
Filter
的实例化会使代码无法使用。
另一种方法是将静态 const 指针指向 Filter<N,2>::predict()
Model<N>
中的方法声明,但这也很丑陋,因为那时类 Model
似乎与类 Filter
相关联,这打破了这些类的独立性(例如,添加另一个过滤器不仅有效)。
是否有更好的方法来遍历这些不同的模型集并调用 Filter<?,2>::predict()
在他们?理想情况下,我希望编译器为我完成所有分派(dispatch)工作,这样就不会为从未真正使用过的参数进行模板实例化。
最佳答案
这是伪代码,省略了很多东西。
class AbstractModel {
virtual int Order() = 0;
};
class AbstractModel {
virtual int Order() = 0;
};
template<int N>
class FilterData : public AbstractFilterData {
virtual int Order() { return N; };
}
template<int N>
class Model : public AbstractModel {
virtual int Order() { return N; };
}
multimap<int, AbstractFilterData*> dataMap; // dataMap[i] contains a pointer to
// FilterData<i>
multimap<int, AbstractModel*> modelMap; // modelMap[i] contains a pointer to
// Model<i>
现在您可以做很多事情。您可以将 AbstractFilterData*
传递给您的 compute
,它会根据需要向下转换参数。您可以将整个 dataMap
传递给 compute
,它会获取并向下转换所需的数据。您可以在只有模板成员的类中隐藏 dataMap
template <int N>
void Put(FilterData<N>);
template <int N>
FilterData<N> Get(); // or perhaps FilterDataIterator<N>, if you really
// need a multimap
并自己进行所有的转换,并传递给那个类。或者你可以颠倒整个事情并用 modelMap
做同样的事情。
关于c++ - 动态选择模板特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24365282/