Funktionale Programmierung in C++: Moderne Möglichkeiten und Beispiele
Funktionale Programmierung (FP) ist ein Paradigma, bei dem Berechnungen als Auswertung mathematischer Funktionen betrachtet werden, die Zustandsänderungen und veränderliche Daten vermeiden. Obwohl C++ traditionell mit objektorientierter und prozeduraler Programmierung assoziiert wird, hat die Sprache seit C++11 und insbesondere in C++14/17/20 leistungsstarke Werkzeuge für den funktionalen Stil erhalten. In diesem Artikel werden wir die wichtigsten Konzepte behandeln, die Ihren C++-Code prägnanter, sicherer und ausdrucksstärker machen.
1. Lambda-Ausdrücke und Closures
Lambda-Ausdrücke sind anonyme Funktionen, die direkt an Ort und Stelle verwendet werden können. Sie bilden die Grundlage der funktionalen Programmierung in C++. Lambdas erfassen Variablen aus der Umgebung (Closure) und können an STL-Algorithmen übergeben werden.
Syntax eines Lambda-Ausdrucks
auto lambda = [capture](parameters) -> return_type { body };Beispiel: Sortieren mit Lambda
#include <iostream>#include <vector>#include <algorithm>
int main() { std::vector<int> nums = {5, 2, 8, 1, 9}; // Absteigend sortieren std::sort(nums.begin(), nums.end(), [](int a, int b) { return a > b; }); for (int n : nums) std::cout << n << " "; // 9 8 5 2 1 return 0;}Closures: Erfassen per Wert und Referenz
#include <iostream>#include <vector>#include <algorithm>
int main() { int threshold = 5; std::vector<int> data = {1, 6, 3, 8, 2}; // Erfassen per Wert [=] - Kopie von threshold auto count_greater = std::count_if(data.begin(), data.end(), [=](int x) { return x > threshold; }); // Erfassen per Referenz [&] - kann geändert werden auto modify = [&](int &x) { if (x < threshold) x += threshold; }; std::for_each(data.begin(), data.end(), modify); std::cout << "Count: " << count_greater << ""; // Count: 2 for (int n : data) std::cout << n << " "; // 6 6 8 8 7 return 0;}2. Funktoren und std::function
Funktoren sind Klassenobjekte, die den Operator operator() überladen. Sie können einen Zustand speichern und sich wie Funktionen verhalten. std::function ist ein polymorpher Wrapper zum Speichern beliebiger aufrufbarer Objekte.
Beispiel eines Funktors
#include <iostream>
class Adder {private: int base;public: Adder(int b) : base(b) {} int operator()(int x) const { return base + x; }};
int main() { Adder add5(5); std::cout << add5(10) << ""; // 15 std::cout << add5(20) << ""; // 25 return 0;}std::function: Universeller Wrapper
#include <iostream>#include <functional>#include <vector>
void process(const std::vector<int>& data, std::function<bool(int)> predicate) { for (int x : data) { if (predicate(x)) std::cout << x << " "; } std::cout << "";}
int main() { std::vector<int> numbers = {1, 2, 3, 4, 5, 6}; // Lambdas können übergeben werden process(numbers, [](int n) { return n % 2 == 0; }); // 2 4 6 process(numbers, [](int n) { return n > 3; }); // 4 5 6 // Und Funktoren struct GreaterThan { int limit; bool operator()(int n) const { return n > limit; } }; process(numbers, GreaterThan{4}); // 5 6 return 0;}3. STL-Algorithmen im funktionalen Stil
Die STL-Bibliothek bietet zahlreiche Algorithmen, die sich perfekt mit Lambdas und Funktoren kombinieren lassen. Verwenden Sie anstelle von Schleifen std::transf