Kleiner-Operator zum Sortieren überladen
-
Vielleicht einfach
boolzurückgeben?
-
SeppJ meint:
struct s { std::string name; int wert; }; // freie Funktion operator<; -> Return Typ ist natürlich bool bool operator< ( s const& a, s const& b ) // Bem.: a UND b sind const! { return a.wert < b.wert; }
-
Und die andere, technisch richtige, aber ungewöhnliche Methode wäre:
struct s { string name; int wert; bool operator< ( s const& rhs ) const // So macht man Methoden const { return ( wert < rhs.wert ); } };
-
Merci - etz schauen wir mal ob der Build da fluppt!
-
Und
const-Lösung:bool operator< (s const& rhs) const { return this->wert < rhs.wert; }
-
Jay1980 schrieb:
Merci - etz schauen wir mal ob der Build da fluppt!
Und danach lesen wir nochmal die Fehlermeldung und versuchen zu verstehen, was der Compiler uns mitteilen möchte:
from main.cpp:8: /usr/include/c++/4.4/bits/stl_algo.h: In function ‘const _Tp& std::__median(const _Tp&, const _Tp&, const _Tp&) [with _Tp = s]’: In file included from /usr/include/c++/4.4/algorithm:62, /usr/include/c++/4.4/bits/stl_algo.h:2268: instantiated from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<s*, std::vector<s, std::allocator<s> > >, _Size = int]’ /usr/include/c++/4.4/bits/stl_algo.h:5220: instantiated from ‘void std::sort(_RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator<s*, std::vector<s, std::allocator<s> > >]’ main.cpp:100: instantiated from here /usr/include/c++/4.4/bits/stl_algo.h:89: error: could not convert ‘operator<(const s&, const s&)(((const s&)((const s*)__b)))’ to ‘bool’Im Grunde genommen ist alles bis zum error: nur ein Wegweiser, wo der Fehler auftaucht, und wo er herkommt. Zeile für Zeile:
- (in main.cpp, Zeile 8 hast du etwas geschrieben, was den Fehler verursacht, nämlich incirekt den Header eingebuden, an der die Stelle unmittelbar auftritt)
- es wird das Funktionstemplate std::__median instantiiert, mit Templateparameter s. In dieser Funktion passiert der Fehler (Das template befindet sich in stl_algo.h)
- (Diese datei wird in <algorithm> auf Zeile 62 includet)
- die std::_median-Funktion wird instantiiert, weil std::__introsort_loop instantiiert wurde (Datei- und Zeilenangabe vorne, hinten die angabe welche Templateparameter)
- diese Funktion wurde wiederum von std::sort instantiiert (Datei- und Zeilenangabe vorne, hinten die angabe welche Templateparameter)
- diese hast du in main.cpp, Zeile 100 instantiiert
- Der Fehler (der in std::__median) ist, dass der Compiler das Ergebnis eines operator<(s const&, s const&) nicht in einen bool konvertieren kann.
Das Einfachste ist immer, nach dem error: zu suchen. Dort steht das eigentliche Problem. Den ganzen Rest bräuchtest du nur, wenn du wissen willst, warum er diesen op< denn überhaupt aufruft und das Ergebnis in ein bool verwandeln möchte.
Mal was allgemeines zur Operatorüberladung: http://magazin.c-plusplus.net/artikel/�berladung von Operatoren in CPlusPlus (Teil 1)
-
Wunderbar, mein kleines Beispiel läuft, ich strauchle beim Transfer in mein 'richtiges' Programm, bei dem namespaces verwendet werden.
#include <algorithm> #include <cstdlib> #include <iostream> #include <vector> using namespace std; namespace global { struct s { string name; int wert; }; } // Operator-Überladung als freie Funktion bool operator<(global::s const& lhs, global::s const& rhs) { return lhs.wert < rhs.wert; } /* * */ int main(int argc, char** argv) { cout << " Start Spielwiese ... " << endl; vector<int> v; v.push_back( 2 ); v.push_back( 3 ); v.push_back( 1 ); v.push_back( 5 ); v.push_back( 6 ); v.push_back( 4 ); cout << " Ausgabe der Liste:\n"; vector<int>::const_iterator iter1 = v.begin(); int c1 = 0; while (iter1 != v.end() ) { cout << " Lauf ... Item ("; cout << c1 << "): "; cout << *iter1 << ";\n"; ++iter1; c1++; } // Sortierung sort( v.begin(), v.end() ); cout << " Ausgabe der Liste:\n"; vector<int>::const_iterator iter2 = v.begin(); int c2 = 0; while (iter2 != v.end() ) { cout << " Lauf ... Item ("; cout << c2 << "): "; cout << *iter2 << ";\n"; ++iter2; c2++; } // Lauf mit Strukturen global::s s1; s1.name = "Item-Eins"; s1.wert = 2; global::s s2; s2.name = "Item-Zwei"; s2.wert = 3; global::s s3; s3.name = "Item-Drei"; s3.wert = 1; vector<global::s> v2; v2.push_back( s1 ); v2.push_back( s2 ); v2.push_back( s3 ); cout << "Ausgabe der Listen:\n"; vector<global::s>::const_iterator iter3 = v2.begin(); int c3 = 0; while (iter3 != v2.end()) { cout << " Lauf ... Item ("; cout << c3 << "): "; cout << iter3->name << " - "; cout << iter3->wert << ";\n"; ++iter3; c3++; } // Sortierung sort( v2.begin(), v2.end() ); cout << "Ausgabe der Listen:\n"; vector<global::s>::const_iterator iter4 = v2.begin(); int c4 = 0; while (iter4 != v2.end()) { cout << " Lauf ... Item ("; cout << c4 << "): "; cout << iter4->name << " - "; cout << iter4->wert << ";\n"; ++iter4; c4++; } cout << " ... ENDE" << endl; return 0; }Auszug aus Fehlermeldung, ich habe natürlich genau auf den ersten 'error' geachtet ... mein Überladungsversuch scheint beim Compiler nicht als solcher anzukommen:
make[1]: Verlasse Verzeichnis '/home/jay/gtd08042010/begleitend/fu-hagen/masterarbeit/h2r_bioinf/workspace-21122010/spielwiese'
from main.cpp:8:
/usr/include/c++/4.4/bits/stl_algo.h: In function ‘const _Tp& std::__median(const _Tp&, const _Tp&, const _Tp&) [with _Tp = global::s]’:
In file included from /usr/include/c++/4.4/algorithm:62,
/usr/include/c++/4.4/bits/stl_algo.h:2268: instantiated from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<global::s*, std::vector<global::s, std::allocatorglobal::s > >, _Size = int]’
/usr/include/c++/4.4/bits/stl_algo.h:5220: instantiated from ‘void std::sort(_RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator<global::s*, std::vector<global::s, std::allocatorglobal::s > >]’
main.cpp:98: instantiated from here
/usr/include/c++/4.4/bits/stl_algo.h:89: error: no match for ‘operator<’ in ‘__a < __b’
/usr/include/c++/4.4/bits/stl_algo.h:90: error: no match for ‘operator<’ in ‘__b < __c’
/usr/include/c++/4.4/bits/stl_algo.h:92: error: no match for ‘operator<’ in ‘__a < __c’
/usr/include/c++/4.4/bits/stl_algo.h:96: error: no match for ‘operator<’ in ‘__a < __c’
/usr/include/c++/4.4/bits/stl_algo.h:98: error: no match for ‘operator<’ in ‘__b < __c’
/usr/include/c++/4.4/bits/stl_algo.h: In function ‘_RandomAccessIterator std::__unguarded_partition(_RandomAccessIterator, _RandomAccessIterator, _Tp) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<global::s*, std::vector<global::s, std::allocatorglobal::s > >, _Tp = global::s]’:
/usr/include/c++/4.4/bits/stl_algo.h:2268: instantiated from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<global::s*, std::vector<global::s, std::allocatorglobal::s > >, _Size = int]’
/usr/include/c++/4.4/bits/stl_algo.h:5220: instantiated from ‘void std::sort(_RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator<global::s*, std::vector<global::s, std::allocatorglobal::s > >]’
main.cpp:98: instantiated from here
-
Du solltest eventuell den Vergleichsoperator in den Namensraum mit reinpacken:
namespace global { struct s { string name; int wert; }; bool operator<(s const& lhs, s const& rhs) { return lhs.wert < rhs.wert; } }(keine Sorge - der Compiler ist clever genug, den Operator dort zu finden)
-
Wenn du das wie CStoll empfiehlt machst, dann kannst du auch noch mal nach "argument dependent lookup" oder "Koenig lookup" googlen. Das ist zwar eine recht spezielle Eigenschaft von C++, aber wichtig zu wissen, wenn man mit Namespaces arbeitet.
-
CStoll schrieb:
Du solltest eventuell den Vergleichsoperator in den Namensraum mit reinpacken:
Nicht nur eventuell. Da Überladungen für < auch im Namensraum std existieren, wird beim unqualifizierten Lookup innerhalb eines Standardalgorithmus der globale Namensraum wahrscheinlich nicht durchsucht werden. Damit bleibt nur ADNL übrig.