Problem mit (*Iterator)



  • Der Compiler generiert einen Fehler bei folgendem Code:

    struct SSectionData {...};
    
    typedef std::wstring tstring;
    typedef std::map<tstring, SSectionData> section_map;
    typedef std::pair<tstring, SSectionData> section_pair;
    typedef std::vector<section_pair*> sorted_section_vector;
    
    void SortSections(sorted_section_vector& Output)
    {
      section_map& SectionMap = GetSectionMap();
      section_map::iterator SectionIter = SectionMap.begin();
      ...
      section_pair& Test = (*SectionIter); // Fehler
      ...
    }
    

    error C2440: 'Initialisierung': 'std::pair<_Ty1,_Ty2>' kann nicht in 'section_pair &' konvertiert werden

    Das funktioniert auch nicht:

    std::pair<tstring, SSectionData>& Test = (*SectionIter);
    

    error C2440: 'Initialisierung': 'std::pair<_Ty1,_Ty2>' kann nicht in 'std::pair<_Ty1,_Ty2> &' konvertiert werden

    Das funktioniert jedoch:

    section_pair Test = (*SectionIter);
    

    Aber ich möchte einen Zeiger auf das in der map gespeicherte Pair, keine Kopie. Und so weit ich sehen kann, liefert doch *SectionIter eine Referenz auf das gespeicherte Pair zurück, oder? (Mein eigentliches Ziel:)

    section_pair* Test = &(*SectionIter);
    Output.insert(InsertPosition, Test);
    

    error C2440: 'Initialisierung': 'std::pair<_Ty1,_Ty2> *' kann nicht in 'section_pair *' konvertiert werden

    Hat jemand eine Idee, wodran es liegen könnte? 😕


  • Administrator

    1. Du gibst nicht die ganzen Fehlermeldungen an.
    2. Da man bei einer std::map den Key nicht einfach verändern darf, wird beim Dereferenzieren eines Iterators ein std::pair<Key const, Mapped>& zurückgegeben. Dies wäre auch sehr gut aus der Fehlermeldung ersichtlich, wenn du sie eben ganz angegeben hättest.
    3. Die Kopie funktioniert, da du dadurch keine Referenz auf den Key mehr hast, sondern eben eine Kopie. Daher muss Key im kopierten Typ nicht konstant sein.

    Grüssli



  • Das ist wirklich die ganze Fehlermeldung. Das einzige was ich davon entfernt hab, ist die Datei, in der der Fehler auftritt...

    Und es wird in der Tat pair<const Key, Type> zurückgegeben 🙄
    Danke 🙂


  • Administrator

    Gugi schrieb:

    Das ist wirklich die ganze Fehlermeldung. Das einzige was ich davon entfernt hab, ist die Datei, in der der Fehler auftritt...

    100%ig nicht!
    Darunter steht immer noch in eckigen Klammer was _Ty1, _Ty2, usw. bedeutet. Solche Fehlermeldungen sind meistens mehrere Zeilen lang.

    Hier ein Beispiel (auch nur der Pfad rausgekürzt):

    #include <map>
    
    int main()
    {
    	std::map<int, int> map;
    	map[0] = 0;
    
    	std::pair<int, int>& p = *map.begin();
    
    	return 0;
    }
    
    1>Compiling...
    1>main.cpp
    1>error C2440: 'initializing' : cannot convert from 'std::pair<_Ty1,_Ty2>' to 'std::pair<_Ty1,_Ty2> &'
    1>        with
    1>        [
    1>            _Ty1=const int,
    1>            _Ty2=int
    1>        ]
    1>        and
    1>        [
    1>            _Ty1=int,
    1>            _Ty2=int
    1>        ]
    

    Grüssli



  • Oha! Ich schaue in VS2008 immer in der "Fehlerliste" nach, dort steht das nicht. In der "Ausgabe" steht es jedoch... Und wieder was gelernt^^


  • Administrator

    Hmmm, stimmt, es gibt ja noch eine Fehlerliste 🙂
    Die benutze ich persönlich eigentlich nie, weil sie eben nicht alle Informationen anzeigt. Zudem kannst du in der Ausgabe auch einen Doppelklick auf den Fehler machen und kommst zur entsprechenden Stelle. Die Fehlerliste ist eigentlich total überflüssig, sie stellt es höchstens ein wenig schöner dar und lässt ein paar Sortierungen zu. Habe ich aber noch nie benötigt.

    Grüssli



  • Huch, Fehlerliste. Wusste gar nicht, dass es die gibt, aber konnte bisher trotzdem Fehler beheben. 🙂

    In MSVC++ gibt es sowieso einige Menüs, die ich noch nie verwendet habe...



  • Nexus schrieb:

    Huch, Fehlerliste. Wusste gar nicht, dass es die gibt, aber konnte bisher trotzdem Fehler beheben. 🙂

    In MSVC++ gibt es sowieso einige Menüs, die ich noch nie verwendet habe...

    Dito. Imo braucht man eh keine grosse Filterung der Probleme/Warnungen. Fehler muss man sowieso beim ersten beginngen abarbeiten und Warnungen.. Naja.. Die sollten einen eh ständig nerven, dass man etwas dagegen tut. 🙂



  • drakon schrieb:

    [...] und Warnungen.. Naja.. Die sollten einen eh ständig nerven, dass man etwas dagegen tut. 🙂

    Hm, manchmal gibt es aber schon so eine Versuchung zu #pragma warning(disable: ) - zum Beispiel bei "Zuweisungsoperator konnte nicht generiert werden" - das weiss ich, wenn ich const -Member habe, und jetzt? 😉



  • Nexus schrieb:

    drakon schrieb:

    [...] und Warnungen.. Naja.. Die sollten einen eh ständig nerven, dass man etwas dagegen tut. 🙂

    Hm, manchmal gibt es aber schon so eine Versuchung zu #pragma warning(disable: ) - zum Beispiel bei "Zuweisungsoperator konnte nicht generiert werden" - das weiss ich, wenn ich const -Member habe, und jetzt? 😉

    Ja, klar, das kann man natürlich machen, aber nicht gerade beim ersten mal, sondenr erst, wenn die Warnung wirklich nervt. Allerdings würde ich da eh nicht die Warnung ausschalten, sondern den Zuweisungsoperator halt privat deklarieren.


  • Administrator

    drakon schrieb:

    Ja, klar, das kann man natürlich machen, aber nicht gerade beim ersten mal, sondenr erst, wenn die Warnung wirklich nervt. Allerdings würde ich da eh nicht die Warnung ausschalten, sondern den Zuweisungsoperator halt privat deklarieren.

    Es ist allerdings problematisch, wenn die Klasse aus einer anderen Bibliothek stammt. Habe ich zum Beispiel bei Boost.Fusion erlebt und weil das noch riesige Templatekonstrukte sind, hast du zu jeder Warnung noch die Erklärungen, von welcher Instantiierung mit welchen Parametern 🙂

    Grüssli



  • Hehe. Dann schalt halt die Warnung aus.. :p



  • Dravere schrieb:

    drakon schrieb:

    Ja, klar, das kann man natürlich machen, aber nicht gerade beim ersten mal, sondenr erst, wenn die Warnung wirklich nervt. Allerdings würde ich da eh nicht die Warnung ausschalten, sondern den Zuweisungsoperator halt privat deklarieren.

    Es ist allerdings problematisch, wenn die Klasse aus einer anderen Bibliothek stammt. Habe ich zum Beispiel bei Boost.Fusion erlebt und weil das noch riesige Templatekonstrukte sind, hast du zu jeder Warnung noch die Erklärungen, von welcher Instantiierung mit welchen Parametern 🙂

    Grüssli

    Ich geh dann eher dazu über, die Bibliotheksklasse zu wrappen, da ich sowieso meist die Schnittstelle an meine Bedürfnisse anpassen muss - dann ist der private op= nur eine Fingerübung 🙂


  • Administrator

    pumuckl schrieb:

    Ich geh dann eher dazu über, die Bibliotheksklasse zu wrappen, da ich sowieso meist die Schnittstelle an meine Bedürfnisse anpassen muss - dann ist der private op= nur eine Fingerübung 🙂

    Boost.Fusion wrappen ... öhm, wozu? Das ist ein TMP Tuple Boost.MPL Konstrukt. Nicht nur das es extrem Anpassungsfähig ist, es dürfte wohl auch recht viel Aufwand sein, das Zeug zu wrappen 🙂

    Und also irgendwo hat es ja Grenzen. Eine Woche (vielleicht mehr?) einen Wrapper schreiben gegenüber einem simplen disable warning ?

    Grüssli


Anmelden zum Antworten