Funktion mit einem Map-Iterator als Rückgabewert
-
Hallo,
ich will mir eine eigene Map-Klasse schreiben und bin gerade dabei, eine Funktion zu schreiben, die mir einen Iterator auf ein pair der Map zurückgibt. Der Compiler will das aber nicht schlucken: (A und B sind dabei die Templates der Map)mymap<A, B>::iterator getElement(double num) { mymap<A, B>::iterator p; if((this -> end()) - (this -> begin()) < num) return (* (new B)); //wenn die map nicht so viele Elemente hat p += (int)num - 1; return p; }
Er sagt nämlich:
error: expected ';' before "getElement"
Wenn ich nur
iterator getElement(double num)
schreibe, sagt er mir:
error: iterator does not name a type
PS: Natürlich habe ich public von Map geerbt.
-
typename mymap<A, B>::iterator getElement(double num)
bb
-
if((this -> end()) - (this -> begin()) < num) return (* (new B)); //wenn die map nicht so viele Elemente hat p += (int)num - 1;
bäh...
willst du noch ändern, oder?
-
unskilled schrieb:
if((this -> end()) - (this -> begin()) < num) return (* (new B)); //wenn die map nicht so viele Elemente hat p += (int)num - 1;
bäh...
willst du noch ändern, oder?Vielleicht eine Exception werfen, aber ansonsten...
-
unskilled schrieb:
typename mymap<A, B>::iterator getElement(double num)
bb
OK, Danke, das funktioniert.
Hier jetzt die ganze Klasse, die Funktion ist jetzt auch mit Exceptionhandling.
PS: Die Zählung bei der Funktion fängt bei 1 an und nicht bei 0.template <class A, class B> class mymap : public map<A, B> { public: mymap() : map<A, B>::map() {} B &operator[](register A object) { return (this -> find(object)) -> second; } void set(register A a, register B b) { this -> erase(a); this -> insert(pair<A, B> (a, b)); } typename mymap<A, B>::iterator getElement(register double num) { num = (int)num; typename mymap<A, B>::iterator p = this -> begin(); if((this -> size()) <= num) throw "Zu wenig Elemente vorhanden"; else if(num < 1) throw "Die Map fängt bei 1 an."; for(register int c = 0; c < num; c++) p++; return p; } };
-
Vielleicht eine Exception werfen, aber ansonsten...
nö, das meinte ich nicht^^
ich meinte das stück:return (* (new B));
(wobei die nächste zeile auch nicht viel besser ist...)wxSkip schrieb:
//hier steht sicherlich (in nem header!) using namespace std davor -> das tut man nicht! template <class A, class B> class mymap : public map<A, B> { //das ableiten von stdandard-lib-objekten ist btw auch keine gute idee - wegen des nicht virtuellen dtors... public: mymap() : map<A, B>::map() {} //unnötig B &operator[](register A object) //wieso register? wer erzählt denn, dass so was nötig ist? wieso keine const ref? { return (this -> find(object)) -> second; //wieso schreibst du immer this mit } //und weshalb machst du so extrem viele leerzeichen? void set(register A a, register B b) //register -> s.o. { this -> erase(a); this -> insert(pair<A, B> (a, b)); //std::make_pair(a, b) } typename mymap<A, B>::iterator getElement(register double num) { //wieso double? was meinst du, wozu der size_type da ist? num = (int)num; typename mymap<A, B>::iterator p = this -> begin(); //hier reicht ein iterator p = begin(); if((this -> size()) <= num) throw "Zu wenig Elemente vorhanden"; //const char* werfen? OO else if(num < 1) throw "Die Map fängt bei 1 an."; //assert reicht vollkommen for(register int c = 0; c < num; c++) p++; //register -> s.o.; int == fail! return p; } };
insg. kein anwendungsgebiet für vererbung sondern für freie fkt.
die 2. fkt gibts btw auch schon ;o)iterator ret_val = begin(); std::advance(ret_val, size); return ret_val;
wie du aush siehst, berücksichtige ich hier logikfehler nicht extra - könnte man aber mit nem assert machen:
assert(the_size > size()); iterator ret_val = begin(); std::advance(ret_val, the_size); return ret_val;
siehe auch:
http://www.cplusplus.com/reference/std/iterator/advance/bb
PS:
Allein schon die Existenz einer solchen Fkt:
typename mymap<A, B>::iterator getElement(register double num)
ist ein Indikator für den falschen Container...
-
unskilled schrieb:
insg. kein anwendungsgebiet für vererbung sondern für freie fkt.
PS:
Allein schon die Existenz einer solchen Fkt:
typename mymap<A, B>::iterator getElement(register double num)
ist ein Indikator für den falschen Container...@1. Meinetwegen freie Funktionen, aber die Operatoren kann man nicht als freie Funktionen machen und dann kann man auch gleich vererben.
@2. Die Funktion ist ja nur, um die Elemente einer mymap<string, string> alphabetisch sortiert zu bekommen.
-
wxSkip schrieb:
@1. Meinetwegen freie Funktionen, aber die Operatoren kann man nicht als freie Funktionen machen und dann kann man auch gleich vererben.
Den op[] zu überladen find ich aber auch richtig doof... Noch dazu, weil du die const - Version nicht überladen hast... Außerdem verwirrst du dann jeden, der weiß, was der op[] einer std::map macht...
und ich find einthe_map.find(x)->second;
viel intuitiver als die Benutzung eines operators...wxSkip schrieb:
@2. Die Funktion ist ja nur, um die Elemente einer mymap<string, string> alphabetisch sortiert zu bekommen.
Das ist aber doof...
for(std::map::const_iterator i(the_map.begin()), e(the_map.end()); i != e; ++i) std::cout << i->first << '\t' << i->second;
geht auch als einzeiler mit
std::copy
...in meinem post stand aber mehr als nur die beiden punkte - ich hoffe, du hast die wenigsten mal durchgelesen und in deinem quelltext ggf. geändert....
bb
-
unskilled schrieb:
in meinem post stand aber mehr als nur die beiden punkte - ich hoffe, du hast die wenigsten mal durchgelesen und in deinem quelltext ggf. geändert....
bb
Also, das mit dem advance hab ich geändert. Die existierende Funktion kenn ich nicht, sonst macht man das doch immer mit insert und pair<>()?!
-
unskilled schrieb:
Den op[] zu überladen find ich aber auch richtig doof... Noch dazu, weil du die const - Version nicht überladen hast...
Die const-Version wäre dann:
const B &operator[](register A object) const;
oder?
Wann wird die dann ausgeführt? Wenn ich den Operator mit einem const-Element aufrufe, oder was?