Nous avions une fonction qui utilisait une lambda interne non capturante, par exemple:
void foo() {
auto bar = [](int a, int b){ return a + b; }
// code using bar(x,y) a bunch of times
}
Maintenant, la fonctionnalité implémentée par le lambda est devenue nécessaire ailleurs, donc je vais sortir le lambda de foo()
dans la portée globale/namespace. Je peux soit le laisser comme lambda, ce qui en fait une option copier-coller, soit le changer pour une fonction appropriée:
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
}
Le changer en une fonction appropriée est trivial, mais cela m'a fait me demander s'il y avait une raison pas de le laisser comme lambda? Y a-t-il une raison de ne pas utiliser les lambdas partout au lieu des fonctions globales "normales"?
Il y a une raison très importante de ne pas utiliser de lambdas globaux: parce que ce n'est pas normal.
La syntaxe de fonction régulière de C++ existe depuis l'époque de C. Les programmeurs savent depuis des décennies ce que signifie cette syntaxe et comment ils fonctionnent (bien qu'il soit vrai que toute cette fonction de décomposition de la fonction vers le pointeur mord parfois même les programmeurs chevronnés). Si un programmeur C++ de n'importe quel niveau de compétence au-delà du "débutant absolu" voit une définition de fonction, il sait ce qu'il obtient.
Un lambda global est une bête complètement différente. Il a un comportement différent d'une fonction régulière. Les lambdas sont des objets, contrairement aux fonctions. Ils ont un type, mais ce type est distinct du type de leur fonction. Et ainsi de suite.
Alors maintenant, vous avez élevé la barre en communiquant avec d'autres programmeurs. Un programmeur C++ doit comprendre les lambdas s'il veut comprendre ce que fait cette fonction. Et oui, nous sommes en 2019, donc un programmeur C++ décent devrait avoir une idée de ce à quoi ressemble un lambda. Mais c'est toujours une barre plus élevée.
Et même s'ils le comprennent, la question dans l'esprit de ce programmeur sera ... pourquoi l'auteur de ce code l'a-t-il écrit de cette façon? Et si vous n'avez pas une bonne réponse à cette question (par exemple, parce que vous explicitement voulez pour interdire la surcharge, comme dans les points de personnalisation des plages), alors vous devez utiliser le mécanisme commun.
Préférez les solutions attendues aux nouvelles, le cas échéant. Utilisez la méthode la moins compliquée pour faire passer votre message.
Je peux penser à quelques raisons pour lesquelles vous voudriez éviter les lambdas globaux comme remplacements directs pour les fonctions régulières:
Après avoir demandé, j'ai pensé à une raison pour ne pas le faire: comme ce sont des variables, elles sont sujettes à Fiasco d'ordre d'initialisation statique ( https : //isocpp.org/wiki/faq/ctors#static-init-order ), ce qui pourrait provoquer des bugs sur toute la ligne.
Y a-t-il une raison de ne pas utiliser les lambdas partout au lieu des fonctions globales "normales"?
Un problème d'un certain niveau de complexité nécessite une solution au moins de la même complexité. Mais s'il existe une solution moins complexe pour le même problème, alors il n'y a vraiment aucune justification pour utiliser le plus complexe. Pourquoi introduire une complexité dont vous n'avez pas besoin?
Entre un lambda et une fonction, une fonction est simplement le type d'entité le moins complexe des deux. Vous n'avez pas à justifier de ne pas utiliser de lambda. Vous devez justifier d'en utiliser un. Une expression lambda introduit un type de fermeture, qui est un type de classe sans nom avec toutes les fonctions membres spéciales habituelles, un opérateur d'appel de fonction et, dans ce cas, un opérateur de conversion implicite vers le pointeur de fonction, et crée un objet de ce type. L'initialisation de la copie d'une variable globale à partir d'une expression lambda fait simplement beaucoup plus que la simple définition d'une fonction. Il définit un type de classe avec six fonctions implicitement déclarées, définit deux autres fonctions d'opérateur et crée un objet. Le compilateur doit faire beaucoup plus. Si vous n'avez besoin d'aucune des fonctionnalités d'un lambda, alors n'utilisez pas de lambda…
Les lambdas sont fonctions anonymes .
Si vous utilisez un lambda nommé, cela signifie que vous utilisez essentiellement une fonction anonyme nommée. Pour éviter cet oxymore, vous pourriez aussi bien utiliser une fonction.
s'il y a une raison de ne pas le laisser comme lambda? Y a-t-il une raison de ne pas utiliser les lambdas partout au lieu des fonctions globales "normales"?
Nous avions l'habitude d'utiliser des fonctions au lieu du foncteur global, donc cela casse la cohérence et le Principe du moindre étonnement.
Les principales différences sont: