Lambda expressions

  • Partenaires

Utilisateurs qui regardent le poste (Total: 0, Members: 0, Invité: 0)

davydavekk

davydavekk

Level 5
Level 4
Level 3
Level 2
Level 1
23 Mai 2013
508
0
322
'merica
Ce tutoriel n'est pas destiné au débutants, mais plutôt a ceux qui ont déjà un peu d’expérience en C++.​

Les lambda ont été introduite dans le plus récent standard, le C++11, vérifiez bien que votre compilateur le supporte !

Headers nécessaires : <iostream> <vector> <algorithm>

Définition

Une lambda, c'est un objet que l'on peut appeler (et non, pas au tel :non:), parce quelles sont simples a déclarer, elles sont très souvent utiliser pour crée des petites fonctions a l’intérieur d'une fonction. On peut aussi les utiliser comme argument pour un algorithme. (exemples plus bas)


Création d'une lambda

Le prototype de base pour une lambda est le suivant :
PHP:
auto name = [capture list] (parameter list) -> return type {body};

  • Auto : J'utilise auto pour que le compilateur puisse déduire le type.
  • Name : Le nom de la lambda.
  • Capture list : Cette liste contient les variables locales de la fonction que la lambda va utiliser. /!\ Par valeur et non référence !
  • Parameter list : La liste des paramètres qu'on doit passer a la lambda ... exactement comme une fonction normale.
  • Return type : Type que la lambda retourne.
  • Body : Vraiment besoin d'expliquer ? :noel:

Voici un exemple d'une lambda qui retourne le nombre d'argument passes a la fonction Main ( int main(int nArgs,char* pArgs[] ) :
PHP:
auto getArgs = [nArgs]() -> int {return nArgs; };
//pour l’appeler :
std::cout << getArgs() << std::endl;

On peut aussi la déclarer comme ça :
PHP:
auto args = [nArgs]()  {return nArgs; };

Différentes options pour la capture list :
/!\ Les variables capturées par valeur ont la valeur qu'ils avaient au moment ou la lambda a été crée, et pas quand elle est exécutée ! (mauvais souvenirs avec LINQ en C#, je préfère prévenir ...)
  • [] : Vide, aucune variable locale utilisée.
  • [names] Capture par valeur, il faut ajouter un '&' devant le nom de la variable pour capturer par référence.
  • [&] Capture toute les variables par référence.
  • [=] Capture toute les variables par valeur.
  • [&,liste] Capture tout par référence sauf les variables qui sont dans la liste, elles seront capturée par valeur.
  • [=,liste] Capture tout par valeur sauf les variables qui sont dans la liste, elles seront capturée par référence.


Exemple avec des algorithmes

Disons qu'on a un std::vector, comme celui ci :
PHP:
std::vector<int> vec; 
	for (int i = 0; i != 10; i++)
		vec.push_back(i);

Maintenant on veut pouvoir afficher chaque élément sur notre console, ce qui vous vient en tête :
PHP:
// j'utilise un std::vector<int>::const_iterator vu qu'on ne modifie rien

for (auto it = vec.cbegin(); it != vec.cend(); it++)
		std::cout << *it << std::endl;

Mais il y a un moyen plus simple (IMO), utiliser l'algorithme std::for_each !

PHP:
std::for_each(vec.cbegin(), vec.cend(), [] (int val)
	{ 
		std::cout << val << std::endl; 
	});

Comment ça fonctionne, demandez vous ? En fait, std::foreach va appeler notre lambda pour chaque élément qui est dans le vector.

PHP:
template<class InputIterator, class Function>
  Function for_each(InputIterator first, InputIterator last, Function fn)
{
  while (first!=last) {
    fn (*first); // ICI
    ++first;
  }
  return fn;      // or, since C++11: return move(fn);
}
src :


Épilogue

Voila, ce tutoriel est termine, je sais que les exemples que j'ai utiliser ne sont pas terribles, mais il y a vraiment beaucoup de choses possibles avec ces lambdas ! J'ajouterais peut être une partie sur std::bind & std::placeholders plus tard.

En attendent si vous avez des questions n’hésitez pas a les poser ;)

Cordialement, Davy.