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 :
|
1 2 3 4 5 6 7 |
#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 :
|
1 2 3 4 5 6 7 8 9 10 |
#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 :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#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::_* :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#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 :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#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


