Iterator begin und end falsch


  • Mod

    Zeig doch mal Zeile 210. Du versuchst anscheinend einen Iterator mit zwei Argumenten zu initialisieren (einer TList und einem const_iterator), aber dein Iterator kennt nur zwei Konstruktoren, von denen beide jeweils einen Parameter von einem Iteratortyp erwarten.



  • Hallo zusammen,

    da ich gestern durch das Spiel ein wenig abgelenkt war erst heute hier die Antwort. 🙂

    template <typename T>
    std::ostream&
    operator<<(std::ostream & out, const List<T> & l) {
    
        out << "[";
    
        typename List<T>::const_iterator e;
        for ( e = l.begin(); e != l.end(); e++) {
            out << (*e);
        }
        out << "]";
        return out;
    }
    

    Die Zeile 217 ist die Zeile mit den for-Schleifen-Kopf:

    main.cc: In instantiation of ‘std::ostream& operator<<(std::ostream&, const List<T>&) [with T = int; std::ostream = std::basic_ostream<char>]’:
    main.cc:458:18:   required from here
    main.cc:217:24: error: no match for ‘operator=’ in ‘e = (& l)->List<T>::begin<int>()’
    main.cc:217:24: note: candidates are:
    main.cc:143:1: note: List<T>::Iterator<L> List<T>::Iterator<L>::operator=(List<T>::Iterator<typename std::remove_const<L>::type>&) [with L = const int; T = int; typename std::remove_const<L>::type = int]
    main.cc:143:1: note:   no known conversion for argument 1 from ‘List<int>::const_iterator {aka List<int>::Iterator<const int>}’ to ‘List<int>::Iterator<int>&’
    main.cc:156:1: note: List<T>::Iterator<L> List<T>::Iterator<L>::operator=(List<T>::Iterator<const typename std::remove_const<L>::type>&) [with L = const int; T = int; typename std::remove_const<L>::type = int]
    main.cc:156:1: note:   no known conversion for argument 1 from ‘List<int>::const_iterator {aka List<int>::Iterator<const int>}’ to ‘List<int>::Iterator<const int>&’
    

    Die Konstruktoren sind:

    template <typename T>
    template <typename L>
    List<T>::Iterator<L>::Iterator(){
    }
    
    template <typename T>
    template <typename L>
    List<T>::Iterator<L>::Iterator(typename std::vector<typename std::remove_const<L>::type>::iterator it) : index(it) {
    }
    
    template <typename T>
    template <typename L>
    List<T>::Iterator<L>::Iterator(Iterator< typename std::remove_const<L>::type > const & other) : index(other.index) {
    }
    

    Der vollständige Code steht hier: http://codepad.org/SwPgqGmi


  • Mod

    operator=(List<T>::Iterator<typename std::remove_const<L>::type>&)
    

    Faellt dir nichts auf an dieser Zeile? Fehlt fa nicht irgendwo ein const ?



  • Ok, da war noch ein wenig alter Schrott drin, und das const fehlte in der Tat. Ein Schritt weiter, hoffe ich.

    Aktueller Stand: http://codepad.org/8GnALiZN

    So wie ich es sehe, ist das Problem hier:

    template <typename T>
    typename List<T>::const_iterator
    List<T>
    ::begin() const {
        return iterator(queue.begin());
    }
    

    Hier hole ich von queue einen const_iterator, und will ihn auf einen iterator legen. Deswegen sagt er:

    main.cc:204:34: error: no matching function for call to ‘List<int>::Iterator<int>::Iterator(std::vector<int, std::allocator<int> >::const_iterator)’
    

    Kommt man an der Stelle überhaupt weiter, oder muß man zu Tricks wie diesen hier greifen: http://www.sj-vs.net/c-implementing-const_iterator-and-non-const-iterator-without-code-duplication/

    ?? Ich hasse Iteratoren. 😉



  • Hallo zusammen,

    also nun habe ich eine Version, welche funktioniert. 😃
    Hier anzuschauen, bei Interesse: http://codepad.org/yiB048WD (Feedback wie immer willkommen).

    Ich habe dazu ein wenig bei Herrn Stroustrup geschaut. Die Version, wie ich es eigentlich wollte, ein Delegate-Iterator, war selbst mit seinen Beispiel-Code nicht compilierfähig. Aber ne Idee habe ich bekommen. So ist es vielleicht nicht die effizientest Variante, aber geht immerhin. Ich hoffe es sind keine weiteren Fehler drin.

    Eine Frage hätte ich noch. Ich habe ja ne Funktion add(), welche zwei Iteratoren akzeptiert. Nun habe ich festgestellt, dass diese nicht so richtig mit den std::iteratoren zusammenarbeitet. Also ein Aufruf:

    List<int> tempList;
     std::vector<std::string> a;
     tempList.add(a.begin(), a.end());
    

    ergibt:

    main.cc:393:36: error: no matching function for call to ‘List<int>::add(std::vector<std::basic_string<char> >::iterator, std::vector<std::basic_string<char> >::iterator)’
    main.cc:393:36: note: candidates are:
    main.cc:212:1: note: List<T>& List<T>::add(const T&) [with T = int]
    main.cc:212:1: note:   candidate expects 1 argument, 2 provided
    main.cc:221:1: note: List<T>& List<T>::add(List<T>::iterator, List<T>::iterator) [with T = int; List<T>::iterator = List<int>::Iterator<int>]
    main.cc:221:1: note:   no known conversion for argument 1 from ‘std::vector<std::basic_string<char> >::iterator {aka __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >}’ to ‘List<int>::iterator {aka List<int>::Iterator<int>}’
    

    Da noch nen Tip für mich???

    Ansonsten erst mal riesen dank für Eure super Hilfe!!!!!! 🙂

    sven_


  • Mod

    Du musst lernen, solche Fehlermeldungen zu lesen. Es steht schon alles erklaert in der Meldung. Es sieht bloss komplizierter aus, als es ist, wegen der Templates. Da hilft es, den ganzen Templatekram einfach erst einmal zu ignorieren:

    main.cc:393:36: error: no matching function for call to ‘List<int>::add(std::vector<std::basic_string<char> >::iterator, std::vector<std::basic_string<char> >::iterator)’
    

    ➡

    main.cc:393:36: error: no matching function for call to ‘List<int>::add(Blah, Blah)’
    

    (mit Blah = std::vector<std::basic_string<char> >::iterator)
    Aha, es gibt also keine passende Memberfunktion add von List<int>, so wie sie in Zeile 393 benutzt wird.

    main.cc:393:36: note: candidates are:
    

    Aber es gibt andere List<int>::add(), die nicht ganz passen:

    main.cc:212:1: note: List<T>& List<T>::add(const T&) [with T = int]
    main.cc:212:1: note:   candidate expects 1 argument, 2 provided
    

    Es gibt ein add, welches ein const int& erwartet. Klar passt dieses nicht, da es nur 1 Argument nimmt, anstatt 2. Aber es gibt noch einen anderen Kandidaten:

    main.cc:221:1: note: List<T>& List<T>::add(List<T>::iterator, List<T>::iterator) [with T = int; List<T>::iterator = List<int>::Iterator<int>]
    main.cc:221:1: note:   no known conversion for argument 1 from ‘std::vector<std::basic_string<char> >::iterator {aka __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >}’ to ‘List<int>::iterator {aka List<int>::Iterator<int>}’
    

    😮 Wieder erst einmal vereinfachen:

    main.cc:221:1: note: List<T>& List<T>::add(Blupp, Blupp) 
    main.cc:221:1: note:   no known conversion for argument 1 from ‘Blah’ to ‘Blupp’
    

    Das ist doch schon verstaendlicher. Wir haben die passende Argumentenzahl, aber die Typen passen nicht. Jetzt koennen wir genauer auf die Typen gucken. Das 'Blupp' hier ist List<T>::iterator oder, wenn man alle typedefs usw. auswertet, dann bekommt man das was der Compiler in die eckigen Klammern am Ende geschrieben hat: List<T>::iterator = List<int>::Iterator<int>]. Das add erwartet also 2x List<int>::Iterator<int>, also deinen eigenen Iteratortypen.

    Was ist das Blah? std::vector<std::basic_string<char> >::iterator. Wir sehen jetzt schon, dass das nicht passt, da das der Iteratortyp des STL-vectors ist, nicht dein List-Iterator. Falls das nocht nicht gereicht haette, hat uns der Compiler wieder in Klammern gesagt, was das fuer ein Typ ist, wenn man lles bis zum Ende auswertet: __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >
    Daraus koennen wir nicht mehr viel ablesen, das sind nur Details, wie der vector-Iterator intern funktioniert. Wir haben oben ja schon gesehen, was falsch ist.

    P.S.: Zusammenfassung: Du benutzt vector-Iteraoren, wo deine Funktionen deine eigenen Iteratoren erwarten. Du hast keine Konvertierungsfunktion, um einen deiner eigenen Iteratoren aus einem vector-Iterator zu erzeugen (sofern dies ueberhaupt Sinn macht).
    P.P.S.: Deine add-Funktion mit 2 Parametern soll wahrscheinlich ein Template sein. Sie nimmt nicht deine Iteratoren, sondern alle moeglichen Iteratoren. Es soltle dem add schliesslich egal sein, woher die Daten kommen. Siehe die ganzen Funktionen der STL, die das so machen. Z.B.:
    http://www.cplusplus.com/reference/vector/vector/insert/
    Da gibt es die Ueberladung

    template <class InputIterator>
        void insert (iterator position, InputIterator first, InputIterator last);
    

    So soll wahrscheinlich auch dein add aussehen. Diese Muster gibt es an ganz vielen Stellen und du solltest es auch benutzen. So kann man alle moeglivchen Objekte benutzen, sie muessen sich bloss iteratorartig verhalten. Das heisst, du kannst einen STL-Vector ohne Probleme mit Zeigern (Iteratoren sind verallgemeinerte Zeiger), Iteratoren aus anderen STL-containern, oder auch problemlos mit deinem eigenen List-Iterator fuettern. Das insert interessiert hier bloss, dass man den Iterator derefenzieren, kopieren, verlgeichen und mittels ++ erhoehen kann (das wird durch den Begriff "Inputiterator" ausgedrueckt).



  • Hallo SeppJ,

    man, die Doku zu vector habe ich gestern gelesen, ich habe an eine Konvertierung gedacht, statt einfach die Schnittstelle nachzubauen. Echt dumm. 😉

    Nun bin ich dabei, habe aber ne komische Frage:

    Laut

    http://www.cplusplus.com/reference/vector/vector/insert/

    soll insert einen iterator zurückgeben.

    template <class InputIterator>
    iterator insert (const_iterator position, InputIterator first, InputIterator last);
    

    Bei mir sagt aber die stl_vector:

    template<typename _InputIterator>
            void
            insert(iterator __position, _InputIterator __first,
    	       _InputIterator __last)
            {
    	  // Check whether it's an integral type.  If so, it's not an iterator.
    	  typedef typename std::__is_integer<_InputIterator>::__type _Integral;
    	  _M_insert_dispatch(__position, __first, __last, _Integral());
    	}
    

    Habe ich da ne falsche Version??? Nutze die Redhat Devtools 1.1 mit GCC 477 und C++11.





  • Hallo zusammen,

    @Nathan Danke für den Link 😉 Scheint, man sollte doch mal zu Clang wechseln? 😉

    Dann habe ich aber doch noch ein Problem, welches beim Testen aufgefallen ist.

    Ich habe nun Zugriffscode an einigen Stellen durch den Iterator ersetzt, was schön ist, aber offenbar mir um die Ohren fliegt. Ich habe ewig rumdebugged, und nun denk ich, dass das Problem wie folgt ist:

    Peer &
    PeerList::getByID(PeerID id) {
      for(size_t i=0; i< size(); i++){
         if(get(i).getPeerID() == id){
            return get(i);
         }
      }//end for
    }
    

    Geht nicht und führt zu einem Segfault:

    Peer &
    PeerList::getByID(PeerID id) {
       for (PeerList::iterator it = begin(); it != end(); it++) {
    std::cerr<<"current it-elem: "<<*it<<"\n";
          if ((*it).getPeerID() == id) {
    std::cerr<<"found, return "<<*it<<"\n";
             return *it;
          }//end if
       }//End for
    }
    

    Wobei found ... das richtige Objekt ausgibt, der Caller, mehrere Schachtelstufen drüber fällt bei der Ausgabe des Rückgabeobjektes auf die Nase.

    Hab ich dann in meinen Iterator doch noch nen Fehler???
    Die *operator Methode lautet:

    template <typename T>
            template <typename L>
            L &
            List<T>::Iterator<L>::operator*() {
                return container.at(index);
            }
    

    Wobei container der Container to manage ist, welchen ich den Operator mitgebe, und index der Ausgerechnete index, im Sinne von:

    template <typename T>
            template <typename L>
            List<T>::Iterator<L>::Iterator(std::vector<T> & con, typename std::vector<T>::iterator it) : index(it - con.begin()), container(con) {
            }
    

    Nochmals danke für die Hilfe und hoffen auf weitere 😉

    sven_


  • Mod

    Hast du denn inzwischen ueberhaupt die Fehler raus gemacht, die dir ganz am Anfgang genannt wurden? Du schienst die irgendwie nicht gaz ernst zu nehmen, obwohl das krasse Logikfehler waren, die zu genau solchen Problemen fuehren. Lies den Thrread noch einmal und korriegiere alles, was dir gesagt wurde.



  • Hey 🙂

    Also soweit ich konnte, hab ich alle Fehler welche ich gefunden hab gefixt. Hier ist der Fehler wohl eher, dass ich irgendwo ne Kopie statt referenz nutze. Da bin ich noch am schauen. 🙂

    In wie weit wichtig ist es, dass man den reference type etc wie zb der vector bei at() ... Nutzt?


Anmelden zum Antworten