Wir hatten eine Funktion, die ein nicht erfassendes Lambda in sich selbst verwendete, z.
void foo() {
auto bar = [](int a, int b){ return a + b; }
// code using bar(x,y) a bunch of times
}
Jetzt wurde die vom Lambda implementierte Funktionalität an anderer Stelle benötigt, sodass ich das Lambda aus foo()
dem Bereich global / Namespace herausheben werde. Ich kann es entweder als Lambda belassen, es zu einer Option zum Kopieren und Einfügen machen, oder es in eine richtige Funktion ändern:
auto bar = [](int a, int b){ return a + b; } // option 1
int bar(int a, int b){ return a + b; } // option 2
void foo() {
// code using bar(x,y) a bunch of times
}
Ändern es auf eine einwandfreie Funktion ist trivial, aber es machte mich wundern , wenn es aus irgendeinem Grund ist nicht , es zu verlassen als Lambda? Gibt es einen Grund, nicht überall nur Lambdas anstelle "regulärer" globaler Funktionen zu verwenden?
Antworten:
Es gibt einen sehr wichtigen Grund, keine globalen Lambdas zu verwenden: weil es nicht normal ist.
Die reguläre Funktionssyntax von C ++ gibt es seit den Tagen von C. Programmierer wissen seit Jahrzehnten, was diese Syntax bedeutet und wie sie funktioniert (obwohl zugegebenermaßen diese ganze Sache mit dem Zerfall von Funktion zu Zeiger manchmal sogar erfahrene Programmierer beißt). Wenn ein C ++ - Programmierer mit einem höheren Können als "absoluter Neuling" eine Funktionsdefinition sieht, weiß er, was er bekommt.
Ein globales Lambda ist ein ganz anderes Tier. Es hat ein anderes Verhalten als eine reguläre Funktion. Lambdas sind Objekte, Funktionen nicht. Sie haben einen Typ, aber dieser Typ unterscheidet sich vom Typ ihrer Funktion. Und so weiter.
Jetzt haben Sie die Messlatte für die Kommunikation mit anderen Programmierern höher gelegt. Ein C ++ - Programmierer muss Lambdas verstehen, wenn er verstehen will, was diese Funktion tut. Und ja, dies ist 2019, also sollte ein anständiger C ++ - Programmierer eine Idee haben, wie ein Lambda aussieht. Aber es ist immer noch eine höhere Messlatte.
Und selbst wenn sie es verstehen, wird die Frage im Kopf dieses Programmierers sein ... warum hat der Verfasser dieses Codes es so geschrieben? Und wenn Sie keine gute Antwort auf diese Frage haben (z. B. weil Sie das Überladen ausdrücklich verbieten möchten , wie in den Anpassungspunkten für Bereiche), sollten Sie den allgemeinen Mechanismus verwenden.
Ziehen Sie erwartete Lösungen gegebenenfalls neuen vor. Verwenden Sie die am wenigsten komplizierte Methode, um Ihren Standpunkt zu vermitteln.
quelle
Ich kann mir einige Gründe vorstellen, warum Sie globale Lambdas als Ersatz für reguläre Funktionen vermeiden möchten:
"Warum sollte ich keine Lambdas verwenden, um staatliche Funktoren (Klassen) zu ersetzen?"
quelle
std::integral_constant
...Nachdem ich gefragt hatte, überlegte ich mir einen Grund, dies nicht zu tun: Da es sich um Variablen handelt, sind sie anfällig für das Fiasko der statischen Initialisierungsreihenfolge ( https://isocpp.org/wiki/faq/ctors#static-init-order ), das dies könnte verursachen Fehler auf der ganzen Linie.
quelle
constexpr
Lambdas machen ... der eigentliche Punkt ist: Verwenden Sie einfach eine Funktion.Ein Problem mit einer bestimmten Komplexität erfordert eine Lösung mit mindestens derselben Komplexität. Wenn es jedoch eine weniger komplexe Lösung für dasselbe Problem gibt, gibt es wirklich keine Rechtfertigung für die Verwendung der komplexeren. Warum Komplexität einführen, die Sie nicht brauchen?
Zwischen einem Lambda und einer Funktion ist eine Funktion einfach die weniger komplexe Art von Entität der beiden. Sie müssen nicht rechtfertigen, kein Lambda zu verwenden. Sie müssen die Verwendung eines begründen. Ein Lambda-Ausdruck führt einen Schließungstyp ein, der ein unbenannter Klassentyp mit allen üblichen speziellen Elementfunktionen ist, einen Funktionsaufrufoperator und in diesem Fall einen impliziten Konvertierungsoperator in einen Funktionszeiger und erstellt ein Objekt dieses Typs. Das Kopieren und Initialisieren einer globalen Variablen aus einem Lambda-Ausdruck ist einfach viel mehr als nur das Definieren einer Funktion. Es definiert einen Klassentyp mit sechs implizit deklarierten Funktionen, definiert zwei weitere Operatorfunktionen und erstellt ein Objekt. Der Compiler muss noch viel mehr tun. Wenn Sie keine der Funktionen eines Lambda benötigen, verwenden Sie kein Lambda…
quelle
Lambdas sind anonyme Funktionen .
Wenn Sie ein benanntes Lambda verwenden, bedeutet dies, dass Sie grundsätzlich eine benannte anonyme Funktion verwenden. Um dieses Oxymoron zu vermeiden, können Sie auch eine Funktion verwenden.
quelle
Früher haben wir Funktionen anstelle von Global Functor verwendet, sodass die Kohärenz und das Prinzip des geringsten Erstaunens verletzt werden .
Die Hauptunterschiede sind:
quelle