2009-01-31 29 views
85

जब एक टेम्पलेट की घोषणा, मैं कोड के इस प्रकार के होने के लिए इस्तेमाल किया कर रहा हूँ:टेम्पलेट <unsigned int N> का अर्थ क्या है?

template <class T> 

लेकिन in this question, वे प्रयोग किया है:

template <unsigned int N> 

मैं जाँच की है कि यह संकलित करता है। लेकिन इसका मतलब क्या है? क्या यह एक गैर-प्रकार पैरामीटर है? और यदि हां, तो हमारे पास किसी भी प्रकार के पैरामीटर के बिना टेम्पलेट कैसे हो सकता है?

उत्तर

116

एक प्रकार के बजाय एक पूर्णांक पर एक वर्ग को टेम्पलेट करना पूरी तरह से संभव है। हम एक चर करने के लिए टेम्प्लेट की गई मूल्य प्रदान कर सकते हैं, या अन्यथा एक तरह से हम किसी अन्य पूर्णांक शाब्दिक साथ हो सकता है में यह हेरफेर:

unsigned int x = N; 

वास्तव में, हम एल्गोरिदम, जो संकलन समय पर मूल्यांकन (Wikipedia से) बना सकते हैं:

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

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

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

आप अपने 'enum' के बजाय' static constexpr int' टाइप भी कर सकते हैं। तो 'फैक्टोरियल <0>' टेम्पलेट में 'स्थैतिक constexpr int value = 1' होगा, और 'टेम्पलेट संरचना फैक्टोरियल' में स्थिर स्थिरांक int मान = एन * फैक्टोरियल :: मान;' – bobobobo

14

आप अपनी कक्षा को 'हस्ताक्षरित int' के आधार पर templatize।

उदाहरण:

template <unsigned int N> 
class MyArray 
{ 
    public: 
    private: 
     double data[N]; // Use N as the size of the array 
}; 

int main() 
{ 
    MyArray<2>  a1; 
    MyArray<2>  a2; 

    MyArray<4>  b1; 

    a1 = a2; // OK The arrays are the same size. 
    a1 = b1; // FAIL because the size of the array is part of the 
       //  template and thus the type, a1 and b1 are different types. 
       //  Thus this is a COMPILE time failure. 
} 
128

हाँ, यह एक गैर प्रकार पैरामीटर है। आपके पास कई प्रकार के टेम्पलेट पैरामीटर

  • पैरामीटर्स टाइप कर सकते हैं।
    • प्रकार
    • टेम्पलेट (केवल वर्गों और उर्फ ​​टेम्पलेट्स, कोई कार्य या चर टेम्पलेट्स)
  • गैर प्रकार पैरामीटर
    • प्वाइंटर
    • संदर्भ
    • इंटीग्रल निरंतर भाव

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

खाका प्रकार पैरामीटर:

template<typename T> 
struct Container { 
    T t; 
}; 

// pass type "long" as argument. 
Container<long> test; 

खाका पूर्णांक पैरामीटर:

template<unsigned int S> 
struct Vector { 
    unsigned char bytes[S]; 
}; 

// pass 3 as argument. 
Vector<3> test; 

खाका सूचक पैरामीटर (एक समारोह के लिए एक सूचक गुजर)

template<void (*F)()> 
struct FunctionWrapper { 
    static void call_it() { F(); } 
}; 

// pass address of function do_it as argument. 
void do_it() { } 
FunctionWrapper<&do_it> test; 

खाका संदर्भ पैरामीटर (एक पूर्णांक गुजरना)

template<int &A> 
struct SillyExample { 
    static void do_it() { A = 10; } 
}; 

// pass flag as argument 
int flag; 
SillyExample<flag> test; 

टेम्पलेट टेम्पलेट पैरामीटर।

template<template<typename T> class AllocatePolicy> 
struct Pool { 
    void allocate(size_t n) { 
     int *p = AllocatePolicy<int>::allocate(n); 
    } 
}; 

// pass the template "allocator" as argument. 
template<typename T> 
struct allocator { static T * allocate(size_t n) { return 0; } }; 
Pool<allocator> test; 

किसी भी पैरामीटर के बिना टेम्पलेट संभव नहीं है। लेकिन किसी भी स्पष्ट तर्क के बिना एक टेम्पलेट के लिए संभव है - यह डिफ़ॉल्ट तर्क हैं:

template<unsigned int SIZE = 3> 
struct Vector { 
    unsigned char buffer[SIZE]; 
}; 

Vector<> test; 

वाक्य रचना, template<> पैरामीटर के बिना एक टेम्पलेट के बजाय, एक स्पष्ट टेम्पलेट विशेषज्ञता चिह्नित करने के लिए आरक्षित है:

template<> 
struct Vector<3> { 
    // alternative definition for SIZE == 3 
}; 
+0

जोहान्स, टेम्पलेट्स " प्रकार "? मैंने सोचा कि वे किस तरह से बनाए जा सकते हैं, लेकिन खुद को टाइप नहीं करते? – sbi

+0

@ एसबीआई स्पष्टीकरण देखें: "मानक में इसे देखने के बाद, मुझे क्लास टेम्पलेट को प्रकार अनुभाग में ले जाना पड़ा - भले ही टेम्पलेट्स प्रकार न हों। लेकिन फिर भी उन प्रकारों का वर्णन करने के उद्देश्य से उन्हें टाइप-पैरामीटर कहा जाता है। । "। 14.1/2 पर फुटनोट 126 ऐसा कहता है। यह गैर वर्गीकरण पैरामीटर बनाने के लिए सिर्फ एक वर्गीकरण है जो एक मान/संदर्भ और प्रकार-पैरामीटर घोषित करता है जो किसी प्रकार का नाम या टेम्पलेट नाम घोषित करता है। –

+0

@ जोहान्सचैब-लिटब इसलिए std :: string कहने के साथ टेम्पलेट टाइप करने का कोई तरीका नहीं है? प्रत्येक अलग स्ट्रिंग के लिए अद्वितीय आईडी बनाने के लिए टेम्पलेट कक्षा में कुछ स्थिर काउंटर के साथ? int के लिए हैशिंग स्ट्रिंग दुर्भाग्य से सही तरीका होगा? – relaxxx

12

एक टेम्पलेट कक्षा एक मैक्रो की तरह है, केवल एक बहुत कम बुरा बुराई।

एक मैक्रो के रूप में टेम्पलेट के बारे में सोचें। जब आप किसी टेम्पलेट का उपयोग करके कक्षा (या फ़ंक्शन) को परिभाषित करते हैं, तो टेम्पलेट के पैरामीटर को कक्षा (या फ़ंक्शन) परिभाषा में प्रतिस्थापित किया जाता है।

अंतर यह है कि पैरामीटर में "प्रकार" होते हैं और संकलन के दौरान पैरामीटर जैसे पैरामीटर की गणना की जाती है। मान्य प्रकार आपके नियमित सी ++ प्रकार हैं, जैसे int और char। जब आप टेम्पलेट क्लास को तुरंत चालू करते हैं, तो आप निर्दिष्ट प्रकार के मान को पास करते हैं, और टेम्पलेट क्लास परिभाषा की एक नई प्रति में इस मान को मूल परिभाषा में पैरामीटर नाम कहीं भी प्रतिस्थापित किया जाता है। एक मैक्रो की तरह।

आप पैरामीटर के लिए "class" या "typename" प्रकारों का भी उपयोग कर सकते हैं (वे वास्तव में वही हैं)। इन प्रकारों में से किसी एक के पैरामीटर के साथ, आप किसी मान के बजाय एक प्रकार का नाम पास कर सकते हैं। बस पहले की तरह, हर जगह पैरामीटर नाम टेम्पलेट क्लास परिभाषा में था, जैसे ही आप एक नया उदाहरण बनाते हैं, आप जो भी प्रकार पास करते हैं, वह बन जाता है। टेम्पलेट वर्ग के लिए यह सबसे आम उपयोग है; सी ++ टेम्पलेट्स के बारे में कुछ भी जानता है जो जानता है कि यह कैसे करें।

#include <cstdio> 
template <int I> 
class foo 
{ 
    void print() 
    { 
    printf("%i", I); 
    } 
}; 

int main() 
{ 
    foo<26> f; 
    f.print(); 
    return 0; 
}

यह कार्यात्मक इस वृहद का उपयोग कर कोड के रूप में ही है::

#include <cstdio> 
#define MAKE_A_FOO(I) class foo_##I \ 
{ \ 
    void print() \ 
    { \ 
    printf("%i", I); \ 
    } \ 
}; 

MAKE_A_FOO(26) 

int main() 
{ 
    foo_26 f; 
    f.print(); 
    return 0; 
}
बेशक

, टेम्पलेट संस्करण में एक अरब गुना सुरक्षित और अधिक लचीला है

इस टेम्पलेट वर्ग उदाहरण कोड पर विचार करें ।

संबंधित मुद्दे