البرمجة الوظيفية في لغة C++: الميزات الحديثة والأمثلة
البرمجة الوظيفية (FP) هي نموذج يتم فيه التعامل مع العمليات الحسابية على أنها تقييم للدوال الرياضية، مع تجنب تغيير الحالة والبيانات القابلة للتغيير. على الرغم من أن لغة C++ ترتبط تقليديًا بالبرمجة الكائنية والإجرائية، إلا أنه بدءًا من C++11 وخاصة في C++14/17/20، اكتسبت اللغة أدوات قوية للأسلوب الوظيفي. في هذه المقالة، سنقوم بتحليل المفاهيم الأساسية التي ستجعل كود C++ الخاص بك أكثر إيجازًا وأمانًا وتعبيرًا.
1. تعبيرات لامدا والإغلاقات
تعبيرات لامدا هي دوال مجهولة يمكن استخدامها مباشرة داخل الكود. لقد أصبحت أساس البرمجة الوظيفية في C++. تلتقط تعبيرات لامدا المتغيرات من بيئتها (الإغلاق) ويمكن تمريرها إلى خوارزميات مكتبة القوالب القياسية (STL).
بناء جملة تعبير لامدا
auto lambda = [capture](parameters) -> return_type { body };مثال: الفرز باستخدام لامدا
#include <iostream>#include <vector>#include <algorithm>
int main() { std::vector<int> nums = {5, 2, 8, 1, 9}; // الفرز بترتيب تنازلي 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;}الإغلاقات: الالتقاط بالقيمة والمرجع
#include <iostream>#include <vector>#include <algorithm>
int main() { int threshold = 5; std::vector<int> data = {1, 6, 3, 8, 2}; // الالتقاط بالقيمة [=] - نسخة من الحد auto count_greater = std::count_if(data.begin(), data.end(), [=](int x) { return x > threshold; }); // الالتقاط بالمرجع [&] - يمكن التعديل auto modify = [&](int &x) { if (x < threshold) x += threshold; }; std::for_each(data.begin(), data.end(), modify); std::cout << "العدد: " << count_greater << ""; // العدد: 2 for (int n : data) std::cout << n << " "; // 6 6 8 8 7 return 0;}2. الكائنات الدالية (Functors) و std::function
الكائنات الدالية هي كائنات فئة تقوم بتحميل عامل التشغيل operator(). يمكنها تخزين حالة والتصرف مثل الدوال. std::function هو غلاف متعدد الأشكال لتخزين أي كائنات قابلة للاستدعاء.
مثال على كائن دالي
#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: غلاف عالمي
#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}; // يمكن تمرير تعبيرات لامدا process(numbers, [](int n) { return n % 2 == 0; }); // 2 4 6 process(numbers, [](int n) { return n > 3; }); // 4 5 6 // وكذلك الكائنات الدالية struct GreaterThan { int limit; bool operator()(int n) const { return n > limit; } }; process(numbers, GreaterThan{4}); // 5 6 return 0;}3. خوارزميات مكتبة STL بالأسلوب الوظيفي
توفر مكتبة STL العديد من الخوارزميات التي تتزاوج بشكل مثالي مع تعبيرات لامدا والكائنات الدالية. بدلاً من الحلقات التكرارية، استخدم std::transf