Funktionale Programmierung in C++: Fortgeschrittene Techniken und Beispiele

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Funktionale Programmierung in C++: Fortgeschrittenes Niveau

\n\n

Funktionale Programmierung (FP) ist ein Paradigma, das Berechnungen als Auswertung mathematischer Funktionen betrachtet und veränderliche Zustände sowie Seiteneffekte vermeidet. Obwohl C++ traditionell mit objektorientierter und prozeduraler Programmierung assoziiert wird, haben moderne Standards (C++11 und neuer) leistungsstarke Werkzeuge für das Schreiben von funktionalem Code eingeführt. In diesem Artikel gehen wir über grundlegende Lambdas hinaus und betrachten fortgeschrittene Techniken: von Funktionskomposition bis zur Emulation von Monaden.

\n\n

1. Funktionskomposition und Pipelines

\n\n

Funktionskomposition ist der Prozess des Kombinierens von zwei oder mehr Funktionen, um eine neue Funktion zu erstellen. In C++ eignen sich hierfür Lambda-Ausdrücke und Templates.

\n\n
#include <iostream>\n#include <functional>\n#include <vector>\n#include <algorithm>\n\n// Template für die Komposition zweier Funktionen\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// Beispiel zur Verwendung\nint main() {\n    auto addTwo = [](int x) { return x + 2; };\n    auto multiplyByThree = [](int x) { return x * 3; };\n\n    // Komposition: zuerst multiplyByThree, dann addTwo\n    auto composed = compose(addTwo, multiplyByThree);\n\n    std::cout << composed(5) << std::endl; // (5*3) + 2 = 17\n\n    // Pipeline-Verarbeitung (pipe) mit 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

Pipelines mit std::views (C++20) ermöglichen das Erstellen von Transformationsketten ohne die Erzeugung von Zwischencontainern, was ein klassischer funktionaler Ansatz ist.

\n\n

2. Currying und partielle Anwendung

\n\n

Currying ist die Transformation einer Funktion, die mehrere Argumente akzeptiert, in eine Sequenz von Funktionen, die jeweils ein Argument akzeptieren. Die partielle Anwendung fixiert einen Teil der Argumente.

\n\n
#include <iostream>\n#include <functional>\n\n// Curry-Funktion zur Addition\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// Partielle Anwendung mit std::bind\nint multiply(int a, int b, int c) {\n    return a * b * c;\n}\n\nint main() {\n    // Verwendung von Currying\n    auto add5 = curriedAdd(5);\n    auto add5And3 = add5(3);\n    std::cout << add5And3(2) << std::endl; // 10\n\n    // Partielle Anwendung über 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    // Partielle Anwendung über Lambda (idiomatischer in 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

Currying ist besonders nützlich bei der Arbeit mit Funktionen höherer Ordnung wie std::transform oder std::accumulate, da es ermöglicht, spezialisierte Versionen von Funktionen "on the fly" zu erstellen.

\n\n

3. Funktoren, Applikative und Emulation von Monaden

\n\n

In Haskell sind Monaden ein mächtiges Muster für die Arbeit mit Seiteneffekten. In C++ können wir sie mit Hilfe von Klassentemplates emulieren. Betrachten wir eine einfache Monade Maybe (analog zu std::optional), jedoch mit monadischen Operationen.

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

Blogs

Buchempfehlungen