2011-12-07 22 views
11

Dato un std::vector<std::unique_ptr<SomeType> >, è legale utilizzare remove_if su di esso? In altre parole, dato questo codice:Puoi usare `std :: remove_if` su un contenitore di` std :: unique_ptr`?

std::vector<std::unique_ptr<SomeType> > v; 
// fill v, all entries point to a valid instance of SomeType... 
v.erase(std::remove_if(v.begin(), v.end(), someCondition), v.end()); 

, sto garantita dopo la cancellazione che tutti i puntatori ancora in v sono validi. So che data l'implementazione intuitiva di std::remove_if, e date tutte le implementazioni che ho visto, saranno . Mi piacerebbe sapere se c'è qualcosa nello standard che lo garantisce; ovvero che std::remove_if non è autorizzato a copiare una qualsiasi delle voci valide senza ricopiare la copia nella sua posizione finale .

(io sono, ovviamente, supponendo che la condizione non copia Se la condizione ha una firma come:.

struct Condition 
{ 
    bool operator()(std::unique_ptr<SomeType> ptr) const; 
}; 

, poi, naturalmente, tutti i puntatori saranno validi dopo remove_if.)

+7

James Kanze fa domande - un fenomeno molto raro! – Nawaz

+3

'unique_ptr' non è copiabile, quindi se hai usato quel predicato il tuo codice non verrebbe compilato. – interjay

+1

Perché no? 'std :: unique' non è copiabile ma mobile. Può essere spostato alla fine del contenitore. –

risposta

2

25.3.8 nella N3290 parla le rimuovere merito funzione:

Richiede: Il tipo di * primo deve soddisfare i requisiti MoveAssignable (Tabella 22).

e

Nota: ciascun elemento nell'intervallo [ret, last), dove ret rappresenta l'restituita valore, ha uno stato fi cato valido ma non specificata, perché gli algoritmi possono eliminare elementi scambiando con o spostandosi da elementi che erano originariamente in quell'intervallo.

Ciò significa che dipende dall'operatore del predicato. Poiché il tuo predicato non crea una copia, gli elementi non verranno copiati.

+0

§25.3.8/1 è un vincolo sul tipo di destinazione, non sull'implementazione di 'remove' . §25.3.8/6 è quello che stavo cercando. Anche male è una nota e non normativa. Ma rende chiaro l'intento. Avrei dovuto leggere le note, e non solo il testo normativo, prima della pubblicazione . +1 in ogni caso, e lo considererò la risposta finale se nessuno trova qualcosa di più definito. –

+0

Ho il n3242. È stato aggiunto il §25.3.8/6 dopo? Il mio/6 discute su 'remove_copy [_if]'. – kennytm

+2

Credo che la nota non sia corretta. Per fortuna non è normativo. ;-) L'algoritmo non è autorizzato a scambiare elementi perché gli elementi non devono essere scambiati. L'algoritmo può utilizzare solo l'assegnazione del movimento. –

5

Proprio come erase() e resize(), remove_if() sarà mossa elementi (possibilmente tramite swap), per cui gli elementi contenitori non devono essere copiabile. Non c'è niente di speciale su unique_ptr, è solo un altro tipo di solo spostamento.

Come si fa notare, il predicato dovrebbe ovviamente prendere elementi per riferimento costante. Ancora una volta, proprio come per qualsiasi tipo di mobile.

+0

Dove è indicato nello standard? E, ancora più importante, dove è ha dichiarato che 'remove_if' non si sposta su un temporaneo, forse più tardi a lasciare il valore lì perché determina che non è necessario metterlo altrove? I contenitori e le funzioni membro sono stati riformulati per riflettere la semantica del movimento, ma non sono a conoscenza di eventuali modifiche nel linguaggio che descrive 'remove_if' a questo proposito. –

+1

@JamesKanze: §25.3.8/1? – kennytm

+0

@KennyTM: Beat me, grazie! –

Problemi correlati