Ich möchte Objekte einer bestimmten Klasse Objekten einer anderen zuordnen. Die Klasse, die ich als Schlüssel verwenden möchte, wurde jedoch nicht von mir geschrieben und ist einfach struct
mit einigen Werten. std :: map ordnet den Inhalt an, und ich habe mich gefragt, wie es funktioniert und ob eine beliebige Klasse als Schlüssel verwendet werden kann oder ob eine Reihe von Anforderungen (Operatoren und was nicht) definiert werden müssen.
In diesem Fall könnte ich einen Wrapper für die Klasse erstellen, die die von der Operator-Map verwendeten verwendet. Ich muss nur wissen, was ich zuerst implementieren muss, und keine der Referenzen für die Klasse, die ich online gefunden habe , gibt sie an.
operator<
für jede Klasse eine zu liefern . Er gab das Beispiel von Stühlen. Sie können sie nach Höhe, Anzahl der Beine oder sogar nach Farbe sortieren, aber was auch immer Sie wählen, ist völlig willkürlich und tatsächlich gibt es keine natürliche Reihenfolge für Stühle, sondern es ist vielmehr der Behälter, der entscheiden muss, wie die Stühle sein sollen bestellt. Zu oftoperator<
scheint eine offensichtliche Wahl nur eine von vielen Möglichkeiten zu sein und gehört als solche nicht in die Klasse ... etwas in dieser Richtung war seine Argumentation.operator <
undstd::less
tut es nicht für Sie, dann eine Vergleichsfunktion als zusätzliches Argument für die Template - Deklaration std :: map schreiben. Wenn Sie die Komparatorfunktion ausführen, ist es am besten, sie als Funktorobjekt zu deklarieren. >> Der Grund, warum es besser ist, das Funktorobjekt auszuführen, besteht darin, dass die Objektinstanz zur Kompilierungszeit optimiert wird, während der Funktionszeiger physisch im Kartenobjekt vorhanden ist und ist viel schwieriger zu optimieren.Sie müssen den Operator <wie folgt definieren:
struct A { int a; std::string b; }; // Simple but wrong as it does not provide the strict weak ordering. // As A(5,"a") and A(5,"b") would be considered equal using this function. bool operator<(const A& l, const A& r ) { return ( l.a < r.a ) && ( l.b < r.b ); } // Better brute force. bool operator<(const A& l, const A& r ) { if ( l.a < r.a ) return true; if ( l.a > r.a ) return false; // Otherwise a are equal if ( l.b < r.b ) return true; if ( l.b > r.b ) return false; // Otherwise both are equal return false; } // This can often be seen written as bool operator<(const A& l, const A& r ) { // This is fine for a small number of members. // But I prefer the brute force approach when you start to get lots of members. return ( l.a < r.a ) || (( l.a == r.a) && ( l.b < r.b )); }
quelle
Die Antwort befindet sich tatsächlich in der Referenz, die Sie verknüpfen, unter der Beschreibung des Vorlagenarguments "Vergleichen".
Die einzige Anforderung ist, dass
Compare
(standardmäßig verwendetless<Key>
, standardmäßigoperator<
zum Vergleichen von Schlüsseln verwendet) eine "streng schwache Reihenfolge" sein muss.quelle
Gleich wie für
set
: Die Klasse muss eine strenge Reihenfolge im Sinne von "kleiner als" haben. Überladen Sie entweder ein geeignetesoperator<
oder geben Sie ein benutzerdefiniertes Prädikat an. Zwei beliebige Objektea
undb
für welche!(a<b) && !(b>a)
wird gleich betrachtet werden.Der Kartencontainer behält tatsächlich alle Elemente in der Reihenfolge bei, die durch diese Reihenfolge bereitgestellt wird. Auf diese Weise können Sie die O- (log n) Such- und Einfügezeit nach Schlüsselwert erreichen.
quelle