Usa sempre la variante che descrive meglio ciò che intendi fare. Questo è
Per ogni elemento x
in vec
, do bar.process(x)
.
Ora esaminiamo gli esempi:
std::for_each(vec.begin(), vec.end(),
std::bind1st(std::mem_fun_ref(&Bar::process), bar));
Abbiamo anche un for_each
lì - yippeh . Abbiamo la [begin; end)
gamma su cui vogliamo operare.
In linea di principio, l'algoritmo era molto più esplicito e quindi preferibile rispetto a qualsiasi implementazione scritta a mano. Ma poi ... Raccoglitori? Memfun? Fondamentalmente C ++ interna su come ottenere una funzione membro? Per il mio compito, non mi importa di loro! Né voglio soffrire di questa sintassi dettagliata e inquietante.
Ora l'altra possibilità:
for (std::vector<Foo>::const_iterator it = vec.begin(); it != vec.end(); ++it)
{
bar.process(*it);
}
Certo, questo è un modello comune da riconoscere, ma ... creazione di iteratori, loop, incremento, dereferenziazione. Anche queste sono tutte cose che non mi interessano per svolgere il mio compito.
Certo, sembra meglio della prima soluzione (almeno, il corpo del loop è flessibile ed abbastanza esplicito), ma non è poi così eccezionale. Useremo questo se non avessimo possibilità migliori, ma forse abbiamo ...
Un modo migliore?
Ora torniamo a for_each
. Non sarebbe bello dire letteralmente for_each
ed essere flessibile anche nell'operazione che deve essere fatta? Fortunatamente, dal C ++ 0x lambdas, lo siamo
for_each(v.begin(), v.end(), [&](const Foo& x) { bar.process(x); })
Ora che abbiamo trovato una soluzione astratta e generica a molte situazioni correlate, vale la pena notare che in questo caso particolare, c'è un preferito in assoluto # 1 :
foreach(const Foo& x, vec) bar.process(x);
Non può essere molto più chiaro di così. Per fortuna, C ++ 0x get è una sintassi simile incorporata !
map(bar.process, vec)
sebbene la mappa per gli effetti collaterali sia scoraggiata e la comprensione dell'elenco / le espressioni del generatore sono raccomandate sulla mappa).