¿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_each
es 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 UnaryFunction
en el punto de la llamada. Pero f
no tiene un tipo específico: es una función sobrecargada, hay muchos f
s cada uno con diferentes tipos. No hay una forma actual de for_each
ayudar al proceso de deducción de plantillas al indicar cuál f
quiere, 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 f
que 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 f
a 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 f
mismo y simplemente hacer lo correcto. Esto funcionará independientemente de si f
es una función libre o una función miembro.