**Մետածրագրավորում**-ը ծրագրավորման տեխնիկա է, որի կիրառման դեպքում ծրագիրն ինքը կարող է աշխատանքի ընթացքում կարդալ, գեներացնել, ստուգել կամ փոփոխել մեկ այլ ծրագրի կամ հենց ինքն իր կառուցվածքը (կոդը)։ 
Շատ դեպքերում սա ծրագրավորողին օգնում է կրճատել կոդի տողերի քանակը և ծրագրավորման ժամանակը։
Այս ամենից բացի ծրագրերը դառնում են ավելի ճկուն և հարմարվում են նոր փոփոխությունների առանց նորից կոմպիլացվելու։

Մետածրագրավորման ձևերից մեկն է կաղապարների (template) միջոցով մետածրագրավորումը, երբ կաղապարներն օգտագործվում են կոմպիլիացիայի ժամանակ որևէ գործ կատարելու նպատակով։ 
Այս տեխնիկան օգտագործվում է հիմնականում C++, Curl, D, և XL լեզուներում, ինչպես նաև Lisp–ում՝ մակրոների միջոցով։

Մոտեցումներ
-----------

Մետածրագրավորումը հնարավորություն է տալիս գրել ծրագրեր կամ մշակել կոդ ընդհանուր ծրագրավորման պարադիգմի համատեքստում։

C++ կաղապարներ
--------------

C++ լեզուն հնարավորություն է տալիս գրել *ընդհանրացված* մեթոդ կամ դաս՝ առանց նշելու, թե որ տիպերի համար պետք է այն աշխատի։
Հետագայում, օգտագործելով այդ մեթոդը կամ դասը որևէ տիպի համար, կոմպիլիատորը գեներացնում է տվյալ կաղապարի համապատասխան կոդը՝ արդեն կոնկրետ նշված տիպի համար։ 
Հաշվի առնելով այն փաստը, որ կաղապարի կոդի գեներացիան կատարվում է կոմպիլիացիայի ժամանակ, հնարավորություն է ստեղծվում կաղապարների օգտագործմամբ հաշվել տարբեր արժեքներ կամ կատարել տարբեր խնդիրներ՝ առանց ծրագրի կատարման ընթացում ժամանակ կորցնելու։

Կաղապարի օրինակ՝

```
template <typename T>
inline T const& max (T const& a, T const& b) {
 // եթե a < b, վերադարձնում է b, հակառակ դեպքում a: 
 return a < b ? b : a;
}

```

Տվյալ կաղապարային ֆունկցիան վերադարձնում է ստացված երկու արժեքներից մեծագույնը։ `typename`֊ը տեղեկացնում է կոմպիլիատորին, որ `T`֊ն տիպ է։ `max` ֆունկացիան որևէ տիպի համար օգտագործելու դեպքում T–ն կփոխարինվի համապատասխան տիպով
և կգեներացվի տվյալ ֆունկցիային համապատասխան կոդը հենց այդ տիպի համար։
Սակայն max ֆունկացիան կանչելու դեպքում այն կաշխատի ծրագրի կատարման ընթացքում, իսկ մետածրագրավորում իրականացնելու համար 
մեզ անհրաժեշտ է հաշվել արժեքներ ոչ թե ծրագրի կատարման ընթացքում, այլ կոմպիլիացիայի ժամանակ, դրանով իսկ դարձնելով ծրագրի 
աշխատանքը ավելի արագ։

Ֆակտորիալի օրինակը
------------------

Կաղապարներով մետածրագրավորման օրինակ կարող է հանդիսանալ թվի ֆակտորիալի հաշվման ծրագիրը։ 
Թվի ֆակտորիալը կաղապարների միջոցով հաշվելը հնարավորություն է տալիս արդյունքը ստանալ կոմպիլիացիայի ժամանակ։ Վերը բերված `max` ֆունկցիայի օրինակով հնարավոր չէ հասնել պահանջվող արդյունքին։ Անհրաժեշտ է ֆակտորիալ հաշվող ֆունկցիայում ունենալ *ռեկուրսիվ* կանչ։

```
template <int N> 
struct Factorial {
 enum { value = N \* Factorial<N - 1>::value };
};

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

void foo() {
 int x = Factorial<0>::value; // == 1
 int y = Factorial<4>::value; // == 24
}

```

Այստեղ կոմպիլյատորը կաղապար գեներացնելու փոխարեն նախ հաշվում է `value`֊ի արժեքը։ `value`֊ի `0` արժեքի համար գրված է մեկ այլ կաղապար (Factorial–ի մասնավոր դեպք), որպես ռեկուրսիայի բազա։ 
`enum`֊ի օգտագործումը հնարավորություն է տալիս ունենալ կոմպիլիացիայի ժամանակ հաշվարկվող արժեք։ Այս եղանակով `x`֊ի և `y`֊ի արժեքները հայտնի են դառնում արդեն ծրագրի կատարվելու պահին՝ առանց որևէ ժամանակային կորուստների։

C++11–ը մեզ հնարավորություն է տալիս անել նույնը առանց կաղապարներից օգտվելու, 
որը իրականացվում է constexpr–ի միջոցով։ constexpr–ը իրենից ներկայացնում է 
արտահայտություն, որի արժեքը հայտնի է կոմպիլյացիայի ժամանակ, կամ ֆունկցիա՝ 
որի վերադարձրած արժեքը հայտնի է կոմպիլյացիայի ժամանակ։

```
#include <iostream>
 
constexpr int factorial(int n) 
{
 return n ? (n \* factorial(n - 1)) : 1;
}

int main() 
{
 constexpr int fact = factorial(10000);
 std::cout << fact << std::endl;
 return 0;
}

```

STL կոնտեյները
--------------

Ստանդարտ Կաղապարային Գրադարանը տարբերի խնդիրներ լուծելու համար ապահովում է մեծ թվով տվյալների կառուցվածքներ։ Այդ թվում նաև `vector`, `set`, `list`, `map`, `queue` և այլ կոնտեյներները։ Բոլոր տվյալների կառուցվածքները կաղապարային դասեր են։ Օրինակ, ամբողջ թվերի `vector` ստեղծելու համար պետք է նշել կաղապարային պարամետրը (տվյալ դեպքում՝ `int`)։

```
std::vector<int> v(10);
for( int j = 0; j < 10; j++ ) 
 v[j] = j \* j;

```

Այս դեպքում կկառուցվի առաջին 10 ամբողջ թվերի քառակուսիները պարունակող `vector` օբյեկտը։

Ծանոթագրություններ
------------------

1. ↑  Course on Program Analysis and Transformation. By Prof. Harald Sondergaard.«Course on Program Analysis and Transformation». Վերցված է 2014 թ․ սեպտեմբերի 18-ին.
2. ↑  Czarnecki, Krzysztof; Eisenecker, Ulrich W. (2000). *Generative Programming*. ISBN 0-201-30977-7.