Por que isso não funciona?
Eu esperaria que o compilador resolvesse f()pelo tipo de iterador. Aparentemente, (gcc 4.1.2) não faz isso.
Seria ótimo se fosse esse o caso! No entanto, for_eaché um modelo de função, declarado como:
template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator, InputIterator, UnaryFunction );
A dedução de modelo precisa selecionar um tipo para UnaryFunctionno ponto da chamada. Mas fnão tem um tipo específico - é uma função sobrecarregada, existem muitos fs com tipos diferentes. Atualmente, não existe uma maneira de for_eachauxiliar o processo de dedução de modelo, indicando o que fele deseja; portanto, a dedução de modelo simplesmente falha. Para que a dedução do modelo seja bem-sucedida, você precisa trabalhar mais no site de chamada.
Solução genérica para corrigi-lo
Entrando aqui alguns anos e C ++ 14 depois. Em vez de usar a static_cast(que permitiria a dedução do modelo com êxito "corrigindo" o que fqueremos usar, mas requer que você execute manualmente a resolução de sobrecarga para "corrigir" a correta)), queremos fazer o compilador funcionar para nós. Queremos chamar falguns argumentos. Da maneira mais genérica possível, é isso:
[&](auto&&... args) -> decltype(auto) { return f(std::forward<decltype(args)>(args)...); }
É muito difícil digitar, mas esse tipo de problema surge irritantemente com frequência, para que possamos apenas envolvê-lo em uma macro (suspiro):
#define AS_LAMBDA(func) [&](auto&&... args) -> decltype(func(std::forward<decltype(args)>(args)...)) { return func(std::forward<decltype(args)>(args)...); }
e então apenas use:
void scan(const std::string& s) {
std::for_each(s.begin(), s.end(), AS_LAMBDA(f));
}
Isso fará exatamente o que você deseja que o compilador faça - execute a resolução de sobrecarga no fpróprio nome e faça a coisa certa. Isso funcionará independentemente de fser uma função livre ou uma função de membro.