تعلم لغة سي بلس بلس – الدرس الخامس Metaprogramming

0

مقدمة

إن البرمجة الوصفية للقالب (TMP) هي تقنية metaprogramming حيث يتم استخدام القوالب من قبل مترجم لإنشاء كود مصدر مؤقت ، والذي يتم دمجه بواسطة المترجم مع بقية التعليمات البرمجية المصدر ثم يتم تجميعها. يتضمن إخراج هذه القوالب ثوابت وقت الترجمة وهياكل البيانات والوظائف الكاملة. يمكن اعتبار استخدام القوالب بمثابة تنفيذ في وقت الترجمة. يتم استخدام هذه التقنية من قبل عدد من اللغات ، أشهرها C ++ ، ولكن أيضًا Curl و D و XL.

برنامجنا الأول

يمكن توضيح ما تعنيه بالضبط “البرمجة في وقت الترجمة” بمثال عن دالة عاملة ، والتي يمكن كتابتها في لغة C ++ غير النموذجية باستخدام العودية على النحو التالي:

unsigned int factorial(unsigned int n) {
  return n == 0 ? 1 : n * factorial(n - 1); 
}

// أمثلة الاستخدام:
// مضروب (0) سينتج 1 ؛
// العامل (4) ينتج عنه 24.

سيتم تنفيذ الكود أعلاه في وقت التشغيل لتحديد القيمة المضروبة للحرفين 4 و 0. وباستخدام البرمجة الوصفية للقالب وتخصص القالب لتوفير شرط النهاية للتكرار ، فإن العوامل المستخدمة في البرنامج – تجاهل أي عامل غير مستخدم – يمكن يتم احتسابها في وقت الترجمة بواسطة هذا الرمز:

template <unsigned int n>
struct factorial {
  enum { value = n * factorial<n - 1>::value };
};

template <>
struct factorial<0> {
  enum { value = 1 };
};

// أمثلة الاستخدام:
// مضروب <0> :: ستنتج القيمة 1 ؛
// مضروب <4> :: ستؤدي إلى 24.

يحسب الكود أعلاه القيمة المضروبة للحرفين 4 و 0 في وقت الترجمة ويستخدم النتائج كما لو كانت ثوابت محسوبة مسبقًا. لتكون قادرًا على استخدام القوالب بهذه الطريقة ، يجب أن يعرف المحول البرمجي قيمة معلماته في وقت الترجمة ، والذي له الشرط الطبيعي الذي لا يمكن استخدامه إلا إذا كان X معروفًا في وقت الترجمة. بمعنى آخر ، يجب أن تكون X عبارة عن تعبير حرفي ثابت أو تعبير ثابت.

تمرين

اكتب برنامج cpp باستخدام metaprogramming النموذجية ، والذي يحسب قوى 2

#include <iostream> 
using namespace std; 

// اكتب الكود هنا
  
int main() 
{ 
    cout << funStruct<8>::val << endl; 
    return 0; 
} 

الحل

#include <iostream> 
using namespace std; 
  
template<int n> struct funStruct 
{ 
    enum { val = 2*funStruct<n-1>::val }; 
}; 
  
template<> struct funStruct<0> 
{ 
    enum { val = 1 }; 
}; 
  
int main() 
{ 
    cout << funStruct<8>::val << endl; 
    return 0; 
} 

سنحصل على النتيجة التالية عند التشغيل

256

الدرس السادس

اترك رد

لن يتم نشر عنوان بريدك الإلكتروني.