我有一个模板类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
实例化会使代码无法使用。
另一种方法可能是在Filter<N,2>::predict()
声明中为Model<N>
方法添加一个静态const指针,但这也很丑陋,因为类Model
似乎与类{{{}}相关联1}},它打破了这些类的独立性(例如,添加另一个过滤器不仅起作用)。
是否有更好的方法来遍历这些不同模型并在其上调用Filter
?理想情况下,我希望编译器能够为我完成所有调度工作,因此对于从未真正使用的参数,不会发生模板实例化。
答案 0 :(得分:0)
这是伪代码,省略了很多东西。
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
做同样的事情。