Assoziatives problem
-
als ergänzung
map<string, shared_ptr<myKlasse> > element;
element["AAA"].reset(new MyKlasse(100,100)); // Parameter übergabe an Konstruktor
element["CCC"].reset(new MyKlasse(100,200));
element["BBB"].reset(new MyKlasse(100,300));so habe ich es und es geht.
er solls beim begin() end() durchlauf auch in dieser reihenfolge.
(was momentan ja nicht so ist, da er die arrays sortiert)wenn ihr sagt das geht am besten mit vector ist, würd ich das gerne machen.
habe aber leider meine probs damit, deshalb wäre ich über bissle code über glücklich
-
@davie:
Wieso sollte man den Functor (ist das ein Functor?) von binary_function erben lassen?
-
Ich kenne kein assoc Array in welchem die Elemente in der Reihenfolge wie sie hinzugefügt
werden gespeichert werden, das würde den Zugriff extrem ausbremsen.
Das beste wäre für dich wolh ein vector< pair< String, int> >, wenn pair 2versch.
Werte aufnehmen darf.
Sonst musst du halt ne eigene Klasse schreiben, was ja aber nicht wirklich schwer ist
-
XguestX schrieb:
wäre zutiefst dankbar für professionelle hilfe *nein von keinem arzt*
Tu mal spitze Klammern zaehlen tun
-
SirLant:
Muss er nicht, davie hat die Möglichkeit bereits gepostet. bzw.struct foo : binary_function<string,string,bool> { bool operator () (const string &a, const string &b) const { return false; } };
oder true, k.A., dann sollte das doch funktionieren, oder?
Wenn er sonst nichts großartig zu sortieren hat, wird er es wohl in der Eintragungsreihenfolge lassen...MfG MAV
-
Mis2com schrieb:
oder true, k.A., dann sollte das doch funktionieren, oder?
davie schrieb:
einfach immer null [bzw. true, false oder einen anderen konstanten Wert] zurückgeben geht natürlich trotzdem nicht bzw bringt nicht das gewünschte ergebnis
-
ach fuck ey! hast recht Shade Of Mine, da fehlte nur nen ">"
#include <vector> #include <boost/shared_ptr.hpp> using namespace std; using boost::shared_ptr; class myKlasse { public: void SetInt(int x); // so daten etc ;) }; vector< pair<string, shared_ptr<myKlasse> > > element;
vorher:
map<string, shared_ptr<GUI_Element> > element;
element["AAA"].reset(new myKlasse(100,100));
element["AAA"]->SetInt(3);auf Azossiatives Array würd ich garnicht so bestehen.
aber wie mach ich das dann mit:
vector<shared_ptr<myKlasse> > element;
element.push_back(???);
element.push_back(new myKlasse(300,300)); // das geht ja nichtund wie rufe ich dann daraus die SetInt(3); auf?
oh man ich komme mir unter euch so dumm vor
würde mich freuen wenn ihr c++ gurus einem nichts das bissle mit sanfter hand nahe bringen könntet
-
@Mis2Com:
Das Ableiten von unary_function bzw. binary_function hat denn sinn, dass man standardisierte namen für die argument- und ergebnistypen hat, um sie zb zum Binden weiterverwenden zu können.
-
vielleicht hat wer auch noch ne ganz andere lösung
sagen wir die myKlasse ist zur darstellung eines buttons
mit hilfe des assoziativen arrays konnte ich den eintrag in der liste leicht ansprechen element["Button1"]->SetKoord(5,5); das ["Button1"] wurde mir auch helfen das ganze im code zu managen und gezielt anzusprechen.wenn ich das jetzt per vector machen soll, sehe ich momentan nicht wie ich gezielt die einzelnen Buttons ansprechen soll und vor allem so das ich die übersicht bewahre. per index sowas zu managen ist nicht übersichtlich, deshalb nahm ich den weg des assoziativen arrays.
-
XguestX schrieb:
auf Azossiatives Array würd ich garnicht so bestehen. aber wie mach ich das dann mit: vector<shared_ptr<myKlasse> > element; element.push_back(???); element.push_back(new myKlasse(300,300)); // das geht ja nicht
jetzt ganz ohne pair oder mit?
vector < pair<string, shared_ptr<X> > a; a.push_back (make_pair ("String", shared_ptr<X>(new X)); //bzw. vector < shared_ptr<X> > b; b.push_back (shared_ptr<X>(new X));
-
vector < pair<string, shared_ptr<X> > a;
a.push_back (make_pair ("String", shared_ptr<X>(new X));vector<pair<string, shared_ptr<X> > > vec; vec.push_back(make_pair ("String", shared_ptr<X>(new X(300,300))));
sorry aus dem error weerd ich nicht schlau
error C2536: 'std::pair<char [7],class boost::shared_ptr<class X> >::first' : Angabe einer expliziten Initialisierung fuer Felder nicht moeglichBei der Kompilierung der Member-Funktion '__thiscall std::pair<char [7],class boost::shared_ptr<class X> >::std::pair<char [7],class boost::shared_ptr<class X> >(const char (&)[7],const class boost::shared_ptr<class X> &)' der Klassenvorlage
und wie greife ich dann auf "String" zu?
-
?
probier malvector<pair<string, shared_ptr<X> > > vec; vec.push_back(make_pair (string("String"), shared_ptr<X>(new X(300,300))));
zugreifen auf die elemente geht dann so:
//am besten irgendwo ein typedef machen typedef vector <pair<string,shared_ptr<X> > > Assoc; //ist sonst umständlich, wenn man das jedesmal ausschreiben muss Assoc a; a.push_back (make_pair(string("foo"), shared_ptr<X>(new X(300,300)))); //... for (Assoc::iterator i = a.begin(); i != a.end(); ++i) { cout << i->first /*das ist der string*/; //unter i->second ist dann der shared_ptr }
-
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