2014-06-23 4 views
1

나는 다른 템플릿 클래스 Model의 인스턴스를 매개 변수로 사용하는 템플릿 클래스 Filter을 가지고 있습니다. 이제 서로 다른 모델 (예 : Model)이 서로 다른 템플릿 매개 변수를 사용하여 vector 개를 갖고 각각에 대해 Filter을 실행할 수 있어야합니다. 이를 위해 템플릿이 아닌 class AbstractModel에서 Model을 파생 시켰습니다. 다른 모델을 하나의 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 
    } 
} 

내가 다음 Filter<k,2>::predict()를 호출 dynamic_cast(models[i],Model<k>*)을하려고, k 모델의 템플릿 매개 변수의 가능한 값을 통해 루프를 만드는 생각할 수있는 코드를하지만 이것은 매우 추한 보인다. 또한, k에 대한 상한을 모르므로, FilterINT_MAX 인스턴스화를 사용하면 코드를 사용할 수 없게되므로 추측해야합니다.

또 다른 방법은 Model<N> 선언에 Filter<N,2>::predict() 방법에 const 정적 포인터를 넣어 수

,하지만 클래스 Model는 이러한 클래스의 독립을 파괴하는 클래스 Filter에 묶여 것으로 나타 때문에이 또한 추한 (예 : 다른 필터를 추가 그냥 작동하지 않습니다).

다른 모델 세트를 탐색하고 Filter<?,2>::predict()을 호출하는 더 좋은 방법이 있습니까? 이론적으로 컴파일러가 모든 파견 작업을 수행하여 실제로 사용되지 않는 매개 변수에 대한 템플릿 인스턴스화가 발생하지 않도록하고 싶습니다.

+0

'n'은 (는) 정적이어야합니까? – user1810087

+0

@ user1810087'n'은 정적이지만'models'은 정적이 아닙니다. – Ruslan

+0

당신은'switch'로 보낼 수 있습니다. – Jarod42

답변

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으로 전달할 수 있으며 필요한 데이터를 가져오고 전송합니다. 당신은 템플릿 회원

template <int N> 
void Put(FilterData<N>); 
template <int N> 
FilterData<N> Get(); // or perhaps FilterDataIterator<N>, if you really 
         // need a multimap 

을 가지고 있으며, 모든 캐스팅 자체를 수행하는 클래스 dataMap을 숨기고, 그 클래스의 주위에 전달할 수 있습니다. 아니면 전체 내용을 뒤집어 대신 modelMap으로 처리 할 수도 있습니다.

관련 문제