Gibts ne Typenerkennung fuer Iteratoren ???
-
also gut, aber das eine mal eben iterator, das andere mal reverse_iterator, und
diesen Unterschied muss ich doch in der Schleife durch den Container im Falle eines
reverse_iterators mit nem break quitieren.
Da hab ich u.U. ja auch ein generelles Verstaendnisproblem, von wegen zur
Compile-Zeit bzw zur Laufzeit:
Wird denn die template-Funktion fuer verschiedene Aufrufe anders compiliert?
Dann ist ja ne template-Funktion nur'n hack fuer'n programisten, und compiliert
gibt's die Funktion dann sooft, wie sie aufgerufen wird??
Diese Antworten wuerden mir wirklich weiter helfen, so zum Verstaednis eben...SF
-
Die template-Funktion wird mehrfach instanziiert, für jede Kombination von Typen mindestens einmal.
Wenn Du
Funktion<int>(); schreibst, dann wird Funktion mit dem Typ int instanziiert und aufgerufen. Das instanziieren passiert zur Compilezeit.
Schreibst Du jetzt Funktion<float> dann wird eine neue Funktion generiert mit float als Parameter. usw.
Es wird nicht die gleiche Funktion wiederverwendet. Das template ist eine Vorlage, sozusagen eine Bauanleitung für Klassen/Funktionen bei denen noch ein paar Sachen offen gelassen wurden (die template-Parameter). Wenn Du die jetzt angibst, dann werden die entsprechenden Funktionen generiert. Aber dieses einfügen kann nur zur Compilezeit geschehen. Es gibt keine Syntax die es ermöglicht das erst zur Laufzeit zu tun, ginge ja auch nicht.MfG Jester
-
Ok, das hab ich nun verstanden; ist es denn in diesem Fall besser, nur EINE
template-Funktion zu benutzen, in der ich dann zur "Compile-Zeit" im Falle eines
reverse_iterators bei Fund die Schleife durch den entsprechenden Container
abbreche, oder eine "normale" ueberladene Funktion zu schreiben, die dann aber
doppelt so oft geschrieben werden muss, wie es verschiedene Container bzw.
verschiedene Key-types gibt?
Was ist der bessere oder sinnvollere Programmierweg?SF
-
Die Funktion als template zu schreiben ist natürlich sinnvoll, Du sagst ja selbst, man muß die Funktion nicht mehrmals schreiben. Und mit den oben gezeigten Tricks von davie kann man die Funktionen sogar abhängig vom Parameter leicht modifizieren.
templates sind oft gut geeignet wenn man eine Funktion mehrmals schreiben müßte, jedesmal nur mit kleinen Unterschieden.
-
Na dann war ich immerhin schon aufm richtigen Weg
Jetzt muss ich dann nur noch davies methode zu Erennung des reverse_iterators
begreifen, aber heut nicht mehr.
Danke soweit mal, frag dann wieder wenn ich richtig vor meinem Code sitz und's
nich mehr blickSchoenen Abend
SF
-
Nabend,
hab's jetzt folgendermasen geloest:
template <typename K, typename S> inline bool REV_IT(std::map<K,S>::iterator it){ return false; } template <typename K, typename S> inline bool REV_IT(std::multimap<K,S>::iterator it){ return false; } template <typename K, typename S> inline bool REV_IT(std::map<K,S>::reverse_iterator it) { return true; } template <typename K, typename S> inline bool REV_IT(std::multimap<K,S>::reverse_iterator it) { return true; } // und der Aufruf: template<typename InIt, typename K, typename S> InIt find_in(InIt BEG, InIt FIN, const S LAST_OPEN){ InIt RESULT = FIN; while(BEG != FIN){ if(strcmp((*BEG).second.c_str(), LAST_OPEN.c_str()) == 0){ RESULT = BEG; if(REV_IT<K,S>(BEG) == true) break; } ++BEG; } return RESULT; }
Mit davie's Vorschlag:
template <class It> inline bool is_reverse (It) { return false; } template <class It> inline bool is_reverse (reverse_iterator<It>) { return true; }
gab's nen Parse Error vor dem ">"-Zeichen in der hier letzten Zeile. War denn
sein Vorschlag nur schematisch, oder fehlt mir fuer das Argument: (reverse_iterator<It>)
was includiertes (und das Verstaendnis).
Trotzdem funktioniert die o.g. ueberladene Funktion REV_IT, und wenn ich's richtig
verstanden hab, muesste ich sie bezueglich map und multimap garnicht ueberladen, da
sich die Iteratoren der sehr aehnlichen Container vermutlich von ihrer Struktur her
nicht unterscheiden?Vielen Dank fuer alle Tips und Erklaerungen
SF
-
Nimm mal noch ein
#include<iterator>
dazu. und denk dran, daß das reverse_iterator-template in std íst.
Eine ganz waschechte Compile-time Lösung ist da übrigens nicht, aber die Entscheidung wird wahrscheinlich dann rausoptimiert.MfG Jester
-
Hallo Jester,
das war der genau richtige Tip(std::reverse_iterator), somit funktioniert es auf alle Faelle ohne dass fuer map und multimap ueberladen werden muss.
Was meinst denn mit
Jester schrieb:
...aber die Entscheidung wird wahrscheinlich dann rausoptimiert.
Dass der Compiler dieses macht
Danke nochmal, schoenen Abend
SF
-
na, bist du ein Stück weiter gekommen. Freud mich für dich.
Habe mal'ne Frage zur Funktion find_in
also angenommen (position eintrag)
0 A, 1 B,2 C, 3 C, 4 D, 5 D, 6 E sind in der Mapppe.
suche C vorwärts würde position 3 ergeben
suche C rückwärts würde position 3 ergebenAlso soll die Funktion den letzten in vorwärts Richtung finden
und den ersten in rückwärts Richtung.hätte da noch ein Vorschlag zu machen
partielle Spezialisierung von Templates
Na ja, guck es dir an vielleicht hilft es jatemplate<class C> C find_in(C first,C last,const string& s) { std::cout<<"basis"<<std::endl; return first; } template<class C> C::iterator find_in(C::iterator first,C::iterator last,const string& s) { std::cout<<"iterator"<<std::endl; C::iterator RetIter; while(first!=last) { if(first->second==s) RetIter=first; first++; } return RetIter; } template<class C> C::reverse_iterator find_in(C::reverse_iterator first,C::reverse_iterator last,const string& s) { std::cout<<"reverse_iterator"<<std::endl; while(first!=last) { if(first->second==s) return first; first++; } return first; } typedef std::multimap<int,string> MINT; int main(int argc, char* argv[]) { MINT m_Int; MINT::reverse_iterator rIter; MINT::iterator Iter; m_Int.insert(MINT::value_type(0,"a")); m_Int.insert(MINT::value_type(1,"b")); m_Int.insert(MINT::value_type(2,"c")); m_Int.insert(MINT::value_type(3,"c")); m_Int.insert(MINT::value_type(4,"d")); m_Int.insert(MINT::value_type(5,"d")); m_Int.insert(MINT::value_type(6,"e")); Iter=find_in<MINT>(m_Int.begin(),m_Int.end(),"c"); rIter=find_in<MINT>(m_Int.rbegin(),m_Int.rend(),"c"); if(Iter!=m_Int.end()) std::cout<<Iter->first<<Iter->second<<std::endl; if(rIter!=m_Int.rend()) std::cout<<rIter->first<<rIter->second<<std::endl; return 0; }
-
hi,
idefix schrieb:
Habe mal'ne Frage zur Funktion find_in
also angenommen (position eintrag)
0 A, 1 B,2 C, 3 C, 4 D, 5 D, 6 E sind in der Mapppe.
suche C vorwärts würde position 3 ergeben
suche C rückwärts würde position 3 ergebenAlso soll die Funktion den letzten in vorwärts Richtung finden
und den ersten in rückwärts Richtung.Ja, die Funktion soll in jedem Fall die letzte Uebereinstimmung (von vorne her gesehen) finden;
Aber vielleicht hab ich ja da mal wieder ein grundlegendes Verstaendisproblem, ich dachte, dass bei der Suche mit nem iterator von vorne, und mit nem reverse_iterator eben von hinten "gesucht" wird, so dass die iterator-Variante bei Deinem Beispiel die "Zeile:" 3 C, und bei der reverse_iterator-Variante die "Zeile:" 2 C zurueckgeben taete, wohlbemerkt ohne die break-Version bei der reverse_iterator-Variante.Bei Deinem Vorschlag mit der ueberladenen Version wird bei der reverse_iterator-Variante schon beim ersten Fund returned, was (eigentlich sollte die Funktion
find_last_in(X,Y,S) statt find_in(X,Y,S) heissen) dann latuernich genauso den gewuenschten Effekt erzielt.Ab hier wird's meines Erachtens philosophisch, bzw. es geht dann halt um Programmierstil. Zum Vergleich hier nochmal meine komplette Version:
template <class It> inline bool REV_IT(It){ return false; } template <class It> inline bool REV_IT(std::reverse_iterator<It>) { return true; } template<typename InIt, typename K, typename S> InIt find_in(InIt BEG, InIt FIN, const S LAST_OPEN){ InIt RESULT = FIN; while(BEG != FIN){ if(strcmp((*BEG).second.c_str(), LAST_OPEN.c_str()) == 0){ RESULT = BEG; if(REV_IT(BEG)) break; } ++BEG; } return RESULT; }
21 zu 27 Zeilen, oder 485 zu 633 Bytes
Aber Spass beiseite, ich bin latuernich als Anfaenger auch an einer Bewertung der Programmierstils interessiert, hier in meinem Kaemmerchen die Dinge wertfrei nur so zu laufen zu bekommen kann's ja auch nicht sein, und Bytes bzw. Zeilen zu zaehlen scheint mir doch auch ein wenig zu lapidar.Also bitte, keine Scheu vor Bewertung...
solong
SF