Prüfen, ob Klasse einen Operator unterstützt



  • Hallo,

    ich arbeite an einer Funktion, die als Parameter per Template einen (Zeiger auf eine) beliebige Klasse übergeben bekommt. Auf dieser wird mit Iterator-ähnlichen Operatoren gearbeitet. Da ich aber nicht weiß, welche Operatoren von der Klasse unterstützt werden (z.B. []), will ich das überprüfen. Für jeden Vorschlag, wie ich so etwas machen könnte, wäre ich dankbar; bis jetzt habe ich zu dieser Frage nichts gefunden (ev. fehlt mir der richtige Suchbegriff?!)

    Gesucht ist folgendes:

    func(T* x)
    {
    wenn (x unterstützt []-Operator) { wahlfreier Zugriff auf x }
    sonst { sequentieller Zugriff auf x }
    }

    Danke!
    Felix



  • Du kannst das nicht überprüfen. Du kannst nur versuchen, den Operator einzusetzen - wenn's nicht klappt, beschwert sich der Compiler.

    Deswegen verwendet die STL auch Kategorie-Tags, um die "Fähigkeiten" eines Iterators einzustufen:

    template<typename It>
    void op(It p)
    {
      op2(p,iterator_traits<It>::category());
    }
    
    template<typename RIt>
    void op2(RIt p,random_access_iterator_tag)
    {
      //nutzt volle Bandbreite der Zugriffsmöglichkeiten: +, -, [],...
    }
    template<typename IIt>
    void op2(IIt p,input_iterator_tag)
    {
      //ersetzt die Operatoren durch advance()- und distance()-Aufrufe
    }
    


  • Die Iterator-Traits kannte ich schon, aber dein Beispiel hilft mir auf jeden Fall bei der Implementierung.
    Der Stroustrup sagt allerdings, dass alles was sich wie ein Iterator verhält, auch ein Iterator ist. Ich bin also nicht gezwungen, meinen eigenen Iterator in die Iterator-Hierachie einzubinden, solange ich die Operationen *, ++, == und ggf. [] unterstütze, oder?



  • Du mußt nicht, aber du kannst - und solange du eine Minimalvariante deines Algorithmus anbietest, dürften auch unbekannte Iterator-Typen verarbeitet werden können (allerdings mit etwas schlechterer Performance).



  • Ich habe jetzt einmal die Implementierung über die iterator_traits versucht, aber ich kann folgenden Code nicht mit dem GNU-Complier übersetzen, wärend Visual Studio 2003 ihn problemlos schluckt. Habe ich etwas falsch gemacht?

    Die Fehlermeldung verstehe ich auch nicht ganz:

    12: dependant-name 'std::iterator_traits<_Iterator>::iterator_category' is parsed as a non-type, but instantiation yields a type

    #include<iostream>
    #include<vector>
    #include<iterator>
    
    using namespace std;
    
    // iterator traits and polymorphic functions
    
    template<typename It>
    void it1(It i)
    {
    	it1_help(i, iterator_traits<It>::iterator_category());
    }
    
    template<typename ItRA>
    void it1_help(ItRA i, random_access_iterator_tag)
    {
    	cout << "random access";
    }
    
    template<typename ItSA>
    void it1_help(ItSA i, input_iterator_tag)
    {
    	cout << "sequential access";
    }
    
    int main()
    {
    	vector<int> v(10);
    	vector<int>::iterator itr_v = v.begin();
    
    	it1(itr_v);
    }
    


  • Hat sich erledigt, es fehlte ein "typename" vor dem iterator_category-Ausdruck. Fragt sich nur, warum Stroustrup und VStudio ohne auskommen...


Anmelden zum Antworten