web-dev-qa-db-fra.com

Quel est le besoin d'un modèle lambda introduit en C ++ 20 lorsque C ++ 14 a déjà un lambda générique?

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?

95
coder3101

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.

108
Quentin

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

30
Antoine Morrier

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 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 appelle directement 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 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

19
Hamza.S