टेम्पलेट मेटाप्रोग्रामिंग

टेम्पलेट मेटाप्रोग्रामिंग (टीएमपी) एक मेटाप्रोग्रामिंग तकनीक है जिसमें एक संकलक  द्वारा अस्थायी स्रोत कोड उत्पन्न करने के लिए  सामान्य प्रोग्रामिंग  का उपयोग किया जाता है, जिसे कंपाइलर द्वारा शेष स्रोत कोड के साथ विलय कर दिया जाता है और फिर संकलित किया जाता है। इन टेम्प्लेट के आउटपुट में  संकलन समय  | कंपाइल-टाइम कॉन्स्टेंट (प्रोग्रामिंग), डेटा संरचना और कम्पलीट  समारोह (कंप्यूटर विज्ञान)  शामिल हो सकते हैं। टेम्प्लेट के उपयोग को  संकलन-समय फ़ंक्शन निष्पादन  | कंपाइल-टाइम पॉलीमोर्फिज्म के रूप में माना जा सकता है। इस तकनीक का उपयोग कई भाषाओं में किया जाता है, जिनमें से सबसे प्रसिद्ध सी ++ है, लेकिन कर्ल प्रोग्रामिंग भाषा, डी प्रोग्रामिंग भाषा, निम (प्रोग्रामिंग भाषा), और एक्सएल प्रोग्रामिंग भाषा भी है।

टेम्पलेट मेटाप्रोग्रामिंग, एक अर्थ में, गलती से खोजी गई थी। कुछ अन्य भाषाएं इसी तरह का समर्थन करती हैं, यदि अधिक शक्तिशाली नहीं, संकलन-समय की सुविधाएं (जैसे लिस्प (प्रोग्रामिंग भाषा) मैक्रो (कंप्यूटर विज्ञान)#सिंटैक्टिक मैक्रोज़), लेकिन वे इस लेख के दायरे से बाहर हैं।

टेम्पलेट मेटाप्रोग्रामिंग के घटक
मेटाप्रोग्रामिंग तकनीक के रूप में टेम्प्लेट के उपयोग के लिए दो अलग-अलग संचालन की आवश्यकता होती है: एक टेम्प्लेट को परिभाषित किया जाना चाहिए, और एक परिभाषित टेम्प्लेट को उदाहरण (कंप्यूटर विज्ञान)  होना चाहिए। जेनरेट किए गए स्रोत कोड का सामान्य रूप टेम्पलेट परिभाषा में वर्णित है, और जब टेम्पलेट तत्काल होता है, तो टेम्पलेट में सामान्य रूप का उपयोग स्रोत कोड के विशिष्ट सेट को उत्पन्न करने के लिए किया जाता है।

टेम्प्लेट मेटाप्रोग्रामिंग ट्यूरिंग-पूर्ण है, जिसका अर्थ है कि कंप्यूटर प्रोग्राम द्वारा अभिव्यक्त किसी भी संगणना की गणना, किसी न किसी रूप में, टेम्प्लेट मेटाप्रोग्राम द्वारा की जा सकती है। टेम्प्लेट मैक्रो (कंप्यूटर साइंस) # प्रोग्रामिंग मैक्रोज़ से अलग हैं। एक मैक्रो कोड का एक टुकड़ा है जो संकलन समय पर निष्पादित होता है और या तो संकलित किए जाने वाले कोड का शाब्दिक हेरफेर करता है (जैसे C ++ मैक्रोज़) या संकलक द्वारा उत्पादित सार वाक्य रचना का पेड़ में हेरफेर करता है (जैसे जंग (प्रोग्रामिंग भाषा) या लिस्प (प्रोग्रामिंग) भाषा) मैक्रोज़)। शाब्दिक मैक्रोज़ हेरफेर की जा रही भाषा के सिंटैक्स से विशेष रूप से अधिक स्वतंत्र हैं, क्योंकि वे संकलन से ठीक पहले स्रोत कोड के इन-मेमोरी टेक्स्ट को बदलते हैं।

टेम्पलेट मेटाप्रोग्राम में कोई अपरिवर्तनीय वस्तु नहीं है - अर्थात, एक बार प्रारंभ होने के बाद कोई चर मूल्य नहीं बदल सकता है, इसलिए टेम्पलेट मेटाप्रोग्रामिंग को कार्यात्मक प्रोग्रामिंग के रूप में देखा जा सकता है। वास्तव में कई टेम्पलेट कार्यान्वयन प्रवाह नियंत्रण को केवल रिकर्सन (कंप्यूटर विज्ञान) के माध्यम से लागू करते हैं, जैसा कि नीचे दिए गए उदाहरण में देखा गया है।

टेम्प्लेट मेटाप्रोग्रामिंग का उपयोग
हालांकि टेम्प्लेट मेटाप्रोग्रामिंग का वाक्य-विन्यास आमतौर पर उस प्रोग्रामिंग भाषा से बहुत अलग होता है जिसके साथ इसका उपयोग किया जाता है, इसके व्यावहारिक उपयोग हैं। टेम्प्लेट का उपयोग करने के कुछ सामान्य कारण सामान्य प्रोग्रामिंग को लागू करना है (कोड के अनुभागों से बचना जो कुछ मामूली बदलावों को छोड़कर समान हैं) या स्वत: संकलन-समय अनुकूलन करने के लिए जैसे कि हर बार कार्यक्रम चलाने के बजाय संकलन समय पर एक बार कुछ करना - उदाहरण के लिए, जब भी प्रोग्राम निष्पादित किया जाता है तो जंपर्स और लूप काउंट डिक्रीमेंट्स को खत्म करने के लिए कंपाइलर अनरोल लूप्स के द्वारा।

संकलन-समय वर्ग पीढ़ी
संकलन-समय पर वास्तव में प्रोग्रामिंग का क्या अर्थ है, इसे फैक्टोरियल फ़ंक्शन के उदाहरण के साथ चित्रित किया जा सकता है, जो गैर-टेम्प्लेट सी ++ में रिकर्सन का उपयोग करके निम्नानुसार लिखा जा सकता है: शाब्दिक 0 और 4 के भाज्य मान को निर्धारित करने के लिए उपरोक्त कोड रन टाइम पर निष्पादित होगा। पुनरावर्तन के लिए अंतिम स्थिति प्रदान करने के लिए टेम्प्लेट मेटाप्रोग्रामिंग और टेम्प्लेट विशेषज्ञता का उपयोग करके, प्रोग्राम में उपयोग किए जाने वाले फैक्टोरियल - उपयोग नहीं किए गए किसी भी फैक्टोरियल को अनदेखा करते हुए - इस कोड द्वारा संकलन समय पर गणना की जा सकती है: उपरोक्त कोड संकलन समय पर शाब्दिक 0 और 4 के भाज्य मान की गणना करता है और परिणामों का उपयोग करता है जैसे कि वे सटीक स्थिरांक थे। इस तरह से टेम्प्लेट का उपयोग करने में सक्षम होने के लिए, कंपाइलर को संकलन समय पर अपने मापदंडों के मूल्य का पता होना चाहिए, जिसमें प्राकृतिक पूर्व शर्त है कि फैक्टोरियल ::मान का उपयोग केवल तभी किया जा सकता है जब X को संकलन समय पर जाना जाता है। दूसरे शब्दों में, X एक स्थिर शाब्दिक या एक स्थिर अभिव्यक्ति होना चाहिए।

सी ++ 11 और सी ++ 20 में, कंपाइलर को कोड निष्पादित करने के लिए constexpr और कॉन्स्टेवल पेश किए गए थे। कॉन्स्टेक्सप्र और कॉन्स्टेवल का उपयोग करके, गैर-टेम्पलेटेड सिंटैक्स के साथ सामान्य पुनरावर्ती फैक्टोरियल परिभाषा का उपयोग किया जा सकता है।

संकलन-समय कोड अनुकूलन
उपरोक्त फैक्टोरियल उदाहरण संकलन-समय कोड अनुकूलन का एक उदाहरण है जिसमें प्रोग्राम द्वारा उपयोग किए जाने वाले सभी फैक्टोरियल पूर्व-संकलित होते हैं और संकलन पर संख्यात्मक स्थिरांक के रूप में इंजेक्ट किए जाते हैं, रन-टाइम ओवरहेड और मेमोरी फ़ुटप्रिंट दोनों को बचाते हैं। हालाँकि, यह अपेक्षाकृत मामूली अनुकूलन है।

दूसरे के रूप में, अधिक महत्वपूर्ण, संकलन-समय लूप अनोलिंग का उदाहरण, टेम्पलेट मेटाप्रोग्रामिंग का उपयोग लंबाई-एन वेक्टर वर्ग बनाने के लिए किया जा सकता है (जहां एन को संकलन समय पर जाना जाता है)। अधिक पारंपरिक लंबाई-एन वेक्टर पर लाभ यह है कि लूप को अनियंत्रित किया जा सकता है, जिसके परिणामस्वरूप बहुत अनुकूलित कोड होता है। एक उदाहरण के रूप में, अतिरिक्त ऑपरेटर पर विचार करें। लंबाई-एन सदिश जोड़ को इस रूप में लिखा जा सकता है जब संकलक ऊपर परिभाषित फ़ंक्शन टेम्पलेट को तुरंत चालू करता है, तो निम्न कोड उत्पन्न हो सकता है:

कंपाइलर का ऑप्टिमाइज़र अनलॉक करने में सक्षम होना चाहिए  लूप क्योंकि टेम्पलेट पैरामीटर   संकलन समय पर स्थिर है।

हालाँकि, सावधानी बरतें और सावधानी बरतें क्योंकि इससे कोड ब्लोट हो सकता है क्योंकि प्रत्येक 'एन' (वेक्टर आकार) के लिए अलग-अलग अनियंत्रित कोड उत्पन्न होगा, जिसके साथ आप तुरंत चलते हैं।

स्थैतिक बहुरूपता
प्रकार बहुरूपता एक सामान्य मानक प्रोग्रामिंग सुविधा है जहां व्युत्पन्न वस्तुओं को उनके मूल वस्तु के उदाहरणों के रूप में उपयोग किया जा सकता है लेकिन जहां व्युत्पन्न वस्तुओं के तरीकों को लागू किया जाएगा, जैसा कि इस कोड में है जहां के सभी आह्वान  विधियाँ सर्वाधिक व्युत्पन्न वर्ग की होंगी। यह गतिशील रूप से बहुरूपी व्यवहार (आमतौर पर) vtable के निर्माण द्वारा प्राप्त किया जाता है। वर्चुअल विधियों के साथ कक्षाओं के लिए वर्चुअल लुक-अप टेबल, टेबल जो रन टाइम पर ट्रैवर्स किए जाते हैं ताकि आह्वान की जाने वाली विधि की पहचान हो सके। इस प्रकार, रन-टाइम बहुरूपता आवश्यक रूप से निष्पादन ओवरहेड (हालांकि आधुनिक आर्किटेक्चर पर ओवरहेड छोटा है) पर जोर देता है।

हालाँकि, कई मामलों में आवश्यक बहुरूपी व्यवहार अपरिवर्तनीय है और संकलन समय पर निर्धारित किया जा सकता है। फिर जिज्ञासु आवर्ती टेम्पलेट पैटर्न (CRTP) का उपयोग 'स्थैतिक बहुरूपता' को प्राप्त करने के लिए किया जा सकता है, जो प्रोग्रामिंग कोड में बहुरूपता की नकल है, लेकिन जिसे संकलन समय पर हल किया जाता है और इस प्रकार रन-टाइम वर्चुअल-टेबल लुकअप से दूर हो जाता है। उदाहरण के लिए: यहां बेस क्लास टेम्पलेट इस तथ्य का लाभ उठाएगा कि सदस्य फ़ंक्शन निकायों को उनकी घोषणा के बाद तक तत्काल नहीं किया जाता है, और यह व्युत्पन्न वर्ग के सदस्यों को अपने स्वयं के सदस्य कार्यों के उपयोग के माध्यम से उपयोग करेगा, इस प्रकार संकलन में बहुरूपी विशेषताओं के साथ एक वस्तु रचना उत्पन्न होती है। वास्तविक दुनिया के उपयोग के उदाहरण के रूप में, CRTP का उपयोग बूस्ट लाइब्रेरी इटरेटर लाइब्रेरी में किया जाता है। एक अन्य समान उपयोग बार्टन-नैकमैन ट्रिक है, जिसे कभी-कभी प्रतिबंधित टेम्पलेट विस्तार के रूप में संदर्भित किया जाता है, जहां सामान्य कार्यक्षमता को एक आधार वर्ग में रखा जा सकता है जिसका उपयोग अनुबंध के रूप में नहीं बल्कि कोड अतिरेक को कम करते हुए अनुरूप व्यवहार को लागू करने के लिए एक आवश्यक घटक के रूप में किया जाता है।

स्टेटिक टेबल जनरेशन
स्थैतिक तालिकाओं का लाभ एक साधारण सरणी अनुक्रमण ऑपरेशन के साथ महंगी गणनाओं का प्रतिस्थापन है (उदाहरण के लिए, लुकअप तालिका देखें)। सी ++ में, संकलन समय पर स्थिर तालिका उत्पन्न करने के एक से अधिक तरीके मौजूद हैं। निम्न सूची रिकर्सिव स्ट्रक्चर्स और विविध टेम्पलेट्स का उपयोग करके एक बहुत ही सरल तालिका बनाने का एक उदाहरण दिखाती है। तालिका का आकार दस है। प्रत्येक मान सूचकांक का वर्ग है।

इसके पीछे विचार यह है कि स्ट्रक्चर हेल्पर पुनरावर्ती रूप से एक संरचना से एक और टेम्पलेट तर्क (इस उदाहरण में INDEX * INDEX के रूप में गणना की गई) के साथ प्राप्त करता है जब तक कि टेम्पलेट की विशेषज्ञता 10 तत्वों के आकार पर पुनरावृत्ति समाप्त नहीं करती। विशेषज्ञता केवल चर तर्क सूची का उपयोग सरणी के तत्वों के रूप में करती है। संकलक निम्नलिखित के समान कोड का उत्पादन करेगा (क्लैंग से लिया गया जिसे -Xclang -ast-print -fsyntax-only कहा जाता है)। चूंकि सी ++ 17 इसे और अधिक आसानी से लिखा जा सकता है:

अधिक परिष्कृत उदाहरण दिखाने के लिए निम्नलिखित सूची में कोड को मूल्य गणना के लिए एक सहायक (अधिक जटिल संगणना की तैयारी में), तालिका विशिष्ट ऑफ़सेट और तालिका मानों के प्रकार के लिए एक टेम्पलेट तर्क के लिए विस्तारित किया गया है (उदाहरण के लिए uint8_t, uint16_t, ...) जिसे C++17 का उपयोग करके इस प्रकार लिखा जा सकता है:

अवधारणाएं
C++20 मानक ने C++ प्रोग्रामर्स को मेटा टेम्पलेट प्रोग्रामिंग, अवधारणाओं के लिए एक नया उपकरण दिया। अवधारणाएँ (C++) प्रोग्रामर को प्रकार के लिए आवश्यकताओं को निर्दिष्ट करने की अनुमति देती हैं, ताकि टेम्पलेट का इन्स्टेन्शियशन संभव हो सके। कंपाइलर उस अवधारणा वाले टेम्पलेट की तलाश करता है जिसकी उच्चतम आवश्यकताएं हैं।

यहाँ टेम्पलेट मेटा प्रोग्रामिंग के साथ हल की गई प्रसिद्ध फ़िज़ बज़ समस्या का एक उदाहरण है।

टेम्प्लेट मेटाप्रोग्रामिंग के लाभ और कमियां

 * कंपाइल-टाइम बनाम एक्ज़ीक्यूशन-टाइम ट्रेडऑफ़: यदि टेम्प्लेट मेटाप्रोग्रामिंग का एक बड़ा उपयोग किया जाता है।
 * सामान्य प्रोग्रामिंग: टेम्प्लेट मेटाप्रोग्रामिंग प्रोग्रामर को आर्किटेक्चर पर ध्यान केंद्रित करने और क्लाइंट कोड द्वारा आवश्यक किसी भी कार्यान्वयन की पीढ़ी को कंपाइलर को सौंपने की अनुमति देता है। इस प्रकार, टेम्प्लेट मेटाप्रोग्रामिंग वास्तव में सामान्य कोड को पूरा कर सकता है, जिससे कोड न्यूनीकरण और बेहतर रखरखाव की सुविधा मिलती है.
 * पठनीयता: C++ 11 से पहले C++ के संबंध में, टेम्पलेट मेटाप्रोग्रामिंग के वाक्य-विन्यास और मुहावरे पारंपरिक C++ प्रोग्रामिंग की तुलना में गूढ़ थे, और टेम्पलेट मेटाप्रोग्राम को समझना बहुत मुश्किल हो सकता है। लेकिन सी ++ 11 से आगे मूल्य गणना मेटाप्रोग्रामिंग के लिए सिंटैक्स कम और कम पठनीयता दंड के साथ सामान्य सी ++ के समान अधिक हो जाता है।

यह भी देखें

 * प्रतिस्थापन विफलता एक त्रुटि नहीं है (SFINAE)
 * मेटाप्रोग्रामिंग
 * preprocessor
 * पैरामीट्रिक बहुरूपता
 * अभिव्यक्ति टेम्पलेट्स
 * वैराडिक टेम्पलेट
 * संकलन-समय फ़ंक्शन निष्पादन

बाहरी संबंध

 * (built using template-metaprogramming)
 * (use STL algorithms easily)
 * (type-safe metaprogramming in Haskell)
 * (template metaprogramming in the D programming language)
 * (type-safe metaprogramming in Haskell)
 * (template metaprogramming in the D programming language)