यहां दो अलग-अलग कारक चल रहे हैं।
सबसे पहले, उन टेम्पलेट्स को परिभाषित करना संभव है जो कि प्रकारों के अलावा अन्य चीज़ों पर पैरामीटरकृत हैं।
template <typename T, size_t N> struct Array {
T arr[N];
};
हम जैसे
Array<int, 137> myArray;
हम जानते हैं कि vector<int>
और vector<double>
विभिन्न प्रकार हैं इस का उपयोग कर सकते हैं: उदाहरण के लिए, यहाँ एक सरल सरणी प्रकार है। लेकिन अब हमें यह भी इंगित करना होगा कि Array<int,137>
और Array<int,136>
विभिन्न प्रकार हैं।
दूसरा, टेम्पलेट का उपयोग करते समय, कंपाइलर को सभी टेम्पलेट तर्कों के लिए एक मूल्य का पता लगाने में सक्षम होना चाहिए। जब आप टेम्पलेट कक्षाओं का उपयोग कर रहे हैं, तो यही कारण है कि आप आमतौर पर सभी टेम्पलेट तर्क निर्दिष्ट करते हैं। उदाहरण के लिए, आप vector x
नहीं कहें, बल्कि इसके बजाय vector<double> x
जैसे कुछ कहें। टेम्पलेट फ़ंक्शंस का उपयोग करते समय, अधिकांश समय संकलक तर्कों को समझ सकते हैं। उदाहरण के लिए, std::sort
उपयोग करने के लिए, तो आप सिर्फ
std::sort(v.begin(), v.end());
की तरह कुछ लेकिन, आप भी लिख सकता है
std::sort<vector<int>::iterator>(v.begin(), v.end());
अधिक स्पष्ट होने के लिए कहते हैं। लेकिन कभी-कभी, आपके पास एक टेम्पलेट फ़ंक्शन होता है जिसके लिए सभी तर्कों का पता नहीं लगाया जा सकता है।
template <unsigned parseFlags>
GenericDocument& Parse(const Ch* str) {
RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
GenericStringStream<Encoding> s(str);
return ParseStream<parseFlags>(s);
}
सूचना है कि parseFlags
टेम्पलेट पैरामीटर सिर्फ समारोह के तर्कों से निष्कर्ष निकाला नहीं जा सकता है: अपने उदाहरण में, हम इस किया है। नतीजतन, फ़ंक्शन को कॉल करने के लिए, आप टेम्पलेट पैरामीटर निर्दिष्ट करें, अन्यथा संकलक इसे समझ नहीं सकता है। यही कारण है कि आप
Parse<0>(myString);
यहाँ की तरह कुछ क्यों लिख करेंगे, 0 एक टेम्पलेट तर्क (संकलन समय पर हल हो गई), और myString
वास्तविक तर्क (रन-टाइम में हल हो गई है)।
आप वास्तव में ऐसे विधियां कर सकते हैं जो थोड़ा प्रकार के अनुमान और थोड़ा स्पष्ट प्रकार पैरामीटर को जोड़ते हैं। उदाहरण के लिए, बूस्ट में, lexical_cast
फ़ंक्शन है जो स्ट्रिंग प्रकारों से और उससे रूपांतरण कर सकता है। समारोह हस्ताक्षर एक स्ट्रिंग प्रकार के लिए एक गैर-स्ट्रिंग प्रकार से परिवर्तित करने के लिए यहां
template <typename Target, typename Source>
Target lexical_cast(const Source& arg);
है, यदि आप lexical_cast
फोन, संकलक पता लगा सकते हैं क्या Source
है, लेकिन यह कुछ संकेत के बिना Target
अनुमान नहीं कर सकते। lexical_cast
उपयोग करने के लिए है, इसलिए, आप की तरह
std::string myString = boost::lexical_cast<std::string>(toConvertToString);
कुछ अधिक आम तौर पर लिखना चाहते हैं, संकलक कहते हैं आप टेम्पलेट तर्क (वैकल्पिक 0) के कुछ संख्या निर्दिष्ट करने के लिए है, और यह बाकी अनुमान करने की कोशिश करेंगे कि। अगर यह कर सकता है, तो बढ़िया! यदि नहीं, तो यह संकलन-समय त्रुटि है। इस का उपयोग करना, यदि आप चाहें, तो आप
template <int IntArgument, typename TypeArgment>
void DoSomething(const TypeArgument& t) {
/* ... */
}
की तरह एक समारोह लिख सकता है इस फ़ंक्शन को कॉल करने के लिए, अगर आप इस तरह यह आह्वान करने के लिए होगा:
DoSomething<intArg>(otherArg);
यहाँ, इस वजह से आप काम करता है IntArgument
क्या संकलक स्पष्ट रूप से बताना है, लेकिन फिर संकलक को DoSomething
पर तर्क के प्रकार से घटा सकता है।
आशा है कि इससे मदद मिलती है!
संभावित डुप्लिकेट [नियमित पैरामीटर के बजाय गैर-प्रकार टेम्पलेट पैरामीटर का उपयोग करने का कारण?] (Http://stackoverflow.com/questions/7395700/reason-for-using-non-type-template-parameter-instead- ऑफ-नियमित-पैरामीटर) –
"गैर-प्रकार का टेम्पलेट पैरामीटर" देखें। –