Nochmal eigene Klasse in eine map<> schreiben
-
Ich poste meinen Post kurz nochmal, weil er schon fast auf der 2. Seite ist und ich nicht weiß, ob ihn noch jemand sieht und es wichtig ist, dass ich das hinkrieg. Hier also mein Originalpost, die Antwort, die ich bekommen hab und dann mein neuer Post mit dem, was ich ausprobiert hab (funzt aber noch nicht).
Hi!
Ich versuche, eine map zu machen, bei der ich eine Klasse (Vector), die ich >>selbst geschrieben habe, reinschreibe:
map<Vector, unsigned> myMap;
So soll die map eigentlich aussehen. Wenn ich so versuche zu kompilieren, >>bekomme ich einen Fehler, dass etwas an meiner Vector-Klasse fehlt, damit >>man ein Objekt dieser Klasse in die map einfügen kann. Wisst ihr, auf was >>ich achten muss/was ich zu meiner Klasse hinzufügen muss, damit das geht? >>Und wie das geht?
Hab rausgefunden, dass es schon geht, wenn ich meine map so mache:
map<Vector*, unsigned> myMap;
aber mit dem Zeiger ist die map schwieriger zu handhaben.Wär super, wenn ihr mir sagen könntet, wie ich meine Klasse in die map >>kriege.
Thx. Nick.
KPC
MitgliedDu musst meines Wissen einen Standardkonstruktor und einen operator< haben, >damit die Objekte sortiert werden können. Außerdem wahrscheinlich noch einen >operator= und einen Kopierkonstruktor, aber die werden ja sowieso automatisch >generiert!
Ansonsten poste mal die Fehlermeldung.
Ja, ich glaub, du hattest recht, mir fehlt ein < - operator. Ich bekomme diese Fehlermeldung:
c:\programme\microsoft visual studio\vc98\include\functional(86) : error C2784: 'bool __cdecl std::operator <(const class std::multimap<_K,_Ty,_Pr,_A> &,const class std::multimap<_K,_Ty,_Pr,_A> &)' : could not deduce template argument for 'const cla
ss std::multimap<_K,_Ty,_Pr,_A> &' from 'const class graphixdemo::Vector'
c:\programme\microsoft visual studio\vc98\include\functional(86) : while compiling class-template member function 'bool __thiscall std::less<class graphixdemo::Vector>::operator ()(const class graphixdemo::Vector &,const class graphixdemo::Vector &) const'Ich hab jetzt schon versucht, so einen Operator für meine Vector-Klasse zu schreiben, aber das hat nicht funktioniert. Wie würde man das am besten machen, eine <-Operation für einen Vektor? Vergleicht man dann, ob alle Komponenten des Vektors kleiner sind als die eines anderen? Hab da keine so richtige Vorstellung davon.
Meine Vector-Klasse sieht so aus:
class Vector { float x, y, z; // + noch die üblichen Operatoren wie +, -, *, += usw. und Punkt-, Kreuzprodukt usw. };
Hab versucht, den <-Operator so zu implementieren (hab zugegebenermaßen auch nicht wirklich ne Ahnung, wie das eigentlich gehen müsste):
bool operator < (Vector &vec) { if((x<vec.x) && (y<vec.y) && (z<vec.z)) return true; else return false; }
damit bekomm ich aber diese 2 Fehlermeldungen:
error C2805: binary 'operator <' has too few parameters
error C2678: binary '<' : no operator defined which takes a left-hand operand of type 'const class graphixdemo::Vector' (or there is no acceptable conversion)
c:\programme\microsoft visual studio\vc98\include\functional(86) : while compiling class-template member function 'bool __thiscall std::less<class graphixdemo::Vector>::operator ()(const class graphixdemo::Vector &,const class graphixdemo::V
ector &) const'Wär cool, wenn ihr mir sagen könntet, wie das geht, am besten mit kurzem Code für den <-Operator.
Thx! Nick.
-
Ich würde keinen operator< definieren, da es eigentlich keine richtige Ordnung für Vektoren gibt. Du brauchst nur eine irgendwie definierte Ordnung fürs Sortieren (und die Map halt), die ausserhalb davon keinen Sinn ergeben muss. Also würd ich eine simple Funktion dafür schreiben und als drittes Template-Argument an map übergeben.
Zum Algorithmus ... lexikographische Ordnung tut immer. Dh man sortiert so wie Wörter im Lexikon. Zuerst das erste Element vergleichen, evtl. das zweite, evtl. das dritte usw.// ungetestet, als Anregung bool compare(const Vector& a, const Vector& b) { if (a.x < b.x) return true; else if (a.x > b.x) return false; else if (a.y < b.y) return true; else if (a.y > b.y) return false; else if (a.z < b.z) return true; else return false; } //... map<Vector, int, compare> myMap;
-
Meine map befindet sich in einer anderen Klasse als Vector. Deshalb hab ich jetzt compare() in Vector mit reingenommen, wie du gesagt hast und versucht, die map so zu erstellen:
map<Vector, unsigned, Vector::compare> myMap;
bekomme dann aber diese Fehlermeldung:
c:\myFile.h(76) : error C2923: 'map' : 'Vector::compare' is invalid as template argument '#3', type expected
Wie muss ich das schreiben, damit die map richtig erstellt werden kann?
-
Ich hab nicht gesagt, dass das eine Memberfunktion sein soll.
-
OK, ich hab sie jetzt nicht als Memberfunktion gemacht und versuche, die map so zu erzeugen:
map<Vector, unsigned, compare> myMap;
und bekomme dann diesen Fehler (ist glaub noch der gleiche wie vorher):
c:\myFile.h(76) : error C2923: 'map' : 'compare' is invalid as template argument '#3', type expected
c:\vector.h(93) : see declaration of 'compare'Was mach ich falsch?
-
Kann es sein, dass ich einen Funktionenzeiger auf compare() brauche?
-
die map erwartet als template argument einen typen.
map<Vector, unsigned, bool (*) (const Vector&, const Vector&)>
den comparator kannst du ihr dan via constructor übergeben.
so sieht's fertig aus:bool compare (const Vector &a, const Vector &b) { /*...*/ } map<Vector, unsigned, bool(*)(const Vector&, const Vector&)> your_map(compare);
idealerweise wirst du wohl ein typedef verwenden, oder statt der funktion einen functor verwenden müssen.
-
Tut mir leid, das kommt davon wenn man keine Ahnung hat und irgendwas postet ...
also es müsste so gehen:
map<Vector, int, bool (*)(const Vector&, const Vector&)> myMap(compare);
Eine Möglichkeit ohne Funktionszeiger, dafür mit Funktionsobjekt, sieht so aus:
struct Vector_comparison { bool operator()(const Vector& a, const Vector& b) { // selber code wie in compare } }; map<Vector, int, Vector_comparison> myMap;
PS an alle: Rein aus Interesse, wieso produziert GCC keinen Segfault wenn ich in der ersten Version im Konstruktor nichts angebe, und dann mehrere Elemente einfüge? Ein default-konstruierter Funktionszeiger müsste doch ein Nullpointer sein, ein Aufruf dessen fatal ...
-
Bashar schrieb:
PS an alle: Rein aus Interesse, wieso produziert GCC keinen Segfault wenn ich in der ersten Version im Konstruktor nichts angebe, und dann mehrere Elemente einfüge? Ein default-konstruierter Funktionszeiger müsste doch ein Nullpointer sein, ein Aufruf dessen fatal ...
Das würde mich auch interessieren, besonders da mein gcc 3.3.2 wie erwartet einen Segfault produziert.
-
Vergesst es, eindeutig: PEBKAC
-
Bashar schrieb:
Vergesst es, eindeutig: PEBKAC
Favoriten -> Internet Acronyms Dictionary -> PEBKAC -> Search -> Ah
Immer wieder schön diese Form der Kommunikation