Programmation fonctionnelle en C++ : techniques avancées et exemples

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Programmation fonctionnelle en C++ : niveau avancé

\n\n

La programmation fonctionnelle (PF) est un paradigme qui considère les calculs comme l'évaluation de fonctions mathématiques et évite les états modifiables et les effets secondaires. Bien que le C++ soit traditionnellement associé à la programmation orientée objet et procédurale, les normes modernes (C++11 et ultérieures) ont introduit des outils puissants pour écrire du code fonctionnel. Dans cet article, nous irons au-delà des lambdas de base et examinerons des techniques avancées : de la composition de fonctions à l'émulation de monades.

\n\n

1. Composition de fonctions et pipelines

\n\n

La composition de fonctions est le processus de combinaison de deux ou plusieurs fonctions pour en créer une nouvelle. En C++, il est pratique d'utiliser des expressions lambda et des templates pour cela.

\n\n
#include <iostream>\n#include <functional>\n#include <vector>\n#include <algorithm>\n\n// Template pour la composition de deux fonctions\ntemplate<typename F, typename G>\nauto compose(F f, G g) {\n    return [f, g](auto x) {\n        return f(g(x));\n    };\n}\n\n// Exemple d'utilisation\nint main() {\n    auto addTwo = [](int x) { return x + 2; };\n    auto multiplyByThree = [](int x) { return x * 3; };\n\n    // Composition : d'abord multiplyByThree, puis addTwo\n    auto composed = compose(addTwo, multiplyByThree);\n\n    std::cout << composed(5) << std::endl; // (5*3) + 2 = 17\n\n    // Traitement en pipeline (pipe) avec std::ranges (C++20)\n    std::vector<int> numbers = {1, 2, 3, 4, 5};\n    auto result = numbers\n        | std::views::filter([](int n) { return n % 2 == 0; })\n        | std::views::transform([](int n) { return n * n; });\n\n    for (int n : result) {\n        std::cout << n << " "; // 4 16\n    }\n    return 0;\n}\n
\n\n

Les pipelines avec std::views (C++20) permettent de construire des chaînes de transformations sans créer de conteneurs intermédiaires, ce qui est une approche fonctionnelle classique.

\n\n

2. Curryfication (Currying) et application partielle

\n\n

La curryfication est la transformation d'une fonction prenant plusieurs arguments en une séquence de fonctions, chacune prenant un seul argument. L'application partielle fixe une partie des arguments.

\n\n
#include <iostream>\n#include <functional>\n\n// Fonction d'addition curryfiée\nauto curriedAdd = [](int a) {\n    return [a](int b) {\n        return [a, b](int c) {\n            return a + b + c;\n        };\n    };\n};\n\n// Application partielle avec std::bind\nint multiply(int a, int b, int c) {\n    return a * b * c;\n}\n\nint main() {\n    // Utilisation de la curryfication\n    auto add5 = curriedAdd(5);\n    auto add5And3 = add5(3);\n    std::cout << add5And3(2) << std::endl; // 10\n\n    // Application partielle via std::bind\n    using namespace std::placeholders;\n    auto multiplyBy2 = std::bind(multiply, _1, _2, 2);\n    std::cout << multiplyBy2(3, 4) << std::endl; // 3*4*2 = 24\n\n    // Application partielle via lambda (plus idiomatique en C++14+)\n    auto multiplyBy3 = [](int a, int b) { return multiply(a, b, 3); };\n    std::cout << multiplyBy3(5, 6) << std::endl; // 5*6*3 = 90\n\n    return 0;\n}\n
\n\n

La curryfication est particulièrement utile lors du travail avec des fonctions d'ordre supérieur, telles que std::transform ou std::accumulate, permettant de créer des versions spécialisées de fonctions "à la volée".

\n\n

3. Foncteurs, applicatifs et émulation de monades

\n\n

En Haskell, les monades sont un puissant modèle pour gérer les effets secondaires. En C++, nous pouvons les émuler à l'aide de templates de classes. Considérons une monade simple Maybe (analogue à std::optional), mais avec des opérations monadiques.

\n\n
#include <iostream>\n#include <functional>\n#include <optional>\n\n// Monade Maybe (wrapper autour de std::optional)\ntemplate<typename T>\nclass Maybe {\n    s                

Blogs

Book Recommendations