2014-05-01 1 views
6

Ho un erase-remove elementi che corrispondono a qualche predicato. Gli oggetti rimossi dovrebbero avere un metodo chiamato che imposta alcuni stati da usare altrove.Rimuovi elementi dal vettore e modifica quelli rimossi

C'è una ragione per cui non dovrei farlo nella funzione predicato quando viene restituito true? Sembra un po 'come mescolare le preoccupazioni, ma le uniche alternative che posso pensare sembrano molto più brutte.

+0

Sarebbe meglio per riassumere le alternative, altrimenti si sta andando ad ottenere loro le risposte. – djechlin

+0

Ecco come lo farei ma, cosa posso dire, sono pigro. Non c'è alternativa che ti permetta comunque di usare la libreria 'algorithm', giusto? Quindi, in entrambi i casi, stai violando la nozione di standard di programmazione "perfetti". (Modifica: a quanto pare c'è ma sarei ancora tentato di farlo a modo tuo!) – Elliott

+0

Questo è il modo più efficiente che riesco a pensare. – 101010

risposta

7

Ci sono due motivi per cui questa non è probabilmente una buona idea.

In primo luogo, la maggior parte degli algoritmi di libreria standard non deve utilizzare predicati per modificare gli elementi su cui agiscono.

Secondo, std::remove e std::remove_if non forniscono un buon set di elementi "rimossi" *. Puoi fare affidamento solo sugli elementi che sono selezionati per mantenere. Gli elementi "rimossi" potrebbero di fatto essere copie di quelli "buoni". E poiché stai memorizzando i puntatori condivisi, potrebbero puntare agli stessi oggetti degli elementi "buoni".

Un'alternativa sarebbe utilizzare std::partition, quindi scorrere la sezione pertinente della partizione, quindi utilizzare erase in un modo simile all'idioma di cancellazione-rimozione.

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

* Questi algoritmi dovrebbe probabilmente sono stati chiamati keep e keep_if

+0

Questa è una buona soluzione, ma non capisco questa parte: "' std :: remove' ... non ti dà una buona serie di elementi 'rimossi' ". Perché importa se stai chiamando l'unica funzione di cui hai bisogno sull'oggetto prima che la funzione di predicato ritorni? – Elliott

+0

@Elliott - Ho scritto codice che ha tentato di usare gli elementi "rimossi" e mi sono bruciato piuttosto male. La linea di fondo è che non si dovrebbero usare gli elementi rimossi, ad eccezione della cancellazione. La soluzione è esattamente ciò che juanchopanza ha inserito nella sua risposta, 'std :: partition' (o' std :: stable_partition'). – PaulMcKenzie

+1

Mi piace l'idea di usare 'partition', ma la parte relativa a' remove (_if) 'non dare garanzie sugli elementi rimossi è probabilmente irrilevante perché l'OP afferma che opererà su questi oggetti da altrove. – Praetorian