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()
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 pour une fonction appropriée est trivial, mais cela m'a fait me demander s'il y avait 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"?
Réponses:
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 cette décomposition de fonction en 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 voulez explicitement 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.
la source
Je peux penser à quelques raisons pour lesquelles vous voudriez éviter les lambdas globaux comme remplacements directs pour les fonctions régulières:
"Pourquoi ne devrais-je pas utiliser des lambdas pour remplacer des foncteurs avec état (classes)?"
la source
std::integral_constant
pour cela ...Après avoir demandé, j'ai pensé à une raison pour ne pas le faire: comme il s'agit de variables, elles sont sujettes au fiasco de l'ordre d'initialisation statique ( https://isocpp.org/wiki/faq/ctors#static-init-order ), ce qui pourrait provoquer des bugs sur toute la ligne.
la source
constexpr
lambdas ... le vrai point est: utilisez simplement une fonction.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 bien plus que simplement définir une fonction. Il définit un type de classe avec six fonctions déclarées implicitement, 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…
la source
Les lambdas sont des 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.
la source
Nous avions l'habitude d'utiliser des fonctions au lieu de foncteur global, donc cela casse la cohérence et le principe du moindre étonnement .
Les principales différences sont:
la source