eigene iteratoren



  • hallo, wenn ich eigene iteratoren für eigene datentypen habe, die z.b. random-access erlauben, was muss ich dann bedenken, damit die standard-funktionen wie std::distance usw SCHNELL ausgeführt werden mit meinen iteratoren?



  • Wenn deine Iteratoren wirklich random access Iteratoren sind (d.h. sie erfüllen alle Anforderungen an random access Iteratoren), sollte das automatisch funktionieren.


  • Mod

    TNA schrieb:

    Wenn deine Iteratoren wirklich random access Iteratoren sind (d.h. sie erfüllen alle Anforderungen an random access Iteratoren), sollte das automatisch funktionieren.

    Nein.

    Du musst von std::iterator ableiten und ihm das entsprechende Tag ( random_access_iterator_tag ) mitgeben. Denn bei std::distance , std::advance / std::next usw. wird Tag Dispatching durchgeführt.

    Und natürlich alle Funktionen bereitstellen, aber das sollte klar sein.



  • Arcoth schrieb:

    TNA schrieb:

    Wenn deine Iteratoren wirklich random access Iteratoren sind (d.h. sie erfüllen alle Anforderungen an random access Iteratoren), sollte das automatisch funktionieren.

    Nein.

    Du musst von std::iterator ableiten und ihm das entsprechende Tag mitgeben. Denn bei std::distance , std::advance / std::next usw. wird Tag Dispatching durchgeführt.

    Und natürlich alle Funktionen bereitstellen, aber das sollte klar sein.

    leuchtet ein, danke.

    für meinen const_iterator muss ich demensprechend einfach von iterator ableiten, während der zweite template-parameter "const T" ist, ja?



  • anhang: wobei redunanz-verhinderung wünschenswert ist.

    wie löst man das elegant?



  • not smart schrieb:

    hallo, wenn ich eigene iteratoren für eigene datentypen habe, die z.b. random-access erlauben, was muss ich dann bedenken, damit die standard-funktionen wie std::distance usw SCHNELL ausgeführt werden mit meinen iteratoren?

    wenn Du SCHNELL meinst, dann willst Du wahrscheinlich verhindern, dass erst mühsam von first bis last iteriert wird, um den Abstand derselben festzustellen.
    Dazu ist es notwendig, dass Dein Iterator den std::random_access_iterator_tag besitzt. Dies führt dann dazu, dass die distance-Funktioin aufgerufen wird, die den operator- Deines Operators benutzt um die Distanz zweier Iteratoren zu ermitteln.

    Dazu gibt es zwei Möglichkeiten, einmal von std::iterator<> ableiten:

    #include <iterator>
    
    class EigenerIterator : public std::iterator< std::random_access_iterator_tag, int > // int ist der Value-Typ und nur ein Beispiel! Trage dort bitte Deinen Value-Typ ein.
    {
    public:
        bool operator!=( const EigenerIterator& b ) const
        {
            return true;
        }
        std::ptrdiff_t operator-( const EigenerIterator& b ) const
        {
            return 42;
        }
    };
    

    oder das std::iterator_traits- Template spezialisieren:

    #include <iterator>
    
    class EigenerIterator
    {
    public:
        bool operator!=( const EigenerIterator& b ) const
        {
            return true;
        }
        std::ptrdiff_t operator-( const EigenerIterator& b ) const
        {
            return 42;
        }
    };
    
    namespace std
    {
        template<>
        struct iterator_traits< EigenerIterator >
        {
            typedef std::random_access_iterator_tag iterator_category;
            typedef std::ptrdiff_t difference_type;
            // .. und weitere typedefs
        };
    }
    

    In beiden Fallen wird dann durch:

    #include <iostream>
    #include "EigenerIterator.h"
    
    int main()
    {
        using namespace std;
        EigenerIterator a, b;
        cout << std::distance( a, b ) << endl;
        return 0;
    }
    

    Deine Implementierung des EigenerIterator::operator- aufgerufen. Und das ist dann so schnell, wie eben diese Implementierung.

    Gruß
    Werner



  • not smart schrieb:

    anhang: wobei redunanz-verhinderung wünschenswert ist.

    wie löst man das elegant?

    Schau Dir mal die Helferlein bei boost an:http://www.boost.org/doc/libs/1_54_0/libs/iterator/doc/index.html
    und im speziellen Fall der Redundanz-Verhinderung für T und const T guckst Du hier: http://www.boost.org/doc/libs/1_54_0/libs/iterator/doc/iterator_adaptor.html#tutorial-example



  • not smart schrieb:

    für meinen const_iterator muss ich demensprechend einfach von iterator ableiten, während der zweite template-parameter "const T" ist, ja?

    Nein - die Unterscheidung const_iterator und iterator geschieht über den Referenztyp.



  • danke dir viel mal für die ausführliche erklärung. versuche ich gleich umzusetzen!


Log in to reply