2012-05-25 13 views
6

Chcę mieć interfejs ModelGenerator, który ma metodę generate(), która pobiera listę dowodów i tworzy model. Korzystanie z STL pseudo-kaczka-typowania iterator idiom ...Metoda wirtualna C++, która przyjmuje iteratory w stylu STL

template<class Model> 
class ModelGenerator { 
    public: 
    template<class Iterator> 
    virtual bool generate(Iterator begin, Iterator end, Model& model) = 0; 
}; 

Ale funkcje wirtualne nie można matrycy. Więc mam do szablonu całą klasę:

template<class Model, class Iterator> 
class ModelGenerator { 
    public: 
    virtual bool generate(Iterator begin, Iterator end, Model& model) = 0; 
}; 

Idealnie co chciałbym zrobić, to coś takiego ...

template<class Model, class Evidence> 
class ModelGenerator { 
    public: 
    virtual bool generate(iterator<Evidence>& begin, 
          iterator<Evidence>& end, 
          Model& model) = 0; 
}; 

Ale nie ma takiego interfejsu, który iteratory dziedziczyć. (Klasa std :: iterator zawiera tylko parę typedefs, bez metod.)

Jedyny sposób, w jaki mogę to zrobić, to nadanie modelowi Generation metody addEvidence(), która dodaje je jeden po drugim przed wywołaniem generowania (), ale wtedy muszę podać stan ModelGenerator, który jest trochę uciążliwy.

Jak mogę napisać wirtualną metodę, która pobiera dowolny kontener STL?

+1

CRTP może być tu przydatny. – Mehrdad

+2

Powinieneś pomyśleć o rozróżnieniu wszystkich operacji iteracyjnych od funkcji wirtualnej. Funkcja szablonowa może generować 'std :: vector ' i przekazywać ją do funkcji 'virtual'. Koszt wydajności i wysiłek programistyczny tego rodzaju opakowania jest prawdopodobnie mniejszy niż 'any_iterator' /' any_range'. – Potatoswatter

Odpowiedz

5

Wydaje się, że potrzebujesz any_iterator. To jest iterator, który wykonuje usuwanie typu, aby odizolować użytkownika od rzeczywistej implementacji iteratora.

Adobe ma implementację any_iterator: http://stlab.adobe.com/classadobe_1_1any__iterator.html

doładowania ma implementację any_range: http://www.boost.org/doc/libs/1_49_0/libs/range/doc/html/range/reference/ranges/any_range.html

+0

Dzięki! Czy wiesz, czy any_iterator można znaleźć w głównych bibliotekach? –

+1

Należy pamiętać, że implementacje 'any_iterator' są powolne, więc używaj ich tylko wtedy, gdy musisz. –

+0

@funkybluecoffee: Not Boost, niestety. Adobe ma jedną: http://stlab.adobe.com/classadobe_1_1any__iterator.html –

0

można rozważyć użycie szablonu specjalizacji zamiast metod wirtualnych w tym celu. Z tego co rozumiem, masz unikalną klasę Dowódcy, pewną liczbę odrębnych klas Modelowych i które mogą stworzyć fabrykę generyczną, by wytworzyć wybrany Model z sekwencji Dowodów.

#include <vector> 
#include <iostream> 

struct Model1 { }; 
struct Model2 { }; 
struct Evidence { }; 

template<class Model> 
struct ModelGenerator; 

template<> 
struct ModelGenerator<Model1> 
{ 
    typedef Model1 model_type; 

    template<class Iterator> 
    model_type generate(Iterator begin, Iterator end) 
    { 
     std::cout << "Generate Model1\n"; 
     return model_type(); 
    } 
}; 

template<> 
struct ModelGenerator<Model2> 
{ 
    typedef Model2 model_type; 

    template<class Iterator> 
    model_type generate(Iterator begin, Iterator end) 
    { 
     std::cout << "Generate Model2\n"; 
     return model_type(); 
    } 
}; 

template<class Model, class Iterator> 
Model make_model(Iterator begin, Iterator end) 
{ 
    ModelGenerator<Model> gen; 
    return gen.generate(begin, end); 
} 

można użyć go w ten sposób:

int main() 
{ 
    std::vector<Evidence> v; 

    Model1 m1 = make_model<Model1>(v.begin(), v.end()); 
    Model2 m2 = make_model<Model2>(v.begin(), v.end()); 
} 
Powiązane problemy