2013-05-16 9 views
30

मैं टेम्पलेट तर्क के रूप में विभिन्न कंटेनर के साथ टेम्पलेट क्लास (एडाप्टर) कैसे घोषित कर सकता हूं? उदाहरण के लिए, मैं कक्षा की घोषणा करने की जरूरत है:टेम्पलेट कंटेनर के साथ टेम्पलेट क्लास

template<typename T, typename Container> 
class MyMultibyteString 
{ 
    Container buffer; 
    ... 
}; 

और मैं वेक्टर के आधार पर मेरे लिए यह चाहते हैं। इसे कैसे परिभाषित किया जाए? (किसी को इस तरह की घोषणा MyMultibyteString<int, vector<char>> लिखने से रोकने के लिए)।

इसके अलावा, कैसे इस तरह के निर्माण को लागू करने: कंटेनर के लिए टेम्पलेट तर्क गुजर बिना

MyMultibyteString<int, std::vector> mbs; 

उत्तर

59

आप टेम्पलेट टेम्पलेट मापदंडों उपयोग करना चाहिए:

template<typename T, template <typename, typename> class Container> 
//     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
class MyMultibyteString 
{ 
    Container<T, std::allocator<T>> buffer; 
    // ... 
}; 

यह आपको लिखने के लिए अनुमति होगी:

MyMultibyteString<int, std::vector> mbs; 

यहाँ एक संकलन live example है। ऊपर लिख हो सकता है की एक वैकल्पिक तरीका:

template<typename T, 
    template <typename, typename = std::allocator<T>> class Container> 
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
class MyMultibyteString 
{ 
    Container<T> buffer; // <== No more need to specify the second argument here 
    // ... 
}; 

और यहाँ इसी live example है।

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

उदाहरण के लिए, the class template std::vector accepts two template parameters (तत्व प्रकार और आवंटक प्रकार), हालांकि दूसरे के पास डिफ़ॉल्ट मान std::allocator<T> है। इस वजह से, आप नहीं लिखने सकता है:

template<typename T, template <typename> class Container> 
//        ^^^^^^^^ 
//        Notice: just one template parameter declared! 
class MyMultibyteString 
{ 
    Container<T> buffer; 
    // ... 
}; 

// ... 

MyMultibyteString<int, std::vector> mbs; // ERROR! 
//      ^^^^^^^^^^^ 
//      The std::vector class template accepts *two* 
//      template parameters (even though the second 
//      one has a default argument) 

इसका मतलब है कि आप एक एकल वर्ग टेम्पलेट है कि दोनों std::set और std::vector एक टेम्पलेट टेम्पलेट पैरामीटर के रूप में स्वीकार कर सकते हैं लिखने के लिए सक्षम नहीं होगा क्योंकि std::vector के विपरीत, the std::set class template accepts three template parameters

+0

क्या एक महान, पूरी तरह से जवाब। –

+0

@ स्कॉट जोन्स: खुशी है कि आपको यह उपयोगी लगता है :) –

+3

@ स्कॉट जोन्स आपके कथन के बारे में: 'इसका मतलब है कि आप एक एकल वर्ग टेम्पलेट लिखने में सक्षम नहीं होंगे जो std :: set और std :: vector' दोनों को स्वीकार कर सकता है: क्या होगा विविध टेम्पलेट समस्या हल करते हैं? http://stackoverflow.com/a/20499809/2436175 – Antonio

2

एक और दृष्टिकोण इस को हल करने के variadic टेम्पलेट्स का उपयोग करना है और जैसा कि ऊपर टिप्पणी में सुझाव दिया है कि के साथ आप किसी भी कंटेनर का उपयोग कर सकते हैं और यहां implemenation है:

template<template <typename... Args> class Container,typename... Types> 
class Test 
{ 
    public: 
    Container<Types...> test; 

}; 
int main() 
{ 
    Test<std::vector,int> t; 
    Test<std::set,std::string> p; 
    return 0; 
} 
संबंधित मुद्दे