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

99

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 funcfonctionne exactement comme une fonction basée sur un modèle fonctionnerait func.

Pourquoi le comité C ++ a-t-il décidé d'ajouter une syntaxe de modèle pour le lamda générique?

codeur3101
la source
5
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?
Un mec programmeur du
On m'a dit que c'était un cas d'utilisation intéressante.
Max Langhof
Voir ceci pour une comparaison des différentes versions lambda: modernescpp.com/index.php/more-powerful-lambdas-with-c-20
schoetbi

Réponses:

115

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, 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 sont bien, mais C ++ 20 nous permet d'implémenter ces cas sans tracas.

Quentin
la source
2
Nice et concis. Juste en ajoutant ceci: Le premier (les mêmes types) peut être résolu (auto a, decltype(a) b)en C ++ 14.
Sebastian Mach
13
@SebastianMach presque. Avec cette solution bn'est pas déduite, et son argument sera implicitement converti au type de a.
Quentin
32

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

Antoine Morrier
la source
8
Quel est le constevallien avec la nouvelle syntaxe? C'est cool et tout, mais je ne comprends pas la pertinence.
StoryTeller - Unslander Monica
C'est plus une information sur ce que le C ++ 20 ajoute à l'expression lambda qu'une réponse à la question
Antoine Morrier
24

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 à faire 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 ainsi que les modèles de fonctions normaux.

Voici quelques exemples.

Conteur - Unslander Monica
la source
21

La nouvelle «syntaxe de modèle familière» pour les lambdas introduite dans C ++ 20 rend les constructions telles que  for_types et  for_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 est l'appel direct  operator() en passant explicitement un paramètre de modèle:

C ++ 14:

   auto l = [](auto){ };
   l.template operator()<int>(0);

C ++ 20:

  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 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 modelé de manière arbitraire. Cela va être très utile pour l'implémentation des constructions de compilation susmentionnées

Hamza.S
la source