Assoziatives problem
-
ja nen durchlauf würd ich schon hinbekommen, mir gehts aber um das explizite ansprechen eines elementes.
map<string, shared_ptr<X> > element; element["AAA"].reset(new X(100,100)); element["CCC"].reset(new X(100,200)); // viel code text element["AAA"]->SetInt(3);
da konnte ich jedes element (klasse) was ich in map ablegte, per assoziatives array leicht ansprechen und deren funktionen nutzen.
genau das brauch ich ....
-
du verzichtest mit vector auf die sortierung; vector ist jetzt die reihenfolge so, wie du die elemente hinzufügst. also mit vector und ohne element-raussuchen geht es so:
vec[0].second->foo(); //der string ist in vec[0].first;
andernfalls musst du nach elementen suchen, oder eine map verwenden.
-
ShadeOfMine:
Aber wieso klappt sowas nicht?davie:
Irgendwie vesteh ich immernoch nicht, was das bringt.
-
hast du's ausprobiert?
ein tip: eine map hat keine zwei gleichen elemente.noch zu den unary/binary_functions:
siehe zbtemplate <class binary> class binder2nd : public unary_function <typename binary::first_argument_type //hier typename binary::result_type> { //hier binary b; typename binary::second_argument_type arg2; //hier public: binder2nd (const binary &x, const typename binary::second_argument_type &v) : b(x), arg2(v) {} //hier result_type operator () (const argument_type &x) const { return op(x,b); } //hier - überall };
da verwendet man es, damit später sowas möglich ist:
list<int>::const_iterator i = find_if (li.begin(), li.end(), bind2nd(less<int>(),7));
d.h. binder2nd verlässt sich zb darauf, eine binary_function zu bekommen.
-
oha, äh, da versteh ich ja echt garnichts von. oO
Meint ihr, dass kann ich mir alleine mit der MSDN erklären?
-
binder2nd und bind2nd sind auch teile der standardbibliothek.
hast du nicht eh das Buch die C++ Programiersprache?
ansonsten empfehle ich dir Thinking in C++ 2nd Edition volume 1 & 2:
http://mindview.erde3.net/ gibt's hier zum download
oder zb http://www.google.at/search?q=cache:8jtJBOIJ9zcJ:web.onetel.net.uk/~anthony_w/cplusplus/functional.pdf+c%2B%2B+functors+binary_function&hl=de&ie=UTF-8
oder das meiste von http://www.google.at/search?hl=de&ie=UTF-8&oe=UTF-8&q=c%2B%2B+functor+binder2nd&btnG=Suche&meta=
-
Also, hier mal was ich net versteh ('ne ganze Menge):
template <class binary> // binary ist einfach nur irgendwas, das als Templateargument übergeben wird, irgendein Typ? class binder2nd : public unary_function <typename binary::first_argument_type //hier typename binary::result_type> { //hier // ja... hier... der binder2nd erbt von einer unären Funktion, aber was ist binary fürn Teil? Und was bedeutet first_argument_type und result_type? Oder sind das nur Namen, die einfach so eingesetzt worden sind? binary b; // wos des? typename binary::second_argument_type arg2; //hier // typename? Ich verstehe nicht... was macht typename? ich kenne nur typedef :( public: binder2nd (const binary &x, const typename binary::second_argument_type &v) : b(x), arg2(v) {} //hier // der ctor hat dieses binary-Teil und dann ein Argument vom Type binary::second_argument_type... warum muss da typename davor stehen? result_type operator () (const argument_type &x) const { return op(x,b); } //hier - überall // was ist op? };
Das ist ein unärer Functor... oder binär? Das ist irgendwie gemischt
list<int>::const_iterator i = find_if (li.begin(), li.end(), bind2nd(less<int>(),7));
Äh, und das?
Ich würde es so interpretiren:
Lege einen iterator auf das Element, das von li.begin() bis li.end() in der Suche als Erstes für bind2nd(less<int>(),7)() gefunden wurde...
Äh
less<int>() macht hier was?
und die 7?
Naja, also... ich bin mir da wirklich noch sehr unsicher, wie kommt man auf solche krassen Teile? oOEDIT:
Buch geladen.
Bringt das mir wirklich was?MfG MAV
-
binary_function sieht so aus:
template <class T, class U, class R> struct binary_function { typedef T first_argument_type; typedef U second_argument_type; typedef R result_type; };
das heißt, wenn ich von binary_function<string,string,int> erbe, dann hab ich automatisch string als first_- und second_argument_type und int als result_type, d.h. in meinem function muss ich eine funktion à la
int operator () (const string &a, const string &b) const;
definieren, denn ich sage ja: ich bin eine binary_function mit string als first_argument, string als second_argument und int als result_type.
operator () verwandelt also deine struktur/klasse in ein funktionsähnliches objekt, einen funktor.std::less ist zum beispiel eine binary_function, die laut standard so definiert ist:
template <class T> less : public binary_function <T, T, bool> { bool operator () (const T &a, const T &b) const; //gibt a < b zurück };
das ist ein sogenanntes prädikat, ein functor (oder eine funktion) mit rückgabetyp bool.
ein binder verbindet jetzt eines der zwei argumente mit einem bestimmten wert, binder2nd das 2. und binder1st das 1.
std::find_if ist eine funktion, die so aussieht:
template <class Iterator, class Predicate> Iterator find_if (Iterator anf, Iterator end, Predicate p);
find_if liefert einen iterator auf das erste element, dass das predicate erfüllt.
das predicate hier muss eine unary_function sein, die in der Lage ist, ein Iterator::value_type als argument zu nehmen.ein beispiel
bool einfaches_predicate (const string &foo) { return foo == "foo"; } void fun (list<string> &li) { list<string>::iterator i = find_if (li.begin(), li.end(), einfaches_predicate); }
der iterator i zeigt jetzt auf das erste element in der liste, dass das prädikat erfüllt (in dem fall das erste element, das == "foo" ist.
die standardlib definiert einige prädikate vor, die dann auch ziemlich einfach zu benutzen sind
//ein beispiel: equals //zuerst ein selbstgeschriebenes einstelliges prädikat template <class T> struct equals : public unary_function<T,bool>{ T t; equals (const T &x) : t(x) {} bool operator () (const T &x) const { return t == x; } }; //das verwende ich jetzt so, wie oben "einfaches_predicate" void fun (list<string> &li) { list<string>::iterator i = find_if (li.begin(), li.end(), equals<string>("foo")); }
das ist schon etwas generischer. find_if läuft also alle elemente von li.begin bis li.end durch, übergibt sie dem prädikat (das hat dafür ja eigens den operator () überladen) und sobald es eine übereinstimmung findet, wird der iterator auf ebendieses element zurückgeliefert.
die standardbibliothek bietet auch ein equal_to an, allerdings ein zweistelliges.
template <class T> struct equal_to : public binary_function<T,T,bool> { //ein prädikat bool operator () (const T &a, const T &b) const { a == b; } };
hier bedient man sich eben eines Binders, um ein Argument an einen ganz bestimmten wert zu hängen.
bind2nd (equal_to<string>(), "foo")
bind2nd ist eine funktion, die einen binder2nd zurückliefert. binder2nd ist wie gesagt ein unäres predicate und damit arbeitet ja find_if.
also, um einen iterator auf erste element aus einer liste von strings zu finden, dessen inhalt "bar" ist, machen wir folgendes (und ersparen uns dadurch das schreiben eines eigenen predicates, wie equals)void fun (list<string> &li) { list<string>::iterator i = find_if (li.begin(), li.end(), bind2nd(equal_to<string>(), "bar")); }
was ein Funktor ist, solltest du aber eigentlich schon wissen
-
ja, das buch bring etwas. empfehle dir dringend, es zu lesen und auch dich allgemein über templates zu informieren (auch typename ist wichtig)
-
typename kenne ich nur als Pseudonym für class innerhalb einer Template-Arguments.
Aber gut, solange man es runterladen kann und nicht kaufen muss, lese ich es.Ich bin jetzt etwas besser aufgeklärt, danke, hab jett alles verstanden.
Ich war mir mit dem Funktor-Begriff nicht ganz sicher, bin ich jetzt aber eher.MfG MAV