Ich möchte eine überladene Funktion an den std::for_each()
Algorithmus übergeben. Beispielsweise,
class A {
void f(char c);
void f(int i);
void scan(const std::string& s) {
std::for_each(s.begin(), s.end(), f);
}
};
Ich würde erwarten, dass der Compiler nach f()
dem Iteratortyp aufgelöst wird. Anscheinend macht es das (GCC 4.1.2) nicht. Wie kann ich also angeben, welche f()
ich möchte?
Antworten:
Sie können
static_cast<>()
angeben, welchef
gemäß der vom Funktionszeigertyp implizierten Funktionssignatur verwendet werden sollen:Oder Sie können dies auch tun:
Wenn
f
es sich um eine Mitgliedsfunktion handelt, müssen Sie die in diesem Artikel von Dr. Dobb vorgestellte Lösung verwendenmem_fun
oder für Ihren Fall verwenden .quelle
f()
Mitglied einer Klassereinterpret_cast
. Meistens sehe ich dafür Abgüsse im C-Stil. Meine Regel ist nur, dass Casts auf Funktionszeiger gefährlich und unnötig sind (wie das zweite Code-Snippet zeigt, existiert eine implizite Konvertierung).std::for_each(s.begin(), s.end(), static_cast<void (A::*)(char)>(&A::f));
Lambdas zur Rettung! (Hinweis: C ++ 11 erforderlich)
Oder verwenden Sie decltype für den Lambda-Parameter:
Mit polymorphen Lambdas (C ++ 14):
Oder durch Entfernen der Überladung eindeutig (funktioniert nur für freie Funktionen):
quelle
mem_fn
undbind
, was übrigens auch C ++ 11 sind). Wenn wir wirklich pedantisch werden wollen, sind[&](char a){ return f(a); }
es 28 Zeichen undstatic_cast<void (A::*)(char)>(&f)
35 Zeichen.Warum funktioniert 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:Der Vorlagenabzug muss zum
UnaryFunction
Zeitpunkt des Aufrufs einen Typ auswählen . Hatf
aber keinen bestimmten Typ - es ist eine überladene Funktion, es gibt vielef
s mit jeweils unterschiedlichen Typen. Es gibt derzeit keine Möglichkeitfor_each
, den Prozess des Vorlagenabzugs zu unterstützen, indem angegeben wird, wasf
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, wasf
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 wollenf
einige Argumente anrufen . Auf die allgemeinste Art und Weise ist das: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):
und dann benutze es einfach:
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, obf
es sich um eine freie Funktion oder eine Mitgliedsfunktion handelt.quelle
Nicht um deine Frage zu beantworten, aber bin ich der einzige, der findet
sowohl einfacher als auch kürzer als die
for_each
von in silico in diesem Fall vorgeschlagene Alternative?quelle
Das Problem hier scheint nicht die Überlastungsauflösung zu sein, sondern die Ableitung von Vorlagenparametern . Während die hervorragende Antwort von @In silico ein mehrdeutiges Überlastungsproblem im Allgemeinen löst, scheint es die beste Lösung zu sein, wenn
std::for_each
(oder ähnliches) die Vorlagenparameter explizit angegeben werden :quelle
Wenn es Ihnen nichts ausmacht, C ++ 11 zu verwenden, finden Sie hier einen cleveren Helfer, der dem statischen Cast ähnlich (aber weniger hässlich als dieser) ist:
(Funktioniert für Elementfunktionen; es sollte offensichtlich sein, wie es für freistehende Funktionen geändert werden kann, und Sie sollten in der Lage sein, beide Versionen bereitzustellen, und der Compiler wählt die richtige für Sie aus.)
Vielen Dank an Miro Knejp für den Vorschlag: siehe auch https://groups.google.com/a/isocpp.org/d/msg/std-discussion/rLVGeGUXsK0/IGj9dKmSyx4J .
quelle
R
, wird es nicht abgeleitet. Das wird in dieser Antwort auch nicht erwähnt.R
, ich bieteArgs
.R
undT
werden abgeleitet. Es ist wahr, die Antwort könnte verbessert werden. (T
In meinem Beispiel gibt es jedoch keine , weil es kein Zeiger auf ein Mitglied ist, weil das nicht funktionieren würdestd::for_each
.)