boost::ptr_vector -> Zeiger austauschen
-
Grüsse zusammen,
Entweder bin ich blind oder dies geht wirklich nicht und ich muss doch einen normalen
std::vectornehmen. Mein Problem ist eigentlich ganz einfach, ich möchte das folgende erreichen, allerdings gerne mitboost::ptr_vector:std::vector<Object*> vec; // Der Vektor, gefüllt. std::swap(vec[a], vec[b]); // Einfach die Zeiger tauschen.boost::ptr_vectorgibt mir die ganze Zeit immer nur irgendwelche Referenzen zurück. Ich komme nicht mehr an die Zeiger im Vektor ran, sobald ich sie reingesetzt habe.Kann mir da einer weiterhelfen? Oder muss ich doch auf den normalen Vektor ausweichen?
Grüssli
-
Wie wäre es mit boost::ptr_vector::replace, tut genau was du willst, musst allerdings zweimal aufrufen.
-
Dravere schrieb:
Ich komme nicht mehr an die Zeiger im Vektor ran, sobald ich sie reingesetzt habe.
Mit dem Adressoperator kommst du auch nicht weiter?
-
WTF?? schrieb:
Wie wäre es mit boost::ptr_vector::replace, tut genau was du willst, musst allerdings zweimal aufrufen.
Ah, wusste ich doch, dass ich etwas übersehen habe. Ist zwar nicht ganz perfekt, aber dürfte wohl für meine Zwecke reichen. Danke!
Nexus schrieb:
Dravere schrieb:
Ich komme nicht mehr an die Zeiger im Vektor ran, sobald ich sie reingesetzt habe.
Mit dem Adressoperator kommst du auch nicht weiter?
So komme ich an den Zeiger, kann ihn aber nicht überschreiben, bzw. durch einen anderen ersetzen.
Grüssli
-
Man kommt doch gar nicht an die internen Zeiger von ptr_vector, man erhält ja nur T&, also kann man maximal die Adresse von T rausfinden, aber nicht von dem Zeiger den ptr_vector auf T hält.
-
#include <boost/ptr_container/ptr_vector.hpp> int main() { boost::ptr_vector<int> intVec; int* first = new int(10); int* second = new int(20); std::cout << "1: " << first << std::endl; std::cout << "2: " << second << std::endl; intVec.push_back(second); intVec.insert(intVec.begin(), first); boost::ptr_vector<int>::iterator iter = intVec.begin(); boost::ptr_vector<int>::iterator next = iter + 1; // Swap ---> boost::ptr_vector<int>::auto_type temp = intVec.replace(iter, &*next); intVec.replace(next, temp.release()).release(); // ---> std::cout << "1: " << &intVec[0] << std::endl; std::cout << "2: " << &intVec[1] << std::endl; return 0; }Hat jemand noch eine bessere Idee? Irgendwie sieht das unheimlich hässlich aus. Es funktioniert allerdings. Naja, vielleicht nehm ich doch ein
std::vector<Object*>oder einstd::vector<boost::shared_ptr<Object*> >, mal schauen. Denke eher ersteres.Grüssli
-
Wie wäre es mit base?
... std::iter_swap(iter.base(),next.base()); ...
-
wo genau ist das problem?
nur weil ein swap etwas unschoen aussieht?naja, schoener gehts so:
swap(*iter.base(), *next.base());PS:
zu langsam
und noch dazu die haesslichere variante.verdammt

-
camper schrieb:
Wie wäre es mit base?
... std::iter_swap(iter.base(),next.base()); ...Perfekt, genau was ich gesucht habe! Vielen Dank!
@Shade Of Mine,
Auch wenn du zu langsam warst, dankeschön
Und swap ist nicht unschön. Swap ist geil ... einfach nur geil. Nur habe ich es einfach nicht rausgefunden, wie ich genau dies da oben durchführen kann. Diese
base()Funktion habe ich nirgends in der Dokumentation gefunden, um ehrlich zu sein, finde ich sie jetzt immer noch nicht und musste im Quellcode von Boost nachschauen, damit ich begriffen habe, was da geschieht.Grüssli
-
-
camper schrieb:
Da ist aber nichts zu finden, dass die Iteratoren eine
base()Methode haben. Nur das der Container eine solche Methode aufweist, welche einen VoidPtrContainer Referenz zurück gibt, welcher beiptr_vectoranscheinend einenstd::vector<void*, Allocator>ist.Allerdings muss ich zugeben, dass ich nicht einmal diese Methode gefunden hatte. Ich komme irgendwie mit dieser Dokumentation nicht zurecht von den pointer_container.
Grüssli
-
Dravere schrieb:
camper schrieb:
Da ist aber nichts zu finden, dass die Iteratoren eine
base()Methode haben. Nur das der Container eine solche Methode aufweist, welche einen VoidPtrContainer Referenz zurück gibt, welcher beiptr_vectoranscheinend einenstd::vector<void*, Allocator>ist.Allerdings muss ich zugeben, dass ich nicht einmal diese Methode gefunden hatte. Ich komme irgendwie mit dieser Dokumentation nicht zurecht von den pointer_container.
Grüssli
Die Dokumentation könnte mehr Querverweise gebrauchen, ansonsten finde ich sie recht aufgeräumt (d.h. für eine boost-Dokumentation...); jedenfalls habe ich die base-Geschichte auf Anhieb gefunden. Lies dir einfach noch einmal im Abschnitt "Semantics: typedefs" durch, was dort über iterator gesagt wird.
Trotz der Warnung denke ich, das die vorgeschlagene Methode sinnvoll ist, selbst wenn die Implementation irgendwann dahingehend geändert wird, dass intern Container aus T* statt Containern aus void* benutzt werden, wird sie noch funktionieren - ist aber erst dann typsicher, denn gegenwärtig kannst du auf diese Weise beliebige Zeigertypen vertauschen.
-
Dravere schrieb:
Allerdings muss ich zugeben, dass ich nicht einmal diese Methode gefunden hatte. Ich komme irgendwie mit dieser Dokumentation nicht zurecht von den pointer_container.
Die boost Doku ist fast immer Schrott. Man braucht ein gespuer dafuer um durchzublicken.
Ich hab mir zB gedacht: der iterator ist ja nur ein proxy und hat im hintergrund ja einen originalen iterator in den container. ergo muss es ne moeglichkeit geben an den ursprungsiterator ranzukommen.
also iterator deklariert und . geschrieben und mein intellisense gefragt was es so denkt. und es dachte base(). also mal sehen was base tut und tada - fertig.
aber bei komplexeren sachen kann man sich schon echt zum krueppel suchen

-
*Brille abnimmt und im Licht betrachtet* ... hmm vielleicht liegst daran

Muss die Stelle sicher 5 Mal überlesen haben.Note that:
iterator i = ...; i.base();returns an iterator that allows one to iterate over void* elements (this is very rarely needed and you should not use the functionality unless you know what you are doing).
Ich verzieh mich jetzt aus diesem Thread aus Schande

@Shade Of Mine,
Mein IntelliSense ist grad am streiken. Wieder so eine Sache mit der Byte-Gewerkschaft
Grüssli