Sempre use a variante que descreve melhor o que você pretende fazer. Isso é
Para cada elemento x
em vec
, faça bar.process(x)
.
Agora, vamos examinar os exemplos:
std::for_each(vec.begin(), vec.end(),
std::bind1st(std::mem_fun_ref(&Bar::process), bar));
Temos um for_each
lá também - yippeh . Temos o [begin; end)
alcance em que queremos operar.
Em princípio, o algoritmo era muito mais explícito e, portanto, preferível a qualquer implementação escrita à mão. Mas então ... Binders? Memfun? Basicamente C ++ interna de como se apossar de uma função de membro? Para a minha tarefa, eu não me importo com eles! Também não quero sofrer com essa sintaxe detalhada e assustadora.
Agora a outra possibilidade:
for (std::vector<Foo>::const_iterator it = vec.begin(); it != vec.end(); ++it)
{
bar.process(*it);
}
É verdade que esse é um padrão comum para reconhecer, mas ... criar iteradores, repetir, incrementar, desreferenciar. Essas também são todas as coisas de que não me importo para realizar minha tarefa.
É certo que parece melhor do que a primeira solução (pelo menos, o corpo do loop é flexível e bastante explícito), mas ainda assim, não é realmente tão bom assim. Usaremos este se não tivermos uma possibilidade melhor, mas talvez tenhamos ...
Uma maneira melhor?
Agora de volta para for_each
. Não seria ótimo dizer literalmente for_each
e ser flexível na operação a ser realizada também? Felizmente, desde C ++ 0x lambdas, estamos
for_each(v.begin(), v.end(), [&](const Foo& x) { bar.process(x); })
Agora que encontramos uma solução abstrata e genérica para muitas situações relacionadas, vale a pena notar que, neste caso em particular, existe um favorito nº 1 absoluto :
foreach(const Foo& x, vec) bar.process(x);
Realmente não pode ficar muito mais claro que isso. Felizmente, C ++ 0x get de uma sintaxe semelhante built-in !
map(bar.process, vec)
embora o mapa para efeitos colaterais seja desencorajado e as compreensões de lista / expressões geradoras sejam recomendadas sobre o mapa).