c ++ 14 a introduit des lambdas génériques qui ont permis d'écrire ce qui suit:
auto func = [](auto a, auto b){ return a + b; }; auto Foo = func(2, 5); auto Bar = func("hello", "world");
Il est très clair que cette func
lambda générique func
comme une fonction de fonction func
un modèle fonctionnerait.
Pourquoi le comité C ++ a-t-il décidé d'ajouter une syntaxe de modèle pour lamda générique?
4 Réponses :
Étant donné que vous pouvez utiliser des modèles lambdas en C ++ 20, vous pouvez restreindre vos types de manière plus simple qu'une expression SFINAE:
auto lambda = []<typename T>(std::vector<T> t){};
Ce lambda fonctionnera uniquement avec les types vectoriels.
Quel est le lien entre consteval
et la nouvelle syntaxe? C'est cool et tout, mais je ne comprends pas la pertinence.
C'est plus une information sur ce que C ++ 20 ajoute à l'expression lambda qu'une réponse à la question
La proposition qui a été acceptée dans C ++ 20 a une longue section de motivation, avec des exemples. La prémisse est la suivante:
Il y a quelques raisons principales pour lesquelles la syntaxe actuelle de définition des lambdas génériques est jugée insuffisante par l'auteur. L'essentiel est que certaines choses qui peuvent être faites facilement avec des modèles de fonction normaux nécessitent des sauts de cerceau importants avec des lambdas génériques, ou ne peuvent pas être faites du tout.L'auteur pense que les lambdas sont suffisamment précieuses pour que C ++ les supporte aussi bien que les modèles de fonctions normaux.
Voici quelques exemples.
Les lambdas génériques C ++ 14 sont un moyen très cool de générer un foncteur avec un operator ()
qui ressemble à ceci:
template <class T> auto operator()() const; // No deduction
Mais pas comme ça:
template <class T, std::size_t N> auto operator()(std::array<T, N> const &) const; // Only `std::array` please
Ni comme ça:
template <class T> auto operator()(T t1, T t2) const; // Same type please
Ni comme ça (bien que cela devienne un peu difficile à utiliser):
template <class T, class U> auto operator()(T t, U u) const;
Les lambdas C ++ 14 conviennent, mais C ++ 20 nous permet d'implémenter ces cas sans tracas.
Nice et concis. Juste en ajoutant ceci: Le premier (mêmes types) peut être résolu par (auto a, decltype(a) b)
en C ++ 14.
@SebastianMach presque. Avec cette solution, b
n'est pas déduit, et son argument sera implicitement converti au type de a
place.
La nouvelle «syntaxe de modèle familière» pour les lambdas introduite dans C ++ 20 rend les constructions telles que «
for_types
«for_range
viables et bien plus lisibles que les alternatives C ++ 17.(source: itération au moment de la compilation avec C ++ 20 lambdas )
Une autre chose intéressante qui peut être faite sur les lambdas génériques C ++ 14 et C ++ 17 est d'appeler directement
operator()
en passant explicitement un paramètre de modèle: C ++ 14 :auto l = []<typename T>(){ }; l.template operator()<int>();C ++ 20 (voir aussi l'explication de
<tparams>
sur cppreference ):auto l = [](auto){ }; l.template operator()<int>(0);L'exemple C ++ 14 ci-dessus est tout à fait inutile: il n'y a aucun moyen de faire référence au type fourni à l'
operator()
dans le corps du lambda sans donner un nom à l'argument et utiliserdecltype
. De plus, nous sommes obligés de passer un argument même si nous n'en avons peut-être pas besoin.L'exemple C ++ 20 montre comment T est facilement accessible dans le corps du lambda et qu'un lambda nul peut désormais être modélisé de manière arbitraire. Cela va être très utile pour l'implémentation des constructions de compilation mentionnées ci-dessus.
Que faire si vous devez utiliser un type de modèle différent de celui des arguments ou du type de retour? Et si c'est nécessaire à l'intérieur du corps?
On m'a dit que c'était un cas d'utilisation intéressante.
Voir ceci pour une comparaison des différentes versions lambda: modernescpp.com/index.php/more-powerful-lambdas-with-c-20