C++: ميزات C++17/20 الجديدة
آخر تحديث: 2026-08-26
في الدرس 47، تعلمنا عن برمجة القوالب الفوقية.
الآن، سنتعلم عن ميزات C++17 وC++20 الجديدة.
هذه الميزات الجديدة تجعل C++ أكثر إيجازًا وأمانًا وقوة.
1. ميزات C++17 الجديدة
(1) 1.1 الربط المهيكل
الميزة: فك ملائم من tuple وpair وstruct.
مثال: الربط المهيكل (الصعوبة ⭐)
▶ مثال 2: مثال على الكود (الصعوبة ⭐)
#include <iostream>
#include <tuple>
int main() {
std::tuple<int, std::string, double> t = {1, "Hello", 3.14};
// C++17: الربط المهيكل
auto [id, name, score] = t;
std::cout << "ID: " << id << std::endl;
std::cout << "Name: " << name << std::endl;
std::cout << "Score: " << score << std::endl;
return 0;
}
الخرج:
ID: 1
Name: Hello
Score: 3.14
(2) 1.2 if constexpr
الميزة: if وقت التجميع، تجميع كود بشكل انتقائي بناءً على الشروط.
مثال: if constexpr (الصعوبة ⭐⭐)
#include <iostream>
#include <type_traits>
template<typename T>
auto process(T value) {
if constexpr (std::is_integral_v<T>) {
return value * 2; // عدد صحيح: ضاعفه
} else {
return value; // غير ذلك: أعد كما هو
}
}
int main() {
std::cout << process(10) << std::endl; // 20
std::cout << process(3.14) << std::endl; // 3.14
return 0;
}
(3) 1.3 تعابير الطي
الميزة: تبسيط القوالب المتغيرة.
مثال: تعبير الطي (الصعوبة ⭐⭐)
#include <iostream>
template<typename... Args>
void print(Args... args) {
(std::cout << ... << args) << std::endl; // تعبير طي
}
int main() {
print(1, 2, 3, 4, 5); // الخرج: 12345
return 0;
}
(4) 1.4 ميزات C++17 الأخرى
| الميزة | الوصف |
|---|---|
std::optional |
قيمة قد تكون فارغة |
std::variant |
اتحاد آمن الأنواع |
std::any |
أي نوع |
std::string_view |
عرض سلسلة (نسخ صفرية) |
| استنتاج معاملات أصناف القوالب | لا حاجة لكتابة pair<int, int> بعد الآن |
2. ميزات C++20 الجديدة
(1) 2.1 المفاهيم (Concepts)
الميزة: تقييد معاملات القالب لرسائل خطأ أكثر وضوحًا.
مثال: تقييد القوالب بالمفاهيم (الصعوبة ⭐⭐⭐)
#include <iostream>
#include <concepts>
// تقييد T ليكون نوعًا صحيحًا
template<typename T>
requires std::integral<T>
T doubleValue(T x) {
return x * 2;
}
int main() {
std::cout << doubleValue(10) << std::endl; // 20
// std::cout << doubleValue(3.14) << std::endl; // ❌ خطأ تجميع (واضح)
return 0;
}
(2) 2.2 مكتبة النطاقات
الميزة: طريقة أكثر إيجازًا لاستدعاء خوارزميات STL.
مثال: استخدام النطاقات (الصعوبة ⭐⭐)
#include <iostream>
#include <ranges>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
// C++20: نطاقات
auto result = v | std::views::filter([](int x) { return x % 2 == 0; })
| std::views::transform([](int x) { return x * 10; });
for (int x : result) {
std::cout << x << " "; // الخرج: 20 40
}
std::cout << std::endl;
return 0;
}
(3) 2.3 الكوروتينات
الميزة: دعم الكوروتينات (دوال يمكن إيقافها/استئنافها).
مثال: كوروتين بسيط (الصعوبة ⭐⭐⭐⭐)
#include <iostream>
#include <coroutine>
// الكوروتينات في C++20 معقدة؛ يتم حذف التنفيذ المحدد هنا
// المفهوم: الكوروتينات يمكنها إيقاف التنفيذ واستئنافه لاحقًا
int main() {
// مثال على كوروتين C++20 (مبسط)
std::cout << "C++20 Coroutines" << std::endl;
return 0;
}
(4) 2.4 ميزات C++20 الأخرى
| الميزة | الوصف |
|---|---|
| الوحدات | تحل محل ملفات الرأس، تجميع أسرع |
| الكوروتينات | البرمجة غير المتزامنة |
| مكتبة التواريخ (امتدادات chrono) | معالجة أفضل للتاريخ/الوقت |
| مكتبة التنسيق (format) | تنسيق بأسلوب Python |
| عامل المركبة الفضائية (<=>) | مقارنة ثلاثية |
3. اختيار المعيار
(1) 3.1 أي معيار يجب أن تستخدم؟
| المعيار | التوصية |
|---|---|
| C++11 | الحد الأدنى من المعيار، يجب استخدامه |
| C++14 | تحسينات طفيفة، موصى به |
| C++17 | ميزات عملية كثيرة، موصى به بشدة |
| C++20 | أحدث الميزات، استخدم بحذر (دعم المترجم قد يكون غير مكتمل) |
4. تمرين: إعادة هيكلة الكود بـ C++17
▶ مثال 1: تبسيط الكود بالربط المهيكل (الصعوبة ⭐⭐)
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<int, std::string> students = {{1, "Zhang San"}, {2, "Li Si"}};
// C++17: الربط المهيكل لاجتياز map
for (const auto& [id, name] : students) {
std::cout << id << ": " << name << std::endl;
}
return 0;
}
الخرج:
1: Zhang San
2: Li Si
▶ مثال 3: استنتاج النوع auto (الصعوبة ⭐)
#include <iostream>
#include <vector>
int main() {
auto x = 10; // int
auto y = 3.14; // double
auto name = "Hello"; // const char*
std::vector<int> nums = {1, 2, 3, 4, 5};
auto it = nums.begin(); // vector<int>::iterator
std::cout << "x = " << x << std::endl;
std::cout << "y = " << y << std::endl;
std::cout << "name = " << name << std::endl;
return 0;
}
الخرج:
x = 10
y = 3.14
name = Hello
الخرج المتوقع:
x = 10
y = 3.14
name = Hello
❓ أسئلة شائعة
bash g++ -std=c++17 main.cpp g++ -std=c++20 main.cpp 📖 ملخص
| المعيار | الميزات الرئيسية |
|---|---|
| C++17 | الربط المهيكل، if constexpr، تعابير الطي |
| C++20 | المفاهيم، النطاقات، الكوروتينات، الوحدات |
📝 تمارين
-
أساسي (الصعوبة ⭐): أعد كتابة مقطع كود C++ قديم (بأنواع صريحة، for تقليدي، NULL) باستخدام auto وfor المدعوم بنطاق وnullptr.
-
متوسط (الصعوبة ⭐⭐): استخدم الربط المهيكل (C++17) لفك قيمة إرجاع pair أو tuple، وقارنها بالطريقة التقليدية .first/.second.
-
متقدم (الصعوبة ⭐⭐⭐): استخدم if constexpr (C++17) لتنفيذ تفرع وقت التجميع — اكتب قالب دالة يطبق منطق معالجة مختلف للأنواع الصحيحة والأنواع العائمة.
- C++11: auto/nullptr/range-for/lambda/المؤشرات الذكية
- C++14: لامدا عامة/make_unique
- C++17: الربط المهيكل/if constexpr/string_view/filesystem
- C++20: الوحدات/الكوروتينات/المفاهيم/النطاقات
- تستخدم هذه الدورة C++17، موازنة بين الميزات الجديدة والتوافق
الدرس التالي: تحسين الأداء (#49)