¿Por qué no funciona?
Esperaría que el compilador se resuelva f()por el tipo de iterador. Aparentemente, (gcc 4.1.2) no lo hace.
¡Sería genial si ese fuera el caso! Sin embargo, for_eaches una plantilla de función, declarada como:
template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator, InputIterator, UnaryFunction );
La deducción de plantilla debe seleccionar un tipo UnaryFunctionen el punto de la llamada. Pero fno tiene un tipo específico: es una función sobrecargada, hay muchos fs cada uno con diferentes tipos. No hay una forma actual de for_eachayudar al proceso de deducción de plantillas al indicar cuál fquiere, por lo que la deducción de plantillas simplemente falla. Para que la deducción de la plantilla sea exitosa, debe trabajar más en el sitio de la llamada.
Solución genérica para arreglarlo
Saltando aquí unos años y C ++ 14 más tarde. En lugar de usar un static_cast(que permitiría que la deducción de plantillas tenga éxito al "arreglar" lo fque queremos usar, pero requiere que usted haga manualmente la resolución de sobrecarga para "arreglar" la correcta), queremos que el compilador funcione para nosotros. Queremos recurrir fa algunos argumentos. De la manera más genérica posible, eso es:
[&](auto&&... args) -> decltype(auto) { return f(std::forward<decltype(args)>(args)...); }
Eso es mucho para escribir, pero este tipo de problema surge de manera molesta con frecuencia, por lo que podemos envolverlo en una macro (suspiro):
#define AS_LAMBDA(func) [&](auto&&... args) -> decltype(func(std::forward<decltype(args)>(args)...)) { return func(std::forward<decltype(args)>(args)...); }
y luego solo utilízalo:
void scan(const std::string& s) {
std::for_each(s.begin(), s.end(), AS_LAMBDA(f));
}
Esto hará exactamente lo que desearía que hiciera el compilador: realizar una resolución de sobrecarga en el nombre fmismo y simplemente hacer lo correcto. Esto funcionará independientemente de si fes una función libre o una función miembro.