أنماط enable_if
قيّد القوالب بالطريقة التقليدية
أنماط enable_if درس مجاني في C++ Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C++ Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C++ Academy 4 دروس في المجموع.
ما هي enable_if؟
إن std::enable_if سمة صغيرة تعرّف عضوًا باسم type بصورة شرطية. عندما يكون الشرط صحيحًا، يكون النوع موجودًا؛ وعندما يكون خطأً، يُحذف القالب المحيط عبر SFINAE.
- توجد في
<type_traits>. - وهي الأداة التقليدية لتقييد القوالب.
#include <iostream>
#include <type_traits>
template <typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
doubleIt(T v) { return v * 2; }
int main() {
std::cout << doubleIt(21) << '\n';
return 0;
}كيف تعمل؟
تكون enable_if<Cond, T>::type مساويةً لـ T فقط عندما تكون Cond صحيحة. وإذا كانت خاطئة، فلا يوجد عضو باسم type، ولذلك يفشل الاستبدال.
#include <iostream>
#include <type_traits>
int main() {
std::cout << std::boolalpha;
std::cout << std::is_same<std::enable_if<true, int>::type, int>::value << '\n';
return 0;
}enable_if في نوع الإرجاع
الموضع الأكثر شيوعًا هو نوع الإرجاع. ولا تكون الدالة موجودة إلا عندما يتحقق الشرط.
#include <iostream>
#include <type_traits>
template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type
half(T v) { return v / 2; }
int main() {
std::cout << half(5.0) << '\n';
return 0;
}enable_if كمعامل قالب
يضع أسلوب آخر enable_if في معامل قالب ذي قيمة افتراضية، مما يحافظ على نظافة نوع الإرجاع.
#include <iostream>
#include <type_traits>
template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
T triple(T v) { return v * 3; }
int main() {
std::cout << triple(4) << '\n';
return 0;
}الاختصار enable_if_t
أضافت C++14 الاسم البديل std::enable_if_t<Cond, T>، بحيث يمكنك تجنب الصياغة الزائدة typename ...::type.
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_integral<T>::value, T>
negate(T v) { return -v; }
int main() {
std::cout << negate(8) << '\n';
return 0;
}إقران تحميلين زائدين
وفر شروطًا متكاملة بحيث يكون أحد التحميلين الزائدين صالحًا تمامًا لأي نوع، من دون أي التباس.
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_integral<T>::value, const char*>
category() { return "integer"; }
template <typename T>
std::enable_if_t<!std::is_integral<T>::value, const char*>
category() { return "non-integer"; }
int main() {
std::cout << category<int>() << ' ' << category<double>() << '\n';
return 0;
}دمج الشروط
استخدم العوامل المنطقية مع قيم السمات للتعبير عن قيود أكثر تعقيدًا، مثل «تكاملي وموقّع».
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value, T>
magnitude(T v) { return v < 0 ? -v : v; }
int main() {
std::cout << magnitude(-12) << '\n';
return 0;
}تقييد مُنشئ
يمكنك وضع enable_if في معامل قالب المُنشئ للسماح باستخدامه فقط مع الأنواع المتوافقة.
#include <iostream>
#include <type_traits>
struct Wrapper {
int value;
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
Wrapper(T v) : value(static_cast<int>(v)) {}
};
int main() {
Wrapper w(42);
std::cout << w.value << '\n';
return 0;
}مأزق معامل القالب الافتراضي
يُنظر إلى تحميلين زائدين يختلفان فقط في معامل قالب enable_if ذي القيمة الافتراضية على أنهما إعادة تعريف. اجعلهما بصيغتين مختلفتين، كأن تضع أحد الشرطين في نوع الإرجاع.
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_integral<T>::value, void>
printKind() { std::cout << "int\n"; }
template <typename T>
std::enable_if_t<std::is_floating_point<T>::value, void>
printKind() { std::cout << "float\n"; }
int main() {
printKind<int>();
printKind<double>();
return 0;
}مقارنة بالمفاهيم
تستبدل المفاهيم في C++20 معظم استخدامات enable_if بصياغة أوضح بكثير، لكن enable_if تظل ضرورية في الشيفرة السابقة لـ C++20 وفي بعض الحالات الخاصة.
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_arithmetic<T>::value, T>
square(T v) { return v * v; }
int main() {
std::cout << square(6) << ' ' << square(1.5) << '\n';
return 0;
}مثال كامل
اجمع كل الأجزاء: عائلة دوال تُنسّق الأعداد الصحيحة والأعداد العشرية بطرق مختلفة، ويُختار بينها في وقت الترجمة.
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_integral<T>::value, void>
format(T v) { std::cout << "int[" << v << "]\n"; }
template <typename T>
std::enable_if_t<std::is_floating_point<T>::value, void>
format(T v) { std::cout << "float(" << v << ")\n"; }
int main() {
format(10);
format(3.5);
return 0;
}تحقق سريع
اختبر مدى فهمك لـ enable_if.
مراجعة
لقد تعلمت الأنماط التقليدية لـ enable_if:
- تعرّف
::typeفقط عندما يكون الشرط صحيحًا، مما يتيح SFINAE - توضع في نوع الإرجاع أو في معامل قالب ذي قيمة افتراضية
- استخدم الاسم البديل
enable_if_tوادمج السمات باستخدام العوامل المنطقية - تحل المفاهيم محلها في C++20، لكنها ما تزال مستخدمة على نطاق واسع
وبذلك يكتمل مقرر تخصيص القوالب وSFINAE.
الأسئلة الشائعة
هل درس «أنماط enable_if» مجاني؟
نعم — نص درس «أنماط enable_if» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C++ Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C++ Academy 4 دروس في المجموع.
ماذا ستتعلم في «أنماط enable_if»؟
قيّد القوالب بالطريقة التقليدية تتمرن على C++ Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ C++ Academy؟
لا تُشترط خبرة سابقة. C++ Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «أنماط enable_if»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس C++ Academy هذا؟
نعم. كل درس في C++ Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- التخصيص الكامل
- التخصيص الجزئي
- SFINAE
- أنماط enable_if