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 ce lambda générique func
fonctionne exactement comme une fonction de modèle func
fonctionnerait.
Pourquoi le comité C++ a-t-il décidé d'ajouter une syntaxe de modèle pour le lamda générique?
Les lambdas génériques C++ 14 sont un moyen très cool de générer un foncteur avec une operator ()
qui ressemble à ceci:
template <class T, class U>
auto operator()(T t, U u) const;
Mais pas comme ça:
template <class T>
auto operator()(T t1, T t2) const; // Same type please
Ni comme ça:
template <class T, std::size_t N>
auto operator()(std::array<T, N> const &) const; // Only `std::array` please
Ni comme ça (bien que cela devienne un peu difficile à utiliser):
template <class T>
auto operator()() const; // No deduction
Les lambdas C++ 14 vont bien, mais C++ 20 nous permet d'implémenter ces cas sans tracas.
Étant donné que vous pouvez utiliser des lambdas basés sur des modèles en C++ 20, vous pouvez restreindre vos types d'une manière plus simple qu'une expression SFINAE:
auto lambda = []<typename T>(std::vector<T> t){};
Cette lambda ne fonctionnera qu'avec les types de vecteurs.
Le proposition qui a été accepté en C++ 20 a une longue section de motivation, avec des exemples. La prémisse est la suivante:
Il y a quelques raisons clés pour lesquelles la syntaxe actuelle pour définir les 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 un saut de cerceau important à faire avec des lambdas génériques, ou ne peuvent pas être faites du tout. L'auteur pense que les lambdas sont suffisamment valables pour que C++ les supporte aussi bien que les modèles de fonctions normales.
Voici quelques exemples.
La nouvelle "syntaxe de modèle familière" pour les lambdas introduite dans C++ 20 rend les constructions telles que
for_types
Etfor_range
Viables et bien plus lisibles par rapport aux 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 appelle directement operator()
en passant explicitement un paramètre de modèle:
auto l = [](auto){ };
l.template operator()<int>(0);
auto l = []<typename T>(){ };
l.template operator()<int>();
L'exemple C++ 14 ci-dessus est tout à fait inutile: il n'y a aucun moyen de faire référence au type fourni à operator()
dans le corps du lambda sans donner un nom à l'argument et en utilisant decltype
. 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 maintenant être arbitrairement modelé. Cela va être très utile pour la mise en œuvre des constructions de compilation susmentionnées