2014-05-01 12 views
6

Ich habe eine std::vector<std::shared_ptr<Foo>> von denen ich möchte, dass erase-remove Elemente mit einigen Prädikaten übereinstimmen. Für die entfernten Objekte sollte eine Methode aufgerufen werden, die einen Status für die Verwendung an anderer Stelle setzt.Entfernen Sie Elemente aus dem Vektor, und mutieren Sie diejenigen, die entfernt werden

Gibt es einen Grund, ich sollte dies in der Prädikatfunktion nicht tun, wenn wahr zurückgegeben wird? Es fühlt sich ein wenig an, als würde man Bedenken mischen, aber die einzigen Alternativen, die mir einfallen, scheinen viel hässlicher.

+0

benannt Es wäre besser, die Alternativen zu fassen, sonst bist du gehen, um sie als Antworten. – djechlin

+0

So würde ich es aber tun, was soll ich sagen, ich bin faul. Es gibt keine Alternative, die Ihnen erlaubt, die 'algorithm'-Bibliothek zu benutzen, oder? In beiden Fällen verstößt man gegen eine Vorstellung von "perfekten" Programmierstandards. (Edit: anscheinend gibt es das, aber ich wäre immer noch versucht, es auf deine Art zu tun!) – Elliott

+0

Das ist die effizienteste Art, die ich mir vorstellen kann. – 101010

Antwort

7

Es gibt zwei Gründe, warum dies wahrscheinlich keine gute Idee ist.

Erstens sollten die meisten Standardbibliotheksalgorithmen Prädikate nicht verwenden, die die Elemente ändern, auf die sie wirken.

Zweitens, std::remove und std::remove_if nicht geben Sie eine gute Reihe von "entfernten" Elemente *. Sie können sich nur darauf verlassen, dass die ausgewählten Elemente beibehalten werden. Die "entfernten" Elemente könnten tatsächlich Kopien der "guten" Elemente sein. Und da Sie geteilte Zeiger speichern, könnten sie auf die gleichen Objekte wie die "guten" Elemente zeigen.

Eine Alternative wäre std::partition zu verwenden, dann über den entsprechenden Abschnitt der Trennwand iterieren, dann erase in einer Weise an die Lösch-remove Idiom ähnliche verwenden.

auto p = std::partition(v.begin, v.end(), pred); 
std::for_each(p, v.end(), call_method_functor); 
v.erase(p, v.end()); 

* Diese Algorithmen wahrscheinlich haben sollte keep und keep_if

+0

Das ist eine gute Lösung, aber ich verstehe diesen Teil nicht wirklich: "' std :: remove' ... gibt dir keinen guten Satz 'entfernter' Elemente ". Warum ist das wichtig, wenn Sie die einzige Funktion aufrufen, die Sie für das Objekt benötigen, bevor die Prädikatfunktion überhaupt zurückkehrt? – Elliott

+0

@Elliott - Ich habe Code geschrieben, der versucht, "entfernte" Elemente zu verwenden, und ich habe ziemlich schlecht gebrannt. Unter dem Strich sollten Sie die entfernten Elemente nicht verwenden, außer zum Löschen. Die Lösung ist genau das, was juanchopanza in seine Antwort "std :: partition" (oder "std :: stable_partition") geschrieben hat. – PaulMcKenzie

+1

Ich mag Ihre Idee der Verwendung von 'Partition', aber der Teil über' remove (_if) 'keine Garantien über die entfernten Elemente zu machen ist wahrscheinlich irrelevant, weil der OP angibt, er wird auf diese Objekte von anderswo arbeiten. – Praetorian