Intro :
Nous allons implémenter un système de delegates comme celles existantes en C#.
Tout d’abord qu’est-ce qu’une fonction anonyme (appelée aussi fonction lambda) ?
Une fonction anonyme est tout simplement une fonction qui n’a pas de nom et qui peut être définie à la volée.
Depuis la dernière version C++11 on peut définir des fonctions anonymes.
Dans ce tutoriel nous allons apprendre à utiliser deux objets de la STL que sont : std::function et std::bind.
A noter que je me suis servi de ces delegates pour implémenter le système d’Events de cet article.
Prérequis :
– Savoir un peu lire du C++.
– Disposer d’un compilateur compatible C++11.
Explications :
Une fonction anonyme peut être définie ainsi :
#include <functional>
// Définition d'une fonction anonyme
auto UneFonction = [](int i) -> double { return 2 * i; };
// Appel de cette fonction anonyme
double d = UneFonction(1);
On place des crochets au début pour annoncer une fonction lambda.
Entre parenthèses on indique les paramètres.
Le type indiqué juste après la flèche indique le type de retour de la fonction.
L’objet std::function peut être affecté par une simple fonction ou par une fonction anonyme :
#include <functional>
// Une fonction toute simple
int my_func(int a, int b) { return a + b; }
// On peut affecter cette précédente fonction à un objet std::function
std::function<int (int, int)> f = my_func;
// On peut affecter directement une fonction anonyme
std::function<int (int)> UneFonction = [](int i) -> double { return 2 * i; };
On met entre crochets : le type de retour et le type des paramètres entre parenthèses.
L’objet std::bind permet de lier un ou plusieurs paramètres de manière préétablis à un objet std::function :
#include <functional>
#include <iostream>
// Une fonction standard
void Afficher(std::string& texte)
{
std::cout << "TEXTE: " << texte << std::endl;
}
// On peut lier à cette précédente fonction un paramètre prédéfini
std::function <void ()> f = std::bind(Afficher, "Du texte !!");
f(); // Affiche "TEXTE : Du texte !!"
On peut faire spécifier ultérieurement un paramètre avec std::placeholder::_* :
#include <functional>
#include <iostream>
int multiply(int a, int b)
{
return a * b;
}
int main()
{
auto f = std::bind(multiply, 5, std::placeholders::_1);
for (int i = 0; i < 10; i++)
{
std::cout << "5 * " << i << " = " << f(i) << std::endl;
}
return 0;
}
On peut stocker des std::function dans un std::vector :
#include <functional>
#include <vector>
std::vector<std::function<double (int)>> fs;
auto UneFonction = [](int i) -> double { return 2 * i; };
fs.push_back(UneFonction);
// On peut invoquer ces fonctions par une boucle automatique
for (auto& f : fs)
{
f();
}
Résumé :
Nous avons appris comment définir des fonctions delegates comme celle disponibles en C#.
Références :
– http://fr.cppreference.com/w/cpp/utility/functional/function
– http://fr.cppreference.com/w/cpp/utility/functional/bind
– http://oopscenities.net/2012/02/24/c11-stdfunction-and-stdbind/
– http://openclassrooms.com/courses/introduction-a-c-2011-c-0x

