Lambda expressions

    Publicités

Users Who Are Viewing This Thread (Total: 0, Members: 0, Guests: 0)

May 23, 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 :Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!


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