Perché non funziona?
Mi aspetto che il compilatore si risolva in f()
base al tipo di iteratore. Apparentemente, (gcc 4.1.2) non lo fa.
Sarebbe bello se fosse così! Tuttavia, for_each
è un modello di funzione, dichiarato come:
template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator, InputIterator, UnaryFunction );
La detrazione del modello deve selezionare un tipo per UnaryFunction
nel punto della chiamata. Ma f
non ha un tipo specifico - è una funzione sovraccarica, ce ne sono molti f
ciascuno con tipi diversi. Non esiste un modo attuale per for_each
aiutare il processo di detrazione del modello dichiarando ciò f
che desidera, quindi la detrazione del modello semplicemente fallisce. Affinché la deduzione del modello abbia esito positivo, è necessario svolgere più lavoro sul sito di chiamata.
Soluzione generica per risolverlo
Saltando qui qualche anno e C ++ 14 più tardi. Invece di usare un static_cast
(che consentirebbe alla deduzione del modello di avere successo "riparando" che f
vogliamo usare, ma richiede che tu faccia manualmente la risoluzione del sovraccarico per "riparare" quella corretta), vogliamo far funzionare il compilatore per noi. Vogliamo chiamare f
alcuni argomenti. Nel modo più generico possibile, questo è:
[&](auto&&... args) -> decltype(auto) { return f(std::forward<decltype(args)>(args)...); }
È molto da scrivere, ma questo tipo di problema si presenta fastidiosamente frequentemente, quindi possiamo semplicemente avvolgerlo in una macro (sospiro):
#define AS_LAMBDA(func) [&](auto&&... args) -> decltype(func(std::forward<decltype(args)>(args)...)) { return func(std::forward<decltype(args)>(args)...); }
e poi basta usarlo:
void scan(const std::string& s) {
std::for_each(s.begin(), s.end(), AS_LAMBDA(f));
}
Questo farà esattamente quello che vorresti fosse fatto dal compilatore: esegui la risoluzione del sovraccarico sul nome f
stesso e fai semplicemente la cosa giusta. f
Funzionerà indipendentemente dal fatto che sia una funzione libera o una funzione membro.