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 UnaryFunction
no ponto da chamada. Mas f
não tem um tipo específico - é uma função sobrecarregada, existem muitos f
s com tipos diferentes. Atualmente, não existe uma maneira de for_each
auxiliar o processo de dedução de modelo, indicando o que f
ele 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 f
queremos 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 f
alguns 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 f
próprio nome e faça a coisa certa. Isso funcionará independentemente de f
ser uma função livre ou uma função de membro.