Warum funktioniert es nicht?
Ich würde erwarten, dass der Compiler nach f()
dem Iteratortyp aufgelöst wird. Anscheinend macht es (gcc 4.1.2) es nicht.
Es wäre großartig, wenn das der Fall wäre! Es handelt sich jedoch for_each
um eine Funktionsvorlage, die wie folgt deklariert ist:
template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator, InputIterator, UnaryFunction );
Der Vorlagenabzug muss zum UnaryFunction
Zeitpunkt des Aufrufs einen Typ auswählen . Hat f
aber keinen bestimmten Typ - es ist eine überladene Funktion, es gibt viele f
s mit jeweils unterschiedlichen Typen. Es gibt derzeit keine Möglichkeit for_each
, den Prozess des Vorlagenabzugs zu unterstützen, indem angegeben wird, was f
gewünscht wird. Daher schlägt der Vorlagenabzug einfach fehl. Damit der Vorlagenabzug erfolgreich ist, müssen Sie mehr Arbeit auf der Anrufseite leisten.
Generische Lösung zur Behebung
Ein paar Jahre hier und später C ++ 14. Anstatt eine zu verwenden static_cast
(die den Abzug von Vorlagen durch "Fixieren" erfolgreich machen würde, was f
wir verwenden möchten, aber Sie müssen die Überladungsauflösung manuell durchführen, um die richtige zu "reparieren"), möchten wir, dass der Compiler für uns funktioniert. Wir wollen f
einige Argumente anrufen . Auf die allgemeinste Art und Weise ist das:
[&](auto&&... args) -> decltype(auto) { return f(std::forward<decltype(args)>(args)...); }
Das ist eine Menge zu tippen, aber diese Art von Problem tritt ärgerlich häufig auf, so dass wir das einfach in ein Makro einwickeln können (Seufzer):
#define AS_LAMBDA(func) [&](auto&&... args) -> decltype(func(std::forward<decltype(args)>(args)...)) { return func(std::forward<decltype(args)>(args)...); }
und dann benutze es einfach:
void scan(const std::string& s) {
std::for_each(s.begin(), s.end(), AS_LAMBDA(f));
}
Dies macht genau das, was Sie sich vom Compiler gewünscht haben - führen Sie eine Überladungsauflösung für den Namen f
selbst durch und tun Sie einfach das Richtige. Dies funktioniert unabhängig davon, ob f
es sich um eine freie Funktion oder eine Mitgliedsfunktion handelt.