100
votes

Quel est le besoin du modèle lambda introduit dans C ++ 20 alors que C ++ 14 a déjà lambda générique?

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?


3 commentaires

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


4 Réponses :


33
votes

É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.


2 commentaires

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



24
votes

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.


0 commentaires

119
votes

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.


2 commentaires

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.



21
votes

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 utiliser 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 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.


0 commentaires