Bags in C++
-
Hallo an alle,
mir stellt sich die Frage ob es in C++ sog. "Bags" gibt. Ein Beutel ist eine unstrukturierte Menge von Objekten, welche auch Duplikate enthalten kann.
In Smalltalk gibt es sowas.
Bags und SetsWenn es denn sowas in C++ gibt, ist es möglich ein Bag anzulegen ohne sich auf den Datentyp festzulegen?
In Smalltalk wird (s. Link oben) ein Bag definiert und dieser kann beliebige Objekttypen beinhalten. Also int, char etc. Betonung liegt auf Objekt.
Das einzige was ich hierzu gefunden habe ist dies.
Es kommt dem Bag zwar nahe ist aber:
1. Auf ein Datentyp festgelegt (im Beispiel ist das int)
2. Hat eine Feste größe (100)
3. Ist durch das verwenden von Arrays sortiert.Hoffe ihr könnt mir helfen.
Schöne Grüße
-
std::vector<boost::any>
-
Vielen Dank.
Den Rest macht google.
-
std::multisetwäre hier erwähnenswert.
-
Edit: Hier stand dummes Zeug
-
multiset geht nur mit einem typ.
und std::multisetboost::any geht nicht, da std::multiset ne strict-weak-ordering braucht, und die bekommt man mit boost::any wohl eher nicht hin.
std::list oder std::deque wäre noch eine option.
p.S.: @Croatiancow: ich glaube übrigens nicht dass du mit der "Lösung" glücklich werden wirst. Anders gesagt: ich würde vector<any> nicht "empfehlen". Es ist nur das einzige was ich kenne, was dem nahe kommt nach was du gefragt hast

-
hustbaer schrieb:
und std::multisetboost::any geht nicht, da std::multiset ne strict-weak-ordering braucht, und die bekommt man mit boost::any wohl eher nicht hin.
Nach dem Wohlordnungssatz kann jede Menge geordnet werden. Da any nichts anderes als ein void* verpackt ist, kann die Speicheradresse als Ordnungsgrundlage dienen. Dann wuerde auch ein std::set ausreichen.
Wenn es denn sowas in C++ gibt, ist es möglich ein Bag anzulegen ohne sich auf den Datentyp festzulegen?
Es ist moeglich, aber du musst es dir selbst bauen.
-
knivil schrieb:
hustbaer schrieb:
und std::multisetboost::any geht nicht, da std::multiset ne strict-weak-ordering braucht, und die bekommt man mit boost::any wohl eher nicht hin.
Nach dem Wohlordnungssatz kann jede Menge geordnet werden.
Es geht sowieso nur um endliche Mengen.
knivil schrieb:
Da any nichts anderes als ein void* verpackt ist, kann die Speicheradresse als Ordnungsgrundlage dienen. Dann wuerde auch ein std::set ausreichen.
Kaum, denn dann gibt es keine äquivalenten Kopien - eine Grundvoraussetzung für Containerelemente.
-
Kaum, denn dann gibt es keine äquivalenten Kopien - eine Grundvoraussetzung für Containerelemente.
Grundvoraussetzung? Kannst du das mal bitte etwas ausfueheren. Ich habe es so schon einmal verwendet, aber ich brauchte keine Kopien.
-
Habe es mal mit der "boost::any" Lösung versucht.
Ich habe nun das Problem das ich zwar per pushback was reinwerfe, es aber mit einer einfachen for schleife nicht auslesen kann, da ich eine Eigene Klasse verwende. In allen Tutorials wird mit einfachen int's gearbeitet.
Hier mein Beispiel:
int main() { Money euro(5,'E'); vector<boost::any> bag; bag.clear(); bag.push_back(euro); }Wenn ich jetzt das Objekt euro ausgeben möchte müsste ich auf meine
getValue(void)vom Objekt zugreifen. Da komme ich aber irgendwie nicht hin.
Einbag[0].getValue();klappt nicht.
Hat jemand ne Idee?
Hier der Header:
class Money { private: char currency; int value; public: Money(); Money(int val,char curr); void set(int val, char curr); int getValue(void); };
-
knivil schrieb:
hustbaer schrieb:
und std::multisetboost::any geht nicht, da std::multiset ne strict-weak-ordering braucht, und die bekommt man mit boost::any wohl eher nicht hin.
Nach dem Wohlordnungssatz kann jede Menge geordnet werden. Da any nichts anderes als ein void* verpackt ist, kann die Speicheradresse als Ordnungsgrundlage dienen. Dann wuerde auch ein std::set ausreichen.
Mit Standard C++ kannst du void* nicht ordnen, da Zeigervergleich undefiniert ist, wenn die Zeiger nicht aus dem selben Array kommen.
-
Croatiancow schrieb:
Wenn ich jetzt das Objekt euro ausgeben möchte müsste ich auf meine
getValue(void)vom Objekt zugreifen. Da komme ich aber irgendwie nicht hin.
Einbag[0].getValue();klappt nicht.
Hat jemand ne Idee?
Du musst das boost::any wieder in ein Money-Objekt casten, das geht IIRC so:
any_cast<Money>(bag[0]).getValue();
-
Ach ja: um vorher zu ueberpruefen ob das Objekt ueberhaupt ein Money-Objekt ist:
if (bag[0].type() == typeid(Money)) // bag[0] ist vom typ Moneywenn bag[0] naemlich kein Money-Objekt waer, wuerde sonst eine bad_any_cast - exception geworfen.
-
Vielen Dank!
Jetzt klappts. Hier kurz die Lösung für die Nachwelt:
int main() { Money euro(5,'E'); Money tmp1; vector<boost::any> bag; bag.clear(); bag.push_back(euro); cout<<boost::any_cast<Money>(bag[0]).getValue(); }Mann kann jetzt auch die Ausgabe in eine Schleife bauen, um alles auszulesen (wie beim Array).
Vielen Dank für deine / eure Hilfe.
Gruß und frohe Weihnachten :xmas1:
-
Auch wenn das Problem gelöst ist würde mich folgendes zu dem Thema interessieren:
Nehmen wir an ich hätte das Bedürfnis zu Prüfen ob in einem Vector ein bestimmtes Objekt drin ist.
Also sowas wie eine includes(Objekt) Methode.
So wie ich das sehe gibt es keine Methode in Vector welche das macht. Also würde ich eine eigene schreiben.Tja und hier komm ich nicht weiter. Vector ist ja aus der STL und da soll man nicht direkt davon ableiten.
Wie krieg ich das aber hin eine eigene Klasse zu schreiben welche mir eingentlich nur ein Vector + meine eigenen Methoden zur verfügung stellt?
Verzeiht mir meine Unwissenheit.
Gruß
-
Croatiancow schrieb:
So wie ich das sehe gibt es keine Methode in Vector welche das macht. Also würde ich eine eigene schreiben.
Nein!
Croatiancow schrieb:
Tja und hier komm ich nicht weiter. Vector ist ja aus der STL und da soll man nicht direkt davon ableiten.
Ja, weil die Vererbung im Normalfall auch nicht nötig ist.
Croatiancow schrieb:
Wie krieg ich das aber hin eine eigene Klasse zu schreiben welche mir eingentlich nur ein Vector + meine eigenen Methoden zur verfügung stellt?
Gar nicht.
Ich habe das Gefühl, du denkst zu fest an andere Programmiersprachen, wo deine Vorgehensweise möglicherweise üblich ist. In C++ gibt es allerdings freie Funktionen, welche unabhängig von Klassen arbeiten können. Folglich brauchst du die Funktionen nicht als Member zu implementieren, sondern -- wenn überhaupt -- global.
Eine Möglichkeit zum Suchen gibt es in der STL jedoch bereits: Siehe dazu den Algorithmus
std::find()auf www.cplusplus.com.Croatiancow schrieb:
Verzeiht mir meine Unwissenheit.
Du brauchst dich doch nicht rechtzufertigen, wir helfen gerne.

-
Nein ich habe in meinem Leben weder Java noch C# oder sonstwas gemacht. Nur C++
Es ging mir darum ein Bag zu erstellen und den dann mit Methoden zu erweitern. Einfach mal was global zu definieren ist leider nicht OO und somit für mich uninteressant. Ich darf nur mit Objekten arbeiten.
Also ist ein
Bag.includes(Objekt)so nicht möglich. Klar das ich mit
p = find(vectorObject.begin(), vectorObject.end(), Objekt);suchen kann.
Schön wäre ein
Bag.find(vectorObject.begin(), vectorObject.end(), Objekt);Gruß
-
Croatiancow schrieb:
Einfach mal was global zu definieren ist leider nicht OO
Du meinst, es entspricht nicht deiner Definition von Objektorientierung.

Croatiancow schrieb:
Ich darf nur mit Objekten arbeiten.
Okay. Dann schreibe dir eine Bag-Klasse, die aber nicht von
std::vectorerbt, sondern ihn als Membervariable enthält (Aggregation). Somit brauchst du auch nicht alle Methoden anzubieten, sondern kannst das Interface auf die beschränken, die du brauchst. Entsprechend bietest du einefind()-,contains()oderincludes()-Memberfunktion an, welche die gewünschte Funktionalität bietet. Intern verwendet siestd::find().
-
Genau das mache ich jetzt

Ist mir beim Brainstorming mit nem Kumpel gekommen

Ich Danke euch vielmals! Ihr seid echt Klasse!
-
das heißt bug