2016-08-02 4 views
35

std::stack और std::queue उनके अंतर्निहित कंटेनर प्रकार के लिए टेम्पलेट टेम्पलेट पैरामीटर के बजाय प्रकार टेम्पलेट पैरामीटर का उपयोग क्यों करें?std :: stack टेम्पलेट टेम्पलेट पैरामीटर का उपयोग क्यों नहीं करता है?

अर्थात क्यों stack इस तरह घोषित किया जाता है:

template<typename T, typename Container = deque<T>> 
class stack; 

लेकिन यह पसंद नहीं:

template<typename T, template<typename> class Container = deque> 
class stack; 

?

+0

@CoryKramer यह प्रश्न लिंक किए गए प्रश्न का डुप्लिकेट नहीं है: लिंक किया गया प्रश्न पूछता है कि हमें टेम्पलेट/टाइपनाम को कहां रखना है, जबकि यह प्रश्न इस बात के बारे में है कि मौजूदा वर्ग ('डेक') का एक निश्चित इंटरफ़ेस क्यों है, एक वाक्य रचनात्मक सवाल के बारे में नहीं। – bennofs

+1

डिफ़ॉल्ट टेम्पलेट टेम्पलेट पैरामीटर के लिए भी काम करते हैं? – anatolyg

+1

@anatolyg हां, वे काम करते हैं। –

उत्तर

38

क्योंकि आम तौर पर std::vector have more than one template argument जैसे कंटेनर हैं। इसे टेम्पलेट होने की परवाह नहीं करते, आप हर प्रकार के कंटेनर का उपयोग करने की अनुमति देते हैं।

कैसे

पर

template<typename> class Container 

template<class T, class Allocator = std::allocator<T>> class vector; 

फिट आप इसे अपने stack में होता है के रूप में होगा? (संकेत: यह नहीं करता है!) आपको प्रत्येक नंबर और प्रकार के टेम्पलेट तर्क (प्रकार बनाम गैर-प्रकार) के लिए विशेष मामलों की आवश्यकता होगी, जो आप समर्थन करना चाहते हैं, जो मूर्खतापूर्ण है, क्योंकि ये आमतौर पर किसी का योगदान नहीं करते हैं एक साधारण

typename Container 

नोट करें कि वास्तविक टेम्पलेट तर्कों को प्राप्त करने के लिए उदाहरण के लिए अधिक जानकारी std::vector, आपके पास टाइप किए गए std::vector::value_type और std::vector::allocator_type हैं, इन प्रकारों को स्पष्ट रूप से उपलब्ध कराने की आवश्यकता को हटाकर जहां आप वास्तव में प्रकार का उपयोग करते हैं (यानी Containerstack)।

+1

ओच। मैंने सोचा कि यह टीटी निर्दिष्ट करने के बिना 'std :: stack ' लिखने में सक्षम होना अधिक सुविधाजनक होगा, लेकिन कंटेनर टेम्पलेट पैरामीटर पर प्रतिबंधों के बारे में नहीं सोचा था। – Hedede

+16

@ हेडडे उन कंटेनरों के बारे में सोचें जो टेम्पलेट्स से भी तत्काल नहीं हैं। अपने डिज़ाइन के साथ आप कुछ नहीं कर सकते जैसे 'std :: stack '। – TartanLlama

+2

यह "टेम्पलेट एजेंसियों के प्रत्येक _number_ के विशेष मामलों" से कहीं भी बदतर है, क्योंकि टेम्पलेट टेम्पलेट पैरामीटर में प्रकार और गैर-प्रकार के टेम्पलेट तर्कों का मिश्रण हो सकता है। अर्थात। न केवल आपके पास कंटेनर <टाइप 1, टाइप 2> 'हो सकता है, बल्कि 'कंटेनर ' भी हो सकता है। यह _exponentially_ बदतर बनाता है। – MSalters

17

संक्षेप में: क्योंकि टेम्पलेट टेम्पलेट पैरामीटर का उपयोग करना किसी भी फायदे के बिना एक प्रकार पैरामीटर का उपयोग करने से अधिक प्रतिबंधक * है।

* "प्रतिबंधक" से मेरा मतलब है कि आपको "सरल" प्रकार पैरामीटर के साथ एक ही परिणाम प्राप्त करने के लिए एक और जटिल सामग्री की आवश्यकता हो सकती है।

कोई लाभ क्यों नहीं है?

आपका std::stack शायद इस तरह एक विशेषता है:

template <typename T, typename Container> 
struct stack { 
    Container container; 
}; 

आप Container की जगह तो एक टेम्पलेट टेम्पलेट पैरामीटर द्वारा, तुम क्यों प्राप्त होगा?

template <typename T, template <typename...> class Container> 
struct stack { 
    Container<T> container; 
}; 

आप T (Container<T>) के लिए केवल एक बार और केवल Container instantiating कर रहे हैं, इसलिए कोई टेम्पलेट टेम्पलेट पैरामीटर के लिए कोई लाभ

यह अधिक प्रतिबंधक क्यों है?

template <typename T, template <typename....> class Container> 
struct stack { 
    Container<T> container; 
}; 

stack<int, std::vector> // Ok, will use std::vector<int, std::allocator<int>> 

लेकिन क्या:

template <typename T, template <typename> class Container> 
struct stack; 

stack<int, std::vector> // Error: std::vector takes two template arguments 

शायद तुम variadic टेम्पलेट का उपयोग कर सकते हैं:

एक टेम्पलेट टेम्पलेट पैरामीटर के साथ

, आप std::stack करने के लिए एक है जो एक ही हस्ताक्षर बेनकाब जैसे टेम्पलेट, पारित करने के लिए है अगर मैं मानक std::allocator<int> का उपयोग नहीं करना चाहता हूं?

template <typename T, 
      template <typename....> class Container = std::vector, 
      typename Allocator = std::allocator<T>> 
struct stack { 
    Container<T, Allocator> container; 
}; 

stack<int, std::vector, MyAllocator> // Ok... 

इसमें कुछ समय गंदा होता जा रहा है ... क्या होगा यदि मैं कि 3/4/एन पैरामीटर लेता है अपने ही कंटेनर टेम्पलेट का उपयोग करना चाहते हैं?

template <typename T, 
      template <typename... > class Container = std::vector, 
      typename ...Args> 
struct stack { 
    Container<T, Args...> container; 
}; 

stack<int, MyTemplate, MyParam1, MyParam2> // Ok... 

लेकिन, अगर मैं एक गैर-टेम्पलेट वाले कंटेनर का उपयोग करना चाहता हूं तो क्या होगा?

struct foo { }; 
struct foo_container{ }; 

stack<foo, foo_container> // Error! 

template <typename... > 
using foo_container_template = foo_container; 

stack<foo, foo_container_template> // Ok... 
एक प्रकार पैरामीटर के साथ

ऐसी कोई मुद्दों हैं:

stack<int> 
stack<int, std::vector<int, MyAllocator<int>> 
stack<int, MyTemplate<int, MyParam1, MyParam2>> 
stack<foo, foo_container> 

वहाँ अन्य मामलों में इस तरह का एक मिश्रण को स्वीकार टेम्पलेट का उपयोग कर के रूप में जो टेम्पलेट टेम्पलेट पैरामीटर साथ काम नहीं करते हैं विशिष्ट ऑर्डर में प्रकार और गैर-प्रकार पैरामीटर, जिसके लिए आप विविध टेम्पलेट टेम्पलेट पैरामीटर बना सकते हैं, यहां तक ​​कि वैरिएडिक टेम्पलेट्स का उपयोग भी कर सकते हैं।

+0

मुझे नहीं लगता कि यह सही जवाब है: सही कारण के लिए अन्य उत्तरों देखें। –

+0

@ कोनराड्रूडॉल्फ सी ++ 11 में, आप 'टेम्पलेट <टाइपनाम ...> कक्षा कंटेनर 'का उपयोग कर सकते हैं और यह टेम्पलेट टेम्पलेट पैरामीटर के साथ काम करेगा। – Holt

+0

@ होल्ट ट्रू, काफी मेला। उस ने कहा, पाठ्यक्रम का इंटरफेस सी ++ 11 की भविष्यवाणी करता है, और इंटरफ़ेस डिज़ाइन के लिए * कारण * प्री -11 सी ++ के तकनीकी प्रतिबंध पहले और सबसे महत्वपूर्ण है। –

13

Because it doesn’t compile:

std::deque प्रकार की नहीं है

template <typename T> class std::deque 

यह प्रकार का है

template<class T, class Alloc> class std::deque 

निश्चित रूप से यह एक अधिक सामान्य समस्या है: भले ही हम Alloc प्रदान करने के लिए थे हमारे stack कक्षा टेम्पलेट में टेम्पलेट पैरामीटर, कक्षा अब केवल उन कंटेनरों के साथ काम करेगी जो पूर्व में हैं वास्तव में दो प्रकार के टेम्पलेट तर्क। यह एक अनुचित प्रतिबंध है।

+0

@ होल्ट यहां टाइप-पैरामीटर के बारे में एक अच्छा जवाब था, जिसमें 'स्ट्रक्चर फू' जैसे गैर-टेम्पलेट कंटेनर का उपयोग करने की अनुमति थी; संरचना foo_container; foo_stack = std :: stack 'का उपयोग कर। लेकिन आधुनिक मानकों के बारे में बात करते समय, 'कंटेनर ' टेम्पलेट 'ऐसे कंटेनरों के उपयोग की अनुमति देगा? यानी, क्या कोई टेम्पलेट पैरामीटर वाले सरल वर्ग में भिन्नता टेम्पलेट "कम" हो सकता है? – Artalus

+0

@ आर्टलस अच्छा सवाल। नहीं, यह नहीं कर सकता। रास्ते में, उनके जवाब का बैक अप। –

18

टेम्पलेट टेम्पलेट पैरामीटर का उपयोग उन प्रकारों को प्रतिबंधित करेगा जिन्हें आप अंतर्निहित कंटेनर के रूप में उपयोग कर सकते हैं जो समान टेम्पलेट हस्ताक्षर का पर्दाफाश करते हैं। यह फ़ॉर्म मनमाने ढंग से प्रकार की अनुमति देता है जब तक वे अपेक्षित इंटरफ़ेस का समर्थन करते हैं।

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