c++ - टेम्पलेट्स में कीवर्ड 'टाइपनाम' और 'क्लास' का अंतर?


टेम्पलेट्स के लिए मैंने दोनों घोषणाओं को देखा है:

template < typename T >
template < class T >

क्या फर्क पड़ता है?

और उन कीवर्ड का वास्तव में निम्न उदाहरण में क्या मतलब है (टेम्पलेट्स के बारे में जर्मन विकिपीडिया लेख से लिया गया)?

template < template < typename, typename > class Container, typename Type >
class Example
{
     Container< Type, std::allocator < Type > > baz;
};

Answers


एक टेम्पलेट को निर्दिष्ट करने के मूल मामले में typename और class विनिमेय हैं:

template<class T>
class Foo
{
};

तथा

template<typename T>
class Foo
{
};

बराबर हैं

उन्होंने कहा कि, विशिष्ट मामलों में जहां typename और class बीच अंतर होता है।

पहले एक निर्भर प्रकारों के मामले में है typename का उपयोग घोषित करने के लिए किया जाता है जब आप एक नेस्टेड प्रकार को संदर्भित कर रहे हैं जो किसी अन्य टेम्पलेट पैरामीटर पर निर्भर करता है, जैसे कि इस उदाहरण में टाइप किए typename :

template<typename param_t>
class Foo
{
    typedef typename param_t::baz sub_t;
};

दूसरा, जिसे आप वास्तव में आपके प्रश्न में दिखाते हैं, यद्यपि आप इसे महसूस नहीं कर सकते हैं:

template < template < typename, typename > class Container, typename Type >

टेम्पलेट टेम्पलेट निर्दिष्ट करते समय, class कीवर्ड को जरूरी रूप में ऊपर वर्णित किया जाता है - इस मामले में typename साथ परस्पर विनिमय नहीं किया जा सकता (ध्यान दें: चूंकि सी ++ 17 दोनों इस मामले में कीवर्ड की अनुमति है)

किसी टेम्पलेट को स्पष्ट रूप से इन्स्तांत करते समय आपको class का भी उपयोग करना चाहिए:

template class Foo<int>;

मुझे यकीन है कि अन्य मामलों में मुझे याद है, लेकिन नीचे की रेखा यह है: ये दो कीवर्ड समकक्ष नहीं हैं, और ये कुछ सामान्य मामलों में जहां आपको एक या दूसरे का उपयोग करने की आवश्यकता है




टेम्पलेट पैरामीटर नाम देने के लिए, typename और class समकक्ष हैं। §14.1.2:

टेम्पलेट-पैरामीटर में वर्ग और टाइपनाम के बीच कोई शब्दार्थ अंतर नहीं है।

टेम्पलेट का उपयोग करते समय typename अन्य संदर्भ में संभव है - संकलक पर संकेत करने के लिए कि आप किसी निर्भर प्रकार का संदर्भ ले रहे हैं §14.6.2:

एक टेम्पलेट घोषणापत्र या परिभाषा में उपयोग किया जाने वाला नाम, और यह एक टेम्पलेट-पैरामीटर पर निर्भर होता है जिसे एक प्रकार का नाम नहीं माना जाता है, जब तक कि लागू नाम देखने में कोई प्रकार का नाम न मिले या नाम की खोजशब्द typename द्वारा योग्य हो।

उदाहरण:

typename some_template<T>::some_type

बिना typename गए कम्पाइलर को सामान्य तौर पर यह नहीं बता सकता कि आप किसी प्रकार की बात कर रहे हैं या नहीं।




हालांकि कोई तकनीकी अंतर नहीं है, मैंने देखा है कि ये दोनों दो अलग-अलग चीज़ों को दर्शाते थे।

एक टेम्पलेट के लिए जिसे किसी प्रकार के टी को स्वीकार करना चाहिए, जिसमें अंतर्निहित (जैसे कि सरणी)

template<typename T>
class Foo { ... }

एक टेम्पलेट के लिए जो केवल काम करेगा जहां टी एक वास्तविक वर्ग है

template<class T>
class Foo { ... }

लेकिन ध्यान रखें कि यह केवल एक शैली की बात है जो कुछ लोगों का उपयोग होता है। मानक द्वारा अनिवार्य नहीं है या कम्पाइलर द्वारा लागू




  1. कोई फर्क नहीं
  2. टेम्पलेट प्रकार पैरामीटर Container स्वयं दो प्रकार के पैरामीटर के साथ एक टेम्पलेट है।



स्निपेट का यह टुकड़ा सी ++ प्राइमर बुक से है। हालांकि मुझे यकीन है कि यह गलत है

प्रत्येक प्रकार के पैरामीटर को कीवर्ड श्रेणी या टाइपनाम से पहले होना चाहिए:

// error: must precede U with either typename or class
template <typename T, U> T calc(const T&, const U&);

इन खोजशब्दों का एक ही अर्थ है और एक टेम्पलेट पैरामीटर सूची के अंदर एक दूसरे का उपयोग किया जा सकता है। टेम्पलेट पैरामीटर सूची दोनों कीवर्ड का उपयोग कर सकती है:

// ok: no distinction between typename and class in a template parameter list
template <typename T, class U> calc (const T&, const U&);

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